Programmation automatique: écrire du code qui écrit du code [fermé]


105

Après avoir lu le livre The Pragmatic Programmer , l'un des arguments que j'ai trouvé le plus intéressant était "écrivez du code qui écrit du code".

J'ai essayé de chercher sur le net des explications supplémentaires ou des articles à ce sujet, et bien que j'ai trouvé de bons articles sur le sujet, je n'ai toujours pas trouvé d'implémentation de code spécifique ni de bons exemples.

Je pense que ce n’est toujours pas un argument si courant, quelque chose qui manque de documentation ou qui n’est pas adopté par tellement de gens, et j'aimerais en savoir plus à ce sujet.

Que pensez-vous du sujet? Est-ce quelque chose qui va vraiment augmenter votre productivité? Quelles sont les bonnes ressources sur le sujet, parmi les livres, les blogs, les diaporamas, etc.?


Quelques exemples de code seraient grandement appréciés pour me permettre de mieux comprendre sa mise en œuvre.


Voici la page wiki sur le sujet avec diverses techniques de programmation pertinentes, telles que la méta-programmation, la programmation générative et la génération de code.


32
J'ai écrit une fois le code qui a écrit le code qui a écrit le code ... :)
Benjol

9
@Benjol: écrivez-vous en Lisp?
Compman

11
De plus, les langages côté serveur le font tout le temps en générant HTML, CSS et JavaScript. Vous pourriez avoir un script côté serveur qui crée un script côté serveur qui crée du HTML avec JavaScript qui crée plus de HTML, et personne ne voudra en prendre conscience à cause de sa fréquence .
zzzzBov

8
Si vous ne l'avez pas déjà fait, consultez cette série d'articles d'IBM developerWorks: " L'art de la métaprogrammation ", parties 1 , 2 et 3 .
John Tobler

3
AtomWeaver ( atomweaver.com ) est un bon exemple de programmation automatique: vous créez d’abord des mini-programmes réutilisables dans Lua. Ensuite, vous modélisez votre système en réutilisant ces actifs. AtomWeaver tisse ensuite un programme Lua contenant vos "mini-générateurs" pour générer le code source final du système. Vous pouvez ensuite modifier votre modèle et le générer à nouveau.
Rui Curado

Réponses:


49

Dans le monde Lisp, il est assez courant de voir le code qui écrit le code qui écrit le code (et ainsi de suite). Ainsi, tout projet Lisp ou Scheme de taille décente sera un bon exemple de code. Je vous recommande de regarder le compilateur Racket et les sources d'exécution, ainsi que Bigloo , leurs bibliothèques sont tout simplement géniales.

En ce qui concerne la productivité: j'utilise la métaprogrammation comme technique dominante dans la quasi-totalité de mes travaux de développement, ce qui est clairement très utile, à la fois en réduisant la taille du code et en améliorant sa lisibilité. La clé réside dans l'utilisation de langages spécifiques à un domaine , et la métaprogrammation est l'un des moyens les plus efficaces de les implémenter.


67

Je préfère aller un peu plus loin et, au lieu d'écrire du code qui écrit du code, écrire du code qui génère des objets, des méthodes, des fonctions. Ceci peut être réalisé avec les macros Lisp ou les capacités de modification de programme dynamique Ruby, par exemple.

La petite différence est que vous ne vous arrêtez pas aux fichiers source générés automatiquement. Habituellement, ces fichiers ne sont pas lisibles par l'homme et ne peuvent pas être modifiés. Pourquoi s'en préoccuper? Je n'aime pas l'idée d'augmenter ma base de code avec quelque chose que je ne peux pas contrôler.

Un livre que j'ai aimé lire sur le sujet était Metaprogramming Ruby (si vous connaissez le langage Ruby)


Modifier après la question suivante dans le commentaire:

Pourquoi devrait-il être utile s'il me reste à coder le code générateur? Devrais-je écrire un code capable de générer différentes choses en fonction de la saisie de l'utilisateur, afin de pouvoir le réutiliser encore et encore?

Tout d'abord, la métaprogrammation n'est pas un objectif, mais un outil. N'utilisez pas de métaprogrammation car "c'est cool" ou "X disait que chaque développeur devrait l'utiliser".

Je pense qu’une bonne raison d’utiliser la métaprogrammation est de généraliser un motif courant (motif répétitif) que vous avez trouvé dans votre code et qu’aucune autre technique de programmation habituelle (héritage, motifs de conception, etc.) ne peut atteindre.

Comme l'a dit Jordan , un cas d'utilisation typique est la gestion de base de données et l'ORM (Object Relation Mapping). Encore une fois, dans Ruby, vous devriez regarder ActiveRecord qui est un excellent exemple de métaprogrammation appliquée à ORM.

Comme note finale:

Ne pensez pas "Je veux appliquer la métaprogrammation, où pourrais-je l'appliquer dans mon code?".

Pensez "Je vois ce motif qui se répète partout dans mon code, je ne peux pas trouver un moyen de le reformater pour le transformer en quelque chose de plus petit et de plus réutilisable. Peut-être que la métaprogrammation pourrait m'aider?"


3
@Jose: Le plus souvent, vous générez du code via des modèles. Il y a apache (N-) vélocité par exemple ou les modèles de Visual Studio T4. Ensuite, vous avez juste un programme qui alimente les métadonnées dans vos modèles et crée de nouveaux fichiers à partir de là. C'est assez facile et je le fais tout le temps pour générer des squelettes d'interface utilisateur, des entités, etc.
Falcon

2
@Jose Faeti, examinez de plus près les macros Lisp (ou Clojure ou Nemerle, selon les préférences de votre plate-forme).
SK-logic

1
J'ajouterais que la métaprogrammation peut remplacer certains modèles, tels que politique ou état, mais sans coût d'exécution. Cela concerne non seulement les problèmes qui ne peuvent pas être résolus avec une refactorisation commune, mais constitue parfois une meilleure alternative.
deadalnix

1
@ Jose Faeti: Je vois que vous connaissez un peu de Python. Il a également des capacités de métaprogrammation, bien que je ne les aie pas vraiment utilisées. Jetez un coup d'oeil à Dangerously Advanced Python PDF
Kit

3
@ Falcon: IMO c'est le pire moyen de générer du code; c'est une solution très médiocre pour les langues sans installation de méta-programmation intégrée. Au lieu de générer Java ou C #, il serait préférable d'écrire ce code dans un langage JVM ou .NET de niveau supérieur.
kevin cline

19

Mieux encore, utilisez le code écrit par quelqu'un d'autre qui écrit votre code pour vous.

L'automatisation du code est généralement bonne pour les ORM et autres codes d'interaction de base de données, et bien sûr pour la création de code répétitif mais similaire.

Bien sûr, si vous construisez beaucoup de classes similaires, vous auriez peut-être pu accomplir la même chose dans un langage dynamique beaucoup plus tôt, mais je m'éloigne du sujet.

Cela concerne beaucoup de gens, même si vous trouverez souvent le logiciel étiqueté comme générateur de code.

Consultez des entreprises et des produits tels que CodeSmith et MyGeneration, ou parcourez cet article de Wikipedia: http://fr.wikipedia.org/wiki/Comparison_de_code_generation_tools


6
Ce n'est pas mieux. Votre précieux code, si propre, ne peut pas être correctement géré par l'outil de génération de code d'un autre type, car ce dernier ne connaît rien de vos détails. L'utilisation la plus productive de la métaprogrammation consiste à implémenter des langages spécifiques à un domaine - et, comme leur nom l'indique, ils sont spécifiques à votre domaine même de problème, ils ne peuvent être implémentés que par vous.
SK-logic

@ SK-logic: qu'en est-il du code généré par ORM? Il est généré par un autre outil / bibliothèque et répond toujours à de nombreux besoins du projet.
David

@ David, pour être honnête, je ne suis pas tout à fait convaincu par les ORM génériques. J'avais tellement de problèmes avec eux dans le passé, ayant plutôt recours à la mise en place de mes propres petits ORM spécifiques.
SK-logic

1
@ Jordan, tous ces outils sont trop spécifiques (et pire encore - basés sur du texte , c’est-à-dire inférieurs par conception). Je parle plutôt de la métaprogrammation appropriée.
SK-logic

1
@ AtillaOzgur, ils peuvent être "très bons", c'est vrai. Mais ils ne sont pas meilleurs que les eDSL. La génération de code autonome est évidemment beaucoup plus limitée et beaucoup moins flexible que la métaprogrammation macro.
SK-logic

16

Un des exemples classiques est Lex et Yacc. Leur objectif principal est d’éviter la corvée d’écrire un type d’analyseur. En cours de route, ils accélèrent considérablement la construction d’analyseurs complexes contenant de nombreuses règles et de nombreux états, et ils évitent également toutes les erreurs de surprise commises par les utilisateurs qui les utilisent.

C’est aussi l’idée derrière c, qui est un outil pour écrire assembleur. La même chose vaut pour n'importe quelle langue de haut niveau que vous souhaitez nommer. Pour les outils qui écrivent du code pour vous, il existe quelques paradigmes simples.

Un IDE approprié aide à fournir une documentation à portée de main, une complétion automatique intelligente et des extraits de code. Les IDE incluent également divers modèles, vous n'avez donc pas besoin de démarrer un programme à partir de zéro. Il existe des programmes pour prendre un diagramme uml et brouiller les cours dans un langage de haut niveau.

Enfin, vous pouvez écrire vos propres outils de génération de code dans votre ensemble de problèmes. C'est ainsi que Lex et Yacc ont commencé. Tout type de langue spécifique à un domaine existe précisément pour cette raison. Vous créez des blocs de construction décrivant votre solution sous forme de code plus facile à comprendre, comprenant des activités courantes ou des sections compliquées à l'aide de commandes simples. Vous ne cherchez pas une solution à chaque problème, mais une définition plus facile du problème spécifique auquel vous faites face.

En un sens, tout ce que vous faites au-dessus de la couche binaire est l’automatisation du code.


C'est une très belle vue. Dans l’ensemble, les programmeurs essaient une des nombreuses méthodes qu’ils tentent d’utiliser pour faciliter leurs opérations et qui se concentrent sur un niveau de codage supérieur, au lieu des détails du code de syntaxe.
Jose Faeti

1
@Jose Faeti L'article de wikipedia en.wikipedia.org/wiki/Automatic_programming contient des liens vers différents outils, si vous souhaitez en savoir plus. Je suggèrerais également de lire sur Lex et Yacc, car il existe un peu plus de documentation et de description pour ceux-ci.
Spencer Rathbun

Dans des langages suffisamment puissants (par exemple, C ++ par opposition à C), des outils externes tels que lex et yacc sont inutiles.
kevin cline

YACC n'écrit pas "aucun type d'analyseur". Il écrit un type spécifique d’analyseur (LALR) qui est très difficile à obtenir sans aide automatisée. Il existe un autre type d’analyseur (descente récursive) qui est beaucoup plus facile à écrire et à comprendre, et donc plus facile à lire et à comprendre ce qui se passe.
Mason Wheeler

@MasonWheeler Le type d'analyseur faisait référence aux grammaires que l'on peut créer pour résoudre des problèmes, dans un sens large et non exact. En le lisant un an plus tard, ce n’est pas aussi clair que je l’aurais souhaité. Je ne suis pas sûr d'être d'accord avec vous sur le fait que les analyseurs syntaxiques LL (*) sont plus faciles à écrire et à utiliser.
Spencer Rathbun

13

Métaprogrammation

La métaprogrammation est une technique controversée dans de nombreux magasins. La raison en est que, comme tout outil puissant, l'aide ou le mal est d'une ampleur considérable.

Avantages

  • Plus expressif, moins de code à écrire et à maintenir (souvent d'un ordre de grandeur ou plus)
  • Cohérence, comportement plus cohérent sur la classe de problèmes que vous résolvez avec le code
  • Productivité, moins de code pour une solution à un plus grand espace de problèmes

Les inconvénients

  • Complexité, cela peut être très compliqué même s'il y a moins de code
  • La sécurité, parfois la sécurité de type et l'analyse statique en général seront sacrifiées
  • Les bugs affectent plus, les petites erreurs auront un impact plus important

Je suis un grand fan de métaprogrammation, mais je le fais depuis longtemps. Pour moi, le compromis entre une taille de code réduite et un comportement cohérent compense largement les risques. Moins de code signifie moins de bugs, moins de code à maintenir, et je peux généralement ajouter de grandes fonctionnalités très rapidement.

Cependant, cela ne signifie pas que je pense que tous les programmeurs devraient y participer. J'ai vu et dû résoudre de gros problèmes créés par la métaprogrammation. Habituellement, c'est à partir de personnes qui ne comprennent pas le concept et qui ont tenté d'étendre les fonctionnalités ou simplement de corriger un bogue. Cela nécessite un état d'esprit particulier qui est au moins axé sur les détails. La question d'utiliser des techniques de métaprogrammation devrait être une décision d'équipe . Si vous avez des membres de l'équipe qui ne comprennent pas, qui n'ont pas le tempérament, ou qui sont juste contre, aucune équipe ne devrait utiliser la métaprogrammation.


Merci pour les considérations utiles! Pourriez-vous me suggérer une tâche très simple et élémentaire que je pourrai mettre en œuvre à l'aide de la métaprogrammation, ce qui me fera gagner du temps par rapport au codage normal, un petit exemple de code?
Jose Faeti

haha me rappelle une erreur que j'ai eue il y a plusieurs années avec GCC. 162 lignes pour mettre le message d'erreur sur mon écran. Métaprogrammation récursive FTW!
deadalnix

6
La complexité de la métaprogrammation est fortement surestimée. Il n’ya absolument rien de compliqué, du moment que vous utilisez les bons outils. Et les DSL sont beaucoup plus faciles à déboguer et à maintenir que le code standard standard. De plus, je ne comprends pas pourquoi on devrait sacrifier la sécurité de type - c'est exactement le contraire, les DSL peuvent également avoir des systèmes de type spécifiques à un domaine et très efficaces.
SK-logic

2
@ SK-logic: toutes les langues ne supportent pas bien la métaprogrammation. Alors parfois, des choses comme la sécurité de type sont sacrifiées (ie. C) . La métaprogrammation ne concerne pas seulement les DSL. Cela inclut des choses comme la programmation de style d'expédition, les génériques, le currying, l'inspection d'objets, l'application dynamique, etc. En ce qui concerne la complexité, je pense qu'il est facile pour nous (personnes ayant une expérience de la métaprogrammation) de dire que ce n'est pas compliqué. J'ai vu d'autres difficultés à comprendre tous les cas dans lesquels le code sera exécuté. Cela dépend principalement de leur expérience et de la technique utilisée.
dietbuddha

@dietbuddha, pourriez-vous préciser, pourquoi un seul type de sécurité doit-il sacrifier la sécurité de son propre DSL, quelle que soit la façon dont il est mis en œuvre? Vous pouvez écrire un interpréteur ad hoc en C pur avec un système de type fort (voir Hugs par exemple). Vous pouvez écrire un générateur de code ciblant C qui effectue lui-même toutes les vérifications de frappe, sans s'appuyer sur le système de type de langue cible. Pour la complexité: la plupart des gens le font de manière inutilement complexe, alors que toutes les mêmes méthodologies de conception peuvent être appliquées à la génération de code comme dans la programmation "normale". Presque aucune nouvelle connaissance n'est requise.
SK-logic

9

La plupart du code écrit du code. Par exemple, le code php aide à écrire du code HTML. La bibliothèque php pdo aide à écrire des appels SQL. Les fonctions d'E / S sur fichier écrivent du code pour communiquer avec le système d'exploitation. Même un appel de fonction normal est une référence à un autre bloc de code qui est exécuté. Donc, vos appels de fonctions écrivent du code.

En termes généraux, on peut considérer l'informatique comme une écriture de codes qui écrivent des codes de manière récursive pour former une pile qui se termine lorsqu'elle se heurte à la réalité physique des codes câblés dans du matériel.


3
Je n'appellerais pas HTML un langage de programmation. C'est une syntaxe pour les documents
Simon Bergot Le

3
@ Simon c'est un point intéressant. Il existe toute une variété de pouvoirs expressifs pour les différents codes que nous utilisons. Le code peut écrire dans une langue plus faible, une langue plus forte ou sa propre langue.
Ben Haley

5

Comment vous faites cela varie en fonction de vos exigences. En supposant que vous utilisez la génération de code statique, vous pouvez écrire toute l'infrastructure vous-même ou un générateur existant tel que CodeSmith ou MyGeneration. Pour les utiliser, il vous suffit d'écrire les modèles requis.

Mon dernier projet impliquant ceci était quelques écrans de base ASP.NET CRUD (la génération de code est bonne pour cela). Le processus a défini des entités sous forme de métadonnées dans des fichiers XML. Rédigez des modèles pour couvrir les différents artefacts requis (classes d’entités, référentiels, classes de service, contrôles asp.net, pages asp.net, etc.). Exécutez le processus de génération et appelez la sortie.

Lors de la rédaction des modèles, il existe des frais généraux, mais ils peuvent être réutilisés pour des projets similaires ultérieurs. De même, les modifications apportées aux données sous-jacentes sont gérées en modifiant les métadonnées et en réexécutant la génération, ce qui simplifie et accélère la mise en œuvre des modifications.

En ce qui concerne les tests. Puisqu'il s'agit d'un système basé sur des modèles, vous devrez passer un certain temps à valider initialement la sortie du processus. Si votre modèle est incorrect, toutes les sorties de ce modèle seront également erronées. Une fois que cela vous convient, vous pouvez également utiliser les générateurs de code pour créer des tests de base à partir des métadonnées xml, que vous pouvez ensuite étendre pour couvrir des cas particuliers. Cependant, rappelez-vous que vous aurez peut-être encore besoin de tests de code pour tenir compte de choses spécifiques. La génération de code réduit votre travail, mais ne l'élimine pas complètement.


5

Dans notre entreprise, nous utilisons des outils qui génèrent des classes C ++ ou C # avec des données téléchargées depuis Internet. Ces classes sont des conteneurs de données et contiennent un grand nombre d'objets dans des listes.


Quelque chose comme les extraits de code trouvés dans certains IDE comme Visual Studio par exemple?
Jose Faeti

@Jose Notre outil est juste une application pour convertir une sortie HTML en classe. Ainsi, au lieu de télécharger les données à chaque démarrage de l’application, nous les téléchargeons une fois pour en faire une classe.
Holli

5

La métaprogrammation fait partie de la programmation depuis longtemps. Ne considérez pas seulement des outils tels que SWIG ou les concepteurs WYSIWYG, qui créent du code, mais également des outils en langage comme le préprocesseur de C, ou même les modèles de C ++ et les génériques de C # / Java - sans parler de Reflection.

En fait, vous pourriez faire valoir que chaque compilateur est juste un autre métaprogramme: ils prennent en texte le programme et le code de la machine ou de la machine virtuelle. Et la vie sans compilateurs? Owch.


C'est vrai, mais comment pouvez-vous réellement l'implémenter dans votre propre langage de programmation pour augmenter réellement votre productivité? C'est ce qui me manque.
Jose Faeti

5

Voici un exemple concret de mon passé.

Je travaillais sur un site contenant environ 50 Mo de code source Delphi utilisant le BDE pour l’accès aux données. Ils voulaient passer à l’utilisation de Direct Oracle Access pour permettre une mise à niveau Oracle au-delà de la version la plus récente prise en charge par le BDE (8i si je me souviens bien).

Ainsi, au lieu de demander à une équipe de codeurs de traiter chaque formulaire et chaque module de données en changeant chaque composant manuellement, j’ai écrit un script PERL qui: -

  1. Analyser le DFM (fichier de formulaire) et identifier tous les objets TQuery, TTable, TStoredProcedure & TDatabase - en stockant les éléments dans une liste.

  2. Analysé le PAS (code) et identifié l'utilisation des objets - les TQueries effectuaient-elles des mises à jour ou des sélections? En outre, il a identifié tous les objets créés dans le code plutôt que déposés dans un formulaire dans l'EDI.

  3. Réécrivez DFM & PAS en modifiant les types d'objet de manière appropriée (par exemple, TTable -> TOracleDataSet avec la propriété SQL définie sur "select * from" etc.) et les appels de méthode. En outre, des appels de méthode supplémentaires ont été ajoutés, le cas échéant, pour fermer, ouvrir et définir des paramètres.

En bref, 3 semaines de travail peaufinant le script pour travailler sur différentes applications écrites par différentes équipes avec différents styles de codage au lieu de l’estimation initiale de plus de 5 développeurs travaillant pendant 6 mois.

Et la raison pour laquelle j'ai même pensé à utiliser cette approche était par la lecture de The Pragmatic Programmer


C'est formidable. Je suis dans Perl depuis quelques jours et j'ai déjà créé des outils de productivité pour générer des espaces de travail de base pour le développement Web, avec tous les répertoires, fichiers, etc. en tapant simplement "créer un espace de travail"! :)
Jose Faeti

1
@Jose C'est l'idée. Utilisez des langages de script pour automatiser les tâches répétitives. Cela peut être occasionnel pour un gain de productivité de 8 fois ou comme une perte de temps que vous ferez encore et encore.
Mcottle

4

Vous demandez des exemples ....

Lorsque vous travaillez avec SQL, vous ne devez pas modifier directement la base de données, mais plutôt exécuter des scripts qui apportent les modifications souhaitées, y compris des modifications structurelles de la base de données (ajout de tables, de colonnes, de clés primaires, de contraintes, etc.). . Très souvent, vous devrez faire la même action contre un grand nombre de tables ou de colonnes en même temps, et les effectuer une par une serait fastidieux, un court script produisant un script plus volumineux qui fait ce que vous voulez peut être un réel gagne-temps.

Par exemple, avant l'introduction du type de données DATE dans MS SQl Server, le seul choix d'une colonne de date était DATETIME, qui comporte une partie heure - une partie heure qui rend le traitement des données un peu plus difficile. Lors de la mise à niveau vers une version avec le type de données Date, vous pouvez mettre à jour les colonnes où l'heure est toujours 00:00. Dans une base de données contenant des dizaines voire des centaines de colonnes DateTime, cela prendrait beaucoup de temps. Mais il est facile d'écrire un script qui interroge toutes les tables, en vérifiant chaque colonne avec un type de données de type DATETIME pour voir si l'heure est toujours différente de 00:00 et si non créer une instruction ALTER pour que la table / colonne change le type de données à DATE. Presto, code qui écrit du code.


3

Examinez les macros CL (Common Lips). À mon avis, c'est exactement ce que vous voulez. Les lèvres sont parfaites en métaprogrammation.

Aussi, je suggère Nemerle si vous voulez avoir des pouvoirs .NET avec un support parfait de la métaprogrammation (y compris les macros)

Mais si vous voulez un véritable moteur de génération de code, jetez un coup d'œil à Apache Thrift


3

Je travaille juste sur un tel outil. Dans notre cas particulier, nous générons le code VB.NET basé sur la signature des fonctions de la base de données pour la couche de données.

Commencer à travailler sur et avec la génération de code est difficile au début car vous ne savez pas comment le code devrait être généré, mais une fois que vous avez établi un ensemble de règles bien établi, vous pouvez toujours générer le code à générer en fonction de ces règles. , travailler avec ce code n’est pas si difficile. Bien entendu, en fonction de la complexité de la génération du code et du nombre de règles, la tâche peut devenir plus difficile. Cependant, la génération de code automatique est essentiellement utilisée pour les tâches de codage répétitives et non pour le code avancé qui varie beaucoup.

Tester la sortie est double. Tout d'abord, vous devez vous assurer que le code est compilé, et c'est facile. Ensuite, vous devez vous assurer que la sortie fait ce que vous vouliez faire en fonction des paramètres sur lesquels elle a été générée. La difficulté de cette sortie varie en fonction de la complexité du code que vous générez.

Ma recommandation sincère est que si vous sentez que vous écrivez du code de manière répétitive et que vous avez les moyens de vous donner le temps nécessaire, essayez de penser si ce que vous faites ne peut pas être fait avec du code généré. Et si tel est le cas (si le code est répétitif, ce qui est presque toujours le cas), réfléchissez au nombre de fois que vous devrez étendre, modifier légèrement ce code et aussi combien de fois devez-vous écrire ce type de code exact. Si la réponse à l'une de ces questions est "plusieurs", vous devriez sérieusement envisager de créer un générateur pour ce code .

J'espère que ça aide,
IPP


Merci de répondre! Comment les règles de votre exemple sont-elles réellement mises en œuvre?
Jose Faeti

1
Je ne peux pas vous dire toutes les règles, mais je peux vous donner quelques exemples. Nous analysons l'interface exposée par une base de données Oracle et prenons en compte les signatures des fonctions de l'interface Oracle. Sur la base de la signature, nous générons le nom de la fonction de couche de données. nous savons que nous obtenons toujours de la base de données db une table de données oracle en tant que résultat que nous analysons et sauvegardons dans un tableau de types d’objets spéciaux que nous utilisons pour stocker nos données. également, en fonction des paramètres d'entrée / sortie de la signature de la fonction db, nous ajoutons les paramètres d'entrée et de sortie correspondants aux fonctions que nous générons, etc.
Ioan Paul Pirau

3

J'ai un module PHP qui génère une page Web contenant du code JavaScript qui génère du HTML. C'est trois couches juste là. Boy était si difficile à lire!

Dans une classe de programmation, nous devions écrire un programme qui prendrait une chaîne de formule de l'utilisateur, puis l'analyse et l'affichage de la valeur. Le solveur le plus impressionnant a simplement pris l'entrée de l'utilisateur, l'a encapsulée dans main () {printf ("% d", ...);} et a exécuté un script pour compiler, lier et exécuter. Il n'a pas écrit d'analyseur! Aujourd'hui, vous pouvez le faire dans une instruction SQL SELECT.

C’est un outil avec lequel vous devriez jouer, puis le ranger pour un jour futur où il vous sera utile.


C'est en fait la même chose que j'essayais de mettre en place! :) Mais ensuite, j'ai décidé de le coder avec Perl hors ligne et cela fonctionne très bien. J'ai une tonne de fonctionnalités que je pense ajouter!
Jose Faeti

J'écris du code avec jusqu'à 20 couches de langage en transformations de langage, sans aucun problème. Ce n’est pas plus compliqué que d’avoir une profondeur d’appel de 20 couches. Je ne suis donc pas du tout d’accord sur le fait qu’il s’agit d’un outil permettant de " ranger le tout pour un jour futur où il sera utile " - la génération de code est toujours pratique.
SK-logic le

3

J'ai développé des solutions de méta-programmation soignées avec Prolog . Où l'application principale (en C ++, par exemple) traduit une définition abstraite d'un problème en une application Prolog au moment de l'exécution, à laquelle elle est ensuite déléguée. Souvent, écrire une fonctionnalité équivalente en C ++ prendrait une éternité.

Je pense que ce scénario est un excellent argument en faveur de l' argument code-write-code .


3

Que pensez-vous du sujet?

La métaprogrammation est le plus souvent associée aux langages non dynamiques, car il est plus difficile d'obtenir certains comportements (tels que la mise en œuvre d'un ORM) sans beaucoup de lignes de code non productives et non intelligentes.

Mais même dans des langages plus dynamiques tels que PHP, la génération de code peut réellement sauver la vie et augmenter considérablement la productivité. Dans les frameworks modernes, il est très courant d'avoir un échafaudage qui génère la plupart des modèles, formulaires, tests et actions communs pour un certain objet métier que vous déclarez. C'est l'une des raisons pour lesquelles des frameworks tels que symfony ou RoR ont autant de succès, ces outils de génération de code rendent le code cohérent très rapidement et augmentent la productivité des programmeurs.

Sur les sites Web, la plupart des interactions s'articulent autour de quatre actions principales:

  • Créer un élément
  • Récupérer un ensemble d'éléments (avec filtrage possible)
  • Mettre à jour un élément avec de nouveaux attributs
  • Supprimer un ensemble d'éléments

Au moins tout ce qui tourne autour de ces 4 actions principales pourrait et IMHO DEVRAIT être réalisé en utilisant des outils de génération de code pour atteindre une productivité maximale.

Dans mon entreprise, nous utilisons symfony et son générateur-admin est un outil exceptionnel, qui génère même du code au moment de l'exécution (et le met en cache), ce qui signifie que nous n'avons même pas besoin d'utiliser un type quelconque de tâche ou d'outil externe pour: générer du nouveau code, nous avons juste besoin de nettoyer notre cache. Je conseille FORTEMENT d'utiliser ce type d'outil pour les opérations CRUD.

Mais faire ce que symfony a fait d’impressionnants contributeurs n’est pas une tâche facile. J'ai moi-même implémenté certaines tâches de génération de code et faire quelque chose de vraiment cohérent et avec une implémentation large couvrant la plupart des cas difficiles n'est pas facile.

Est-ce quelque chose qui va vraiment augmenter votre productivité?

Je crois que la métaprogrammation est très très importante dans les niveaux de travail inférieurs (frameworks, mise en cache, compilateurs, etc.), mais que nous devons faire preuve de la plus grande prudence si nous agissons dans la couche métier.

L’utilisation de la génération de code est sans contredit un atout majeur pour la productivité. Implémentation de vos propres outils de génération de code, pas tant que vous ne construisez pas vous-même un framework.

Quelles sont les bonnes ressources sur le sujet, parmi les livres, les blogs, les diaporamas, etc.?

La meilleure ressource pour comprendre la programmation est toujours un code source bon et bien commenté. Je dirais que rechercher des générateurs d’administration RubyOnRails et Symfony est une bonne idée.


3

Bien que de nombreuses réponses ici renvoient à ce que l’on appelle couramment la méta-programmation, il existait en fait un domaine associé à l’IA, appelé programmation automatique, qui concernait les programmes de compréhension ou de synthèse de programmes [1].

Tout compilateur (ou méta-programme, générateur de code, traducteur, système macro, ...) travaille avec des transformations, générant une sortie à partir d'une entrée en effectuant son algorithme de transformation fixe. Mais un compilateur traditionnel ou un méta-programme traditionnel ne crée pas, à partir d'une définition, d'une description ou d'un exemple de ce qu'est le tri d'une liste (par exemple, [5, 3, 9] => [3,5,9]], un algorithme de tri. Ces problèmes présentaient un intérêt pour ce domaine de la "programmation automatique".

[1] - Rapport d'avancement sur les systèmes de compréhension de programmes ftp://db.stanford.edu/pub/cstr/reports/cs/.../CS-TR-74-444.pdfShare


2

La méta-programmation peut être très difficile à maintenir. Au début, cela a l'air élégant, mais lorsque vous commencez à courir dans les cas critiques, les erreurs sont interceptées tardivement (sur le code qui a été généré), et le tout devient un cauchemar à utiliser / debug.

J'ai principalement écrit du code python et, selon mon expérience, la méta-programmation est toujours un mauvais choix avec ce langage. Vous pouvez toujours refactoriser les choses pour le faire avec des fonctionnalités ennuyeuses du langage normal. Le résultat est moins funky, mais plus facile à vivre.


tout type de code peut être très difficile à maintenir. Et peut être très facile si fait de la bonne façon. La métaprogrammation peut en effet augmenter la maintenabilité par ordres de grandeur. Votre expérience de python est probablement sans rapport avec la métaprogrammation réelle, car Python ne convient pas à cette façon de penser, avec son AST trop lourd et trop profond. Mais même avec Python, j’utilisais la bibliothèque Tempita avec une grande efficacité et n’avais jamais eu de problème de maintenabilité, même avec une équipe n’ayant pratiquement aucune expérience de Python.
SK-logic

Votre point sur python AST m'intéresse. Avez-vous utilisé tempita à des fins de méta-programmation?
Simon Bergot

ceci ( docs.python.org/library/ast.html ) est plutôt une AST ad hoc, et l’analyseur donne un arbre non optimisé et trop volumineux, ce qui rend l’analyse problématique (en particulier avec l’absence de correspondance correcte des modèles en Python). Générer un tel AST n’est pas très pratique non plus. J'ai utilisé tempita pour produire à la fois du code Python et du code C (c'est-à-dire une métaprogrammation purement basée sur du texte), cela fonctionnait parfaitement pour cette tâche spécifique (génération de code passe-partout). J'ai aussi souvent utilisé Python pour générer du code C à partir de descriptions XML de haut niveau.
SK-logic

2

OP demande des ressources.

Vous pourriez trouver notre boîte à outils DMS Software Reengineering intéressante. C’est un pur outil de métaprogrammation, conçu pour permettre à chacun de construire des outils d’analyse et de transformation de programmes personnalisés.

[Pour suivre un commentaire sur la question d'OP, lorsqu'il est utilisé pour créer un outil de transformation spécifique, DMS est une ligne de produits qui écrit du code, qui écrit du code:]

DMS y parvient en étant agnostique (mais pas indépendant) des langues de programmation cibles. DMS fournit les services standard nécessaires à une grande variété de tâches de métaprogrammation, de la même manière qu'un système d'exploitation fournit une grande variété de services pour des tâches de programmation standard. Ces services incluent une analyse syntaxique poussée, la construction automatique d’arbres de syntaxe d’abstrait, la recherche de motifs et la réécriture sur des arbres, des bibliothèques de tables de symboles permettant de gérer facilement des langages avec des règles de périmètre malveillantes telles que l’héritage multiple, le flux de données, le flux de données, le point-to et les appels. analyse graphique. Rien de cela n’est méchant en l’absence de langages spécifiques à traiter. DMS accepte donc les définitions de langage liées à ces machines générales, donnant lieu à une analyse syntaxique spécifique à la langue, à la construction AST, à la correspondance / réécriture de modèles spécifiques à une langue cible. syntaxe de langage,

Et comme un système d’exploitation, DMS est conçu pour avoir très peu d’opinions ou de contraintes sur les programmes (méta) que vous souhaitez écrire, ce qui signifie qu’il peut être utilisé à des fins très variées: extraire des métriques, trouver du code mort, mettre en œuvre des tisseurs d’aspect, traduire langauges, générer des codes à partir de DSL, réarchiver de grandes applications. (DMS a déjà été utilisé pour toutes ces tâches).

Vous avez besoin de définitions de langage robustes si vous ne voulez pas perdre votre temps à tout coder dans le manuel de référence en langues (réfléchissez à ce que cela signifie pour Java et C ++). DMS résout ce problème en disposant d'une bibliothèque de définitions de langauge complètes. L’analogique ressemble un peu à avoir une base de données disponible pour votre système d’exploitation; vous n'avez pas à implémenter l'un d'entre eux pour écrire votre application centrée sur la base de données.


2

Voir la série de problèmes 4 de Philip Greenspun dans le cours 6.916 du MIT: Ingénierie logicielle de services Web innovants ( http://philip.greenspun.com/teaching/psets/ps4/ps4.adp ).

Son objectif est le suivant: "Enseigner aux étudiants les vertus des métadonnées. Plus spécifiquement, ils apprennent à représenter formellement les exigences d'un service Web, puis à créer un programme informatique permettant de générer les programmes informatiques qui implémentent ce service."

C’est l’un des problèmes majeurs que les recrues potentielles ArsDigita ( http://en.wikipedia.org/wiki/ArsDigita ) ont dû résoudre lors de la première bulle.

Le livre "SQL for Web Nerds" référencé par Philip dans le pset a été déplacé vers ( http://philip.greenspun.com/sql/ ).


2

Vers 2001, j'ai commencé à travailler sur un projet qui utilisait beaucoup les objets de gestion et les objets de données. Je devais construire le site Web front-end, mais j'ai été suspendu parce que la couche métier et la couche d'accès aux données n'étaient pas complètement développées. Après quelques semaines, j'ai commencé à jeter un regard critique sur ce que ces couches faisaient. Fondamentalement, ils exposaient les données renvoyées par les procédures stockées sous forme de collections d'objets avec des propriétés correspondant aux champs des données, ou prenaient des paramètres d'entrée et les envoyaient à des procédures stockées pour les sauvegarder dans des tables de base de données. Il y avait beaucoup de sérialisation / désérialisation entre les deux couches, il y avait Microsoft Transaction Server impliqué, une bibliothèque de types IDL / ODL ... mais tout cela correspondait à un modèle.

Deux semaines plus tard, un générateur de code a été mis au point pour vider IDL / ODL, ainsi que les objets métier et de données. Il avait fallu deux ans au responsable de la création des objets de la couche de gestion et de la couche de données pour arriver au point de déboguer et de tester ces objets. En 2 semaines, avec la génération de code, nous avions la même sortie, mais comme elle était entièrement générée, elle ne contenait aucun bogue.

Ce générateur de code (outil CASE de niveau inférieur) m'a suivi à travers de nombreuses itérations différentes, pendant environ 8 à 10 ans, parce que le principe était si simple: vous faites quelque chose qui doit être fait lorsque vous parlez de bases de données, c'est joli beaucoup de codage répétitif, et une fois que vous avez bien compris, vous n’aurez plus à vous en soucier.

Donc, oui: utilisez un générateur de code, en particulier lorsque le codage est répétitif et correspond à un modèle bien défini.

J'ai connu des personnes qui utilisaient des macros RegX pour faire des choses similaires, ou qui utilisaient des formules Excel pour faire des choses similaires (je le fais aussi).


2

Un exemple de métaprogrammation

J'ai une bibliothèque d'autorisation Ruby appelée Autorité . Il permet aux développeurs de poser des questions dans leur application avec des méthodes telles que current_user.can_read?(@post)et @post.readable_by?(current_user). Ces questions sont répondues par des classes centralisées d'autorisateur.

C'est la partie cruciale: l' autorité ne sait pas quelles méthodes définir avant de voir la configuration de l'utilisateur . La configuration de l'utilisateur peut contenir:

config.abilities =  {
  ...
  :read      => 'readable',
  :microwave => 'microwavable',  # user-defined
  ...
}

Dans ce cas, il doit y avoir une méthode comme current_user.can_microwave?(@post).

La métaprogrammation rend cela possible: après avoir lu la configuration, je sais quelles méthodes définir :

Authority.verbs.each do |verb|
  class_eval <<-RUBY, __FILE__, __LINE__ + 1 # allows for a nice bracktrace
    def can_#{verb}?(resource)
      resource.#{Authority.abilities[verb]}_by?(self)
    end
  RUBY
end
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.