2010-07-11 10 views
3

Je suis avec un fond de génie mécanique, mais je suis intéressé à apprendre la bonne pratique de génie logiciel avec Ada. J'ai quelques questions.Génie logiciel avec Ada: stubs; unités séparées et de compilation

Q1. Si je comprends bien alors quelqu'un peut simplement écrire un fichier de spécification de paquet (annonces), le compiler, puis compiler le programme principal qui utilise le paquet. Plus tard, quand on sait ce qu'il faut inclure dans le corps du paquet, celui-ci peut être écrit et compilé. Ensuite, le programme principal peut maintenant être exécuté. J'ai essayé cela et je voudrais confirmer que c'est une bonne pratique.

Q2. Ma deuxième question concerne les souches (sous-unités) et l'utilisation de SEPARATE. Dire que j'ai un programme principal comme suit:

WITH Ada.Float_Text_IO; 
    WITH Ada.Text_IO; 
    WITH Ada.Integer_Text_IO; 

    PROCEDURE TEST2 IS 
    A,B  : FLOAT; 
    N  : INTEGER; 

    PROCEDURE INPUT(A,B: OUT FLOAT; N: OUT INTEGER) IS SEPARATE; 

    BEGIN -- main program 
     INPUT(A,B,N); 
     Ada.Float_Text_IO.Put(Item => A); 
     Ada.Text_IO.New_line; 
     Ada.Integer_Text_IO.Put(Item => N); 
    END TEST2; 

J'ai la procédure entrée dans un fichier séparé:

separate(TEST2) 
PROCEDURE INPUT(A,B: OUT FLOAT; N: OUT INTEGER) IS 
    BEGIN 
     Ada.Float_Text_IO.Get(Item => A); 
     Ada.Text_IO.New_line; 
     Ada.Float_Text_IO.Get(Item => B); 
     Ada.Text_IO.New_line; 
     Ada.Integer_Text_IO.Get(Item => N); 
    END INPUT; 

Mes questions:

a) AdaGIDE me suggère de sauver le la Fichier de procédure INPUT en tant que input.adb. Mais sur la compilation du principal test2 du programme, je reçois l'avertissement:

warning: subunit "TEST2.INPUT" in file "test2-input.adb" not found 
cannot generate code for file test2.adb (missing subunits) 

Pour AdaGIDE, ce qui est plus d'une erreur que les avertissements ci-dessus viennent avant que le message:

Compiling... 
Done--error detected 

Je rebaptisés la fichier input.adb à test2-input.adb comme m'a été suggéré par AdaGIDE lors de la compilation. Maintenant, en compilant le fichier principal, je n'ai aucun avertissement. Ma question est maintenant s'il est autorisé à écrire

PROCEDURE INPUT(A,B: OUT FLOAT; N: OUT INTEGER) IS 

comme je l'ai fait dans le fichier sous-unité test2-input.adb ou est-il préférable d'écrire un terme plus descriptif comme

PROCEDURE TEST2-INPUT(A,B: OUT FLOAT; N: OUT INTEGER) IS 

souligner cette entrée de procédure a une procédure parent test2? Cette idée découle d'AdaGIDE qui m'indique à propos de test2-input.adb comme je l'ai mentionné plus haut.

b) Ma question suivante:

Si je comprends bien l'ordre de compilation, alors je devrais compiler le fichier principal test2.adb d'abord, puis le talon test2-input.adb. Sur la compilation du stub je reçois le message d'erreur:

cannot generate code for file test2-input.adb (subunit) 
Done--error detected 

Cependant, je peux maintenant la liaison et ne liant pour test2.adb et exécuter le programme.

Je voudrais savoir si j'ai mal fait en essayant de compiler le stub test2-input.adb ou ne devrait-il pas être compilé?

Q3. Quelle est l'utilité d'avoir des sous-unités? Est-ce juste pour casser un grand programme en plus petites parties? Je sais qu'une erreur survient si l'on ne place aucune instruction entre BEGIN et END dans la sous-unité. Donc, cela signifie que l'on doit toujours mettre une déclaration là-bas. Et si l'on veut écrire les déclarations plus tard, on peut toujours mettre une instruction NULL entre BEGIN et END dans la sous-unité et revenir à ce dernier à un moment ultérieur. Est-ce la façon dont le génie logiciel est fait dans la pratique?

Merci beaucoup ...

+0

Je suis curieux de connaître le choix d'Ada. Était-ce basé sur les exigences du travail/client? Les statistiques sur la langue (par exemple, http://www.langpop.com/) indiquent que ce n'est pas vraiment la langue de choix pour la plupart des projets. –

+0

Eh bien, je connais quelques langages comme Basic, Pascal, C et Matlab (si celui-ci peut être considéré comme un langage de programmation). J'ai décidé d'apprendre Ada comme étant un langage fortement typé, il aide à éviter les erreurs qui peuvent facilement se glisser dans d'autres langues que j'ai apprises auparavant. Et Ada fait la promotion de la bonne pratique de l'ingénierie logicielle. Je ne peux pas trouver un meilleur langage de programmation. C peut être plus rapide mais peut-être plus difficile à maintenir que Ada verbeux. Je choisis Ada non pas à cause de la vitesse d'exécution mais je veux des résultats précis et ses unités de compilation séparées aident beaucoup lors du développement d'un grand programme. – yCalleecharan

+0

@yCalleecharan: Vous avez une excellente compréhension des avantages et des contributions d'Ada pour la qualité et la productivité des logiciels. Et en fait, sa performance n'est pas trop mal non plus: http://groups.google.com/group/comp.lang.ada/browse_thread/thread/847751a7e7aa6234?pli=1 –

Répondre

7

Q1: C'est excellente pratique. En traitant la spécification de paquet comme spécification, vous pouvez la fournir à d'autres développeurs afin qu'ils sachent comment interfacer avec votre code. Q2: Je crois qu'AdaGIDE utilise réellement le compilateur GNAT pour toute la compilation, c'est donc GNAT qui est en charge des noms de fichiers acceptables. (Ceci peut être configuré, mais à moins que vous ayez une raison très convaincante de le faire, il est beaucoup plus simple de suivre les conventions de nommage de GNAT/AdaGIDE.) Plus pertinent à votre question, cependant, il n'y a aucune raison d'inclure le parent unité dans le nom de l'unité séparée. Mais voir la réponse à Q3 ...

Q3: Les sous-unités ont été introduites avec la première version d'Ada-Ada 83 - en partie pour aider à moduler le code, et permettre un développement et une compilation différés. Cependant, la pratique de développement de logiciels Ada a quasiment abandonné l'utilisation de sous-unités, tous les corps de procédure/fonction/tâche/etc sont simplement tous maintenus dans le corps du paquet. Ils sont encore utilisés dans certains domaines, comme si une version de sous-programme spécifique à la plate-forme peut être nécessaire, mais pour la plupart, ils sont rarement utilisés. Il laisse moins de fichiers à garder en mémoire et conserve le code d'implémentation d'un paquet tous ensemble. Donc, je vous recommande fortement de simplement ignorer les capacités des sous-unités et de placer tout votre code d'implémentation dans les corps des paquets.

+0

Merci pour les idées spécialement pour Q3. J'utilise AdaGIDE avec le compilateur AdaCore GNAT. 1 vote jusqu'à. – yCalleecharan

4

Il est assez normal de diviser un problème en composants (packages), chacun prenant en charge un aspect différent. Si vous avez appris Ada, il serait normal d'écrire les spécifications des paquets en premier, de faire valoir (peut-être avec vous-même) pourquoi c'est la bonne conception, puis de les implémenter. Et ce serait normal, je pense, dans n'importe quel langage qui prend en charge les spécifications et les corps - par exemple, C.

Personnellement, je vérifierais les compilations au fur et à mesure, juste pour m'assurer que je ne fais rien de stupide. En ce qui concerne les séparations - une (pas très bonne) raison est de réduire l'encombrement, d'arrêter l'unité trop longtemps. Une autre raison (pour un générateur de code que j'ai écrit) était que le générateur de code n'avait pas à se soucier de préserver le code manuscrit des développeurs dans le modèle UML; tous les corps de code étaient séparés. Un troisième pourrait être pour une implémentation dépendant de l'environnement (par exemple, Windows vs Unix), où vous laisseriez le compilateur voir une version différente du corps séparé pour chaque environnement (les gens utilisent normalement des paquets de bibliothèque pour cela, cependant).

Compilateurs ont leurs propres règles sur les noms de fichiers, et ce que les choses commande peuvent être compilés. Lorsque GNAT voit

procedure Foo is 
    procedure Bar is separate; 

il attend de trouver le corps de Foo dans un fichier nommé foo.adb et le corps de Bar à foo-bar.adb (vous peut, je crois, le dire différent - gnatmake paquet de Naming - mais il ne vaut probablement pas la peine). Il est préférable d'aller avec le flux ici;

separate (Foo) 
procedure Bar is 

est suffisamment clair.

Vous pouvez compiler foo-bar.adb, et cela fera une analyse complète et attraper presque toutes les erreurs dans le code; mais GNAT ne peut pas générer de code pour cela seul. Au lieu de cela, lorsque vous compilez foo.adb, il inclut tous les corps distincts dans le fichier objet généré. Ce n'est certainement pas mauvais pour ce faire.Avec GNAT, vous n'avez pas à vous soucier de l'ordre de compilation, vous pouvez compiler dans l'ordre que vous voulez. Mais il est préférable d'utiliser gnatmake et laissez l'ordinateur prendre la pression!

+0

Merci pour tous les commentaires précieux. Je veux juste confirmer à nouveau que compiler un stub sur son propre va générer un message d'erreur comme je l'ai eu mais c'est ok. L'important est bien sûr de compiler le programme principal et de ne pas avoir d'erreurs alors. 1 vote jusqu'à. – yCalleecharan

+0

Simon, votre réponse est en effet très utile mais la réponse de Marc est un peu plus complète que la vôtre. C'est pourquoi j'accepte sa réponse. J'espère que ça va avec toi. Je vous ai également donné 1 vote pour m'aider, un novice, pour apprendre une meilleure pratique de génie logiciel. – yCalleecharan

+0

@yCalleecharan - pas de problème! –

1

Vous pouvez en effet travailler de la façon dont vous le décrivez, sauf bien sûr que votre programme ne liera pas tant que tous les corps de paquet n'auront pas une implémentation quelconque. Pour cette raison, je pense qu'il est normal d'écrire un corps de paquet factice avec toutes les procédures mises en œuvre comme:

begin 
    null; 
end; 

Et toutes les fonctions comme quelque chose comme mis en œuvre:

begin 
    return The_Return_Type'first; --' 
end; 

... Pour ce qui est sépare Je ne les aime pas. Pour moi, je préfèrerais suivre la règle selon laquelle tout le code d'un paquet est dans son corps. Les séparations sont marginalement acceptables si pour une raison quelconque la routine est énorme, mais dans ce cas une meilleure solution est presque toujours de refactoriser votre code. Donc, chaque fois que j'en vois un, c'est un gros drapeau rouge. En ce qui concerne le nom de fichier, c'est un problème de gnat, pas un problème Ada. Gnat a pris la position inhabituelle pour un compilateur que le nom du contenu d'un fichier dicte ce que le fichier lui-même doit être nommé. Il y a probablement d'autres compilateurs dans le monde qui font cela, mais je n'ai pas encore trouvé un codeur sur 30 ans.

+0

Merci pour les super commentaires. 1 vote jusqu'à. – yCalleecharan

Questions connexes