La réutilisation du code est peut-être la plus grande promesse d'utiliser un paradigme orienté objet. Certains contestent que cela a été réalisé. Pourquoi a-t-il (non) été atteint?
Est-ce que la réutilisation de code telle que définie par la POO rend les projets plus productifs?
Ou plus gérable? Ou plus facile à entretenir? Ou avec plus de qualité?
Nous sommes probablement tous d'accord pour dire que la réutilisation du code est une bonne chose, mais il existe plusieurs façons d'atteindre cet objectif. La question concerne la méthode de réutilisation de code proposée par OOP. Était-ce une bonne chose? Existe-t-il de meilleures méthodes de réutilisation du code que l'orientation d'objet, la sous-classification, le polymorphisme, etc.? Quels sont les meilleurs moyens? Pourquoi ?
Racontez-nous votre expérience de la réutilisation de la POO ou d'autres paradigmes.
Réponses:
La réutilisation du code est une très bonne idée. Pas terrible .
J'ai une perspective tirée d'environ 30 ans d'ingénierie logicielle, qui tente de "réutiliser".
J'ai commencé à étudier la «réutilisation de code» comme sujet de recherche dans les années 80, après avoir découvert que j'avais réutilisé le design d'un système d'exploitation que j'avais construit au début des années 70, pour un autre installé à la fin des années 70.
La bonne partie de la réutilisation de code réside dans la possibilité de réutiliser parfois du code préexistant «dieu-dieu». Mais le monde est plein de code; comment trouver ce que tu veux Voici ce que j'appelle la malédiction de réutilisation :
Je suis le père Noël (ok Open Source), et j'ai un sac d'un milliard de composants logiciels. Vous pouvez avoir n'importe lequel d'entre eux.
Bonne chance pour choisir.
Pour résoudre correctement le problème de réutilisation:
La plupart du temps, on a découvert au fil des ans que pour que le code soit réutilisable, il doit en quelque sorte être conçu dans ce but, ou il contient trop d'hypothèses implicites. Les bibliothèques les plus réussies de réutilisation de code ont été plutôt petites. On peut soutenir que les librairies et les frameworks sont du code "réutilisable" et qu'ils ont un grand succès; Java et C # réussissent non pas parce qu’ils sont de très bons langages informatiques, mais plutôt parce qu’ils disposent d’énormes bibliothèques bien conçues, implémentées et documentées. Mais les gens ne regardent pas le code source dans les bibliothèques; ils appellent simplement une API bien documentée (conçue pour être généralement utilisable).
Ce que la réutilisation de code n’a pas encore fait (la POO non plus), c’est améliorer considérablement notre capacité à coder les systèmes.
Je pense que le principal inconvénient est que tout type de réutilisation de code est fondamentalement limité car le code contient trop d'hypothèses intégrées . Si vous réduisez le code de façon minuscule, vous réduisez les hypothèses au minimum, mais le coût de la création à partir de zéro n'est pas très élevé et les gains de réutilisation ne sont pas efficaces. Si vous créez des morceaux de code énormes, ils sont quasiment inutiles dans un nouveau contexte. Comme Gulliver, ils sont attachés à la plage par un million de petites ficelles, et vous ne pouvez tout simplement pas vous permettre de tous les couper.
Nous devrions travailler sur la réutilisation des connaissances pour construire du code . Si nous pouvons faire cela, alors nous pouvons appliquer cette connaissance à la construction du code dont nous avons besoin, en gérant l'ensemble actuel des hypothèses.
Pour ce faire, il faut toujours la même capacité de spécification pour caractériser les composants logiciels (vous devez toujours dire ce que vous voulez!). Mais ensuite, vous appliquez cette connaissance de "construction" aux spécifications pour générer le code souhaité.
En tant que communauté, nous ne sommes pas encore très bons à cela. Mais les gens le font tout le temps. pourquoi ne pouvons-nous pas l'automatiser? Il y a beaucoup de recherches et cela montre que cela peut être fait dans de nombreuses circonstances.
Les outils mécaniques nécessaires pour accepter les "descriptions de composants" (ce ne sont que des documents formels et peuvent être analysés comme des langages de programmation) constituent un élément clé de cette machinerie et leur appliquent des transformations de programme .
Les compilateurs le font déjà:} Et ils sont vraiment bons dans la classe de problèmes qu’ils abordent.
Les modèles UML avec génération de code constituent une tentative. Ce n'est pas une très bonne tentative. à peu près ce que l’on dit dans la plupart des modèles UML est "j’ai des données qui ressemblent à ceci". Assez difficile de générer un vrai programme si la fonctionnalité est laissée de côté.
J'essaie de construire des systèmes pratiques de transformation de programme, un outil appelé DMS . J'ai été assez distrait en appliquant des transformations de programme, non pas tant aux spécifications abstraites pour générer du code, mais plutôt au code hérité pour le nettoyer. (Ce sont le même problème dans l'abstrait!). (Construire de tels outils prend beaucoup de temps; je le fais depuis 15 ans et en attendant, il faut manger).
Mais DMS a les deux propriétés clés que j'ai décrites ci-dessus: la capacité de traiter des spécifications formelles arbitraires et la capacité de capturer des "connaissances en matière de génération de code" sous forme de transformations et de les appliquer à la demande. Et remarquablement, nous générons dans certains cas particuliers, du code plutôt intéressant provenant de spécifications; DMS est en grande partie construit en utilisant lui-même pour générer son implémentation. Cela nous a permis de réaliser au moins une partie de la promesse de réutilisation (du savoir): des gains de productivité extrêmement importants. J'ai une équipe d'environ 7 personnes techniques; nous avons probablement écrit 1 à 2 MSLOC de "spécifications" pour DMS, mais avons environ 10 LMS de code généré.
Résumé: la réutilisation des connaissances de la génération est la victoire, pas la réutilisation du code .
la source
Mostly what has been discovered over the years is that for code to be reusable, it sort of has to be designed for that purpose, or it contains too many implicit assumptions.
Je suis arrivé à une conclusion similaire mais je ne pouvais pas l'exprimer de manière aussi succincte.La réutilisation de code est obtenue en POO, mais également en programmation fonctionnelle. Chaque fois que vous prenez un bloc de code et que vous le rendez appelable par le reste de votre code, de telle sorte que vous puissiez utiliser cette fonctionnalité ailleurs, cela constitue une réutilisation du code.
Ce type de réutilisation de code rend également le code plus facile à gérer, car la modification de ce bloc appelable modifie tous les emplacements auxquels il est appelé. Je dirais que ce résultat améliore également la qualité et la lisibilité.
Je ne suis pas sûr que la programmation orientée objet soit simplement là pour permettre la réutilisation du code. Je considère la programmation orientée objet plus comme un moyen d'interagir avec des objets et d'abstraction des détails de la structure de données.
De Wikpedia:
la source
double sqrt (double x)
? Les fonctions pures sont l'archétype de la réutilisabilité.double sqrt(double x)
,float sqrt(float x)
,int sqrt(int x)
vous pouvez définir un grand nombre d'entre eux, alors qu'avec un langage de programmation générique que vous auriezNumber sqrt(Number x)
et faire avec elle.Oui et non
La réutilisation de code est un terme fourre-tout pour de nombreuses activités différentes.
la source
Je posterais une longue réponse mais pourquoi? Udi Dahan l'explique beaucoup mieux que moi.
http://www.udidahan.com/2009/06/07/the-fallacy-of-reuse/
Voici le début du post:
la source
Je suis d'accord avec Chris, la programmation fonctionnelle est un bon moyen de réutiliser le code.
De nombreux programmes ont des structures de code récurrentes. Pour cela, certains modèles de conception sont utilisés dans le monde de la programmation orientée objet, mais cela peut être réalisé à l'aide de fonctions récursives et de correspondance de modèles dans des langages de programmation fonctionnels. Pour plus d'informations à ce sujet, voir le premier chapitre de la programmation fonctionnelle dans le monde réel .
Je pense que l'héritage profond en POO peut être trompeur dans de nombreux cas. Vous avez une classe et de nombreuses méthodes étroitement liées sont implémentées dans différents fichiers. Comme Joe Armstrong l'a dit à propos de la programmation orientée objet:
Les fonctions d'ordre élevé sont également très utiles pour la réutilisation de code, par exemple,
map
etfoldr
constituent le fondement de MapReduce de Google .Le passage de messages asynchrone est également un bon moyen d’organiser des logiciels complexes, et certains informaticiens affirment que les objets étaient supposés communiquer entre eux de manière asynchrone, comme dans le principe Tell, ne demandez pas le principe de la POO. Vous en saurez plus à ce sujet dans Programmation orientée objet: le mauvais chemin? étaient Joe Armstrong est cité:
La transmission asynchrone des messages, comme dans les systèmes événementiels et dans Erlang, est également un très bon moyen de découpler les systèmes et le couplage faible est important dans les systèmes complexes. Avec un système suffisamment découplé, vous pouvez faire évoluer le système pendant son fonctionnement, peut-être sur différents nœuds. Unibet a fait une excellente présentation à ce sujet: Architecture axée sur les événements de domaine
Cependant, je pense que la majeure partie de la réutilisation du code se fait en utilisant des bibliothèques et des frameworks.
la source
L’humble pipe Unix a fait plus pour la réutilisation du code que tout ce qui a été fait. Les objets se sont avérés être un moyen intuitif de structurer le code quand ils sont arrivés, et plus tard, les gens ont commencé à utiliser n'importe quoi dessus. En général, les objets sont destinés à l'encapsulation et non à la réutilisation de code, la réutilisation de code nécessite quelque chose de plus et la hiérarchie d'héritage de classe est un substitut médiocre à ce que devrait être un mécanisme de réutilisation de code.
la source
OOP n'est pas spécial; vous pouvez créer du code réutilisable avec ou sans POO. Les fonctions pures sont particulièrement réutilisables : par exemple,
java.lang.math.sqrt(double)
entrer un nombre et en donner un. Pas de POO, mais certainement plus réutilisable que la plupart des codes existants.la source
Du point de vue de la programmation fonctionnelle, la programmation orientée objet concerne principalement la gestion des états.
En programmation fonctionnelle, vous pouvez facilement disposer de centaines de fonctions utiles pour les listes: http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Data-List.html .
Auriez-vous des centaines de méthodes dans une classe List? Les méthodes publiques sont considérées comme une interface avec l'état interne que vous souhaitez conserver de petite taille.
Malheureusement, au lieu de (ré) utiliser de nombreuses petites fonctions, certaines personnes dupliquent des fonctionnalités. Pour moi, c'est parce que la POO n'encourage pas la réutilisation de code autant que la programmation fonctionnelle.
la source
Pour moi, oui, mais pas tout le temps, et cela aurait pu être fait autrement.
La plupart du temps, vous créez une classe de base abstraite et créez des implémentations concrètes de cette classe.
De plus, de nombreux frameworks utilisent l'héritage pour permettre la réutilisation du code (Delphi, Java, .Net en sont quelques-uns qui viennent immédiatement à l'esprit).
Cela ne veut pas dire que beaucoup de bibliothèques d'utilitaires et d'extraits de code n'auraient pas pu faire le travail aussi, mais il y a quelque chose d'agréable à propos d'une hiérarchie d'objets bien conçue.
la source
D'après mon expérience, j'ai plus de succès à exploiter le code "réutilisable" via des fonctions de programmation génériques (telles que les modèles C ++) que l'utilisation de principes de POO tels que les hiérarchies d'héritage.
la source
La POO est trop ouverte pour une réutilisation efficace.
Il y a trop de façons de réutiliser. Chaque classe publique demande: "crée une nouvelle instance de moi!" , chaque méthode publique dit: "appelle-moi!" , chaque méthode protégée donne: "écrasez-moi!" - et tous ces modes de réutilisation sont différents , ils ont des paramètres différents, ils apparaissent dans un contexte différent, ils ont tous des règles différentes, comment l'appeler / l'étendre / le remplacer.
L'API est préférable, c'est un sous-ensemble strict de points OOP (ou non-oop), mais dans la vraie vie, les API sont sur-exploitées et en croissance constante, il y a encore trop de points de connexion. En outre, une bonne API peut rendre la vie plus facile, c'est le meilleur moyen de fournir une interface pour la POO.
Le paradigme Datadlow fournit une interface stricte pour les composants, ils ont des types de ports suivants:
Dépend du domaine, il y a certains types de paquets, afin que les consommateurs et les producteurs puissent être connectés s'ils ont les mêmes ports (ou compatibles). La plus belle partie de ce qui peut être fait visuellement, parce qu’il n’ya pas de paramètres ni d’autres réglages sur les connexions, elles ne font que connecter un consommateur et un producteur.
J'étais un peu incertain, vous pouvez jeter un oeil sur la balise "dataflow" de StackOverflow , ou sur la "programmation datafow" de Wikipedia ou sur la "programmation basée sur les flux" de Wikipedia .
(En outre, j'ai écrit un système de flux de données, en C ++. Ainsi, OOP et DF ne sont pas des ennemis, DF est un moyen d'organisation de niveau supérieur.)
la source
Dans CommonLisp, il existe de nombreux moyens de réutiliser:
typage dynamique, votre code étant générique par défaut
abstractions impératives, c.-à-d. sous-programmes
orientation objet, avec héritage multiple et envoi multiple
syntaxe-abstraction, capacité à définir de nouvelles constructions syntaxiques ou à abréger le code de la plaque de chaudière
Abstractions fonctionnelles, fermetures et fonctions d'ordre élevé
Si vous essayez de comparer l'expérience CommonLisp à d'autres langues, vous constaterez que la principale caractéristique qui facilite la réutilisation du code est la présence d' abstractions à la fois orientées objet et fonctionnelles. Ils sont plus complémentaires qu’alternatifs: sans l’un d’entre eux, vous êtes obligé de réimplémenter les fonctionnalités manquantes de manière maladroite. Voir, par exemple, les classes de foncteur utilisées comme fermetures et correspondance de modèles pour obtenir une répartition de méthode non extensible.
la source
- Kevlin Henney
la source
Je vais risquer de ridiculiser et d’avouer que je n’utilise la POO que très récemment. Cela ne me vient pas automatiquement. La plupart de mes expériences concernent des bases de données relationnelles, je pense donc aux tables et aux jointures. Certains prétendent qu'il vaut mieux l'apprendre dès le début, ce qui évite de devoir reformuler ses idées en matière de programmation. Je n’ai pas ce luxe et je refuse d’abandonner ma carrière au détriment d’une théorie de la tour d’ivoire. Comme tout le reste, je vais comprendre.
Au début, je pensais que le concept n’avait aucun sens. Cela semblait juste inutile et trop de problèmes. Je sais, c'est un discours fou. Évidemment, il faut un certain niveau de compréhension avant de pouvoir apprécier les avantages de quoi que ce soit ou de le rejeter pour de meilleures méthodes.
La réutilisation de code nécessite une volonté de ne pas répéter le code, une compréhension de la manière de le réaliser, une planification initiale. Devez-vous éviter de réutiliser du code une fois que vous avez décidé de ne pas en valoir la peine? Et aucune langue n’est tellement stricte qu’elle génère une erreur quand elle pense que vous devriez hériter du code d’une autre classe. Au mieux, ils fournissent un environnement propice à sa mise en œuvre.
Je pense que le plus grand avantage de la programmation orientée objet est l'acceptation générale de la manière dont le code devrait être organisé. Tout le reste est de la sauce. Une équipe de programmeurs peut ne pas être totalement d'accord sur la structure de toutes les classes, mais elle devrait pouvoir trouver le code.
J'ai vu suffisamment de code de procédure pour savoir que cela pourrait être n'importe où, et parfois c'est partout.
la source
La POO vous donne plus de moyens de réutiliser le code. C'est tout.
la source
Réutilisation horizontale: aspects, traits, greffes
Classic OO ne parvient parfois pas à réutiliser le code, en particulier lorsque vous êtes fous d'héritage, faute d'un meilleur moyen de partager les fonctionnalités réelles entre les classes. Pour ce problème, des mécanismes de réutilisation horizontale ont été créés, tels que AOP, traits et greffes.
Programmation Orientée Aspect
Je considère AOP comme la demi-orange manquante de OOP. AOP n'est pas vraiment connu, mais il a été transformé en code de production.
Je vais essayer d'expliquer en termes simples: imaginez que vous pouvez injecter et la fonctionnalité de filtre avec une structure spéciale appelée un aspect, ces aspects ont des « méthodes » qui définissent quoi et comment va être affectée par la réflexion , mais au moment de la compilation , ce processus s'appelle le tissage .
Un exemple serait un aspect qui indique "pour toutes les méthodes de certaines classes qui commencent par get, votre programme écrit dans un fichier journal les données obtenues et l'heure à laquelle elles ont été obtenues".
Regardez ces deux entretiens si vous voulez mieux comprendre AOP:
Traits et greffes
Les traits sont une autre construction permettant de définir du code réutilisable qui complète la POO. Ils sont similaires à mixins , mais plus propres.
Plutôt que de les expliquer, il existe un excellent RFC PHP qui explique les deux . Les traits viennent à PHP btw, ils sont déjà commis au coffre.
En résumé
La programmation orientée objet est la clé de la modularité mais, à mon avis, et telle que nous la connaissons aujourd'hui, la programmation orientée objet est encore incomplète .
la source
OOP Fournit un ensemble d'outils utiles vous permettant d'écrire du code pouvant être utilisé dans plus d'endroits que vous ne pourriez en avoir sans ces outils. Si vous écrivez une
PrintIt
fonction qui prend n'importe quel ancien objet et appelle.toString()
dessus, vous aurez réutilisé ce code dès que vous l'appelez avec plus d'un type d'objet. Avec ces outils, chaque ligne de code en fait plus.La programmation fonctionnelle est très chaude en ce moment chez les hipsters. Il vous fournit un ensemble d'outils distincts pour que chaque ligne de code en fasse plus. Ce n'est probablement pas mieux ou ne fonctionne pas, mais fournit un autre outil dans la boîte à outils.
(Il y avait une idée folle pour un niveau supplémentaire de réutilisation orientée objet: l’idée était de pouvoir définir une
Customer
classe unique et de l’utiliser dans toutes les applications que nous écrivions. Les applications seraient alors un peu collées ici et là. Cela ne signifie pas pour autant que OO a échoué ou même que la réutilisation a échoué. Les types de base de code réutilisés dans les applications ont permis d’écrire des applications qui en faisaient plus et de les écrire plus rapidement.)la source
En lisant les articles ci-dessus, quelques remarques:
la source
Le problème est plus subtile à mon humble avis:
Ainsi, la programmation orientée objet en soi n’est pas une mauvaise chose de créer du code réutilisable , mais les types de code écrits à l’aide de la programmation orientée objet sont, par nature, difficiles à réutiliser .
En outre, la programmation fonctionnelle peut générer davantage de code réutilisable . Cependant, obtenir les bonnes abstractions pour écrire un code fonctionnel sain tout en respectant une date limite peut ne pas être faisable. Et les abstractions "à moitié droite" seront plus faciles à exprimer en style POO. Et cela ne facilitera pas la réutilisation du code . Un niveau d'abstraction plus élevé signifie que la compréhension du code nécessitera un investissement initial plus important de la part des capacités cognitives limitées des programmeurs.
Comme exemple pratique: Le code de jeu implique beaucoup d’états mutables, car c’est la façon naturelle de penser à coder un jeu. Sauf s’il s’agit d’un casse-tête / d’un algorithme, il est évident qu’il finit par être structuré à l’aide de OO. Et bien sûr, c'est difficile à réutiliser. Mais le même code, contenant les mêmes connaissances, serait encore plus difficile à réutiliser sans la POO . Et réécrire pour devenir un style fonctionnel peut nécessiter une modification totale de la façon dont vous envisagez ce code, les connaissances qui le sous-tendent. Ouais, les connaissances acquises derrière le code seraient beaucoup plus claires après la réécriture d'OO à FP ... peut-être, mais le coût pourrait être énorme et ce pourrait êtrele genre de coûts que devraient également payer les personnes qui souhaitent réutiliser le code incroyablement intelligent et bien abstrait que vous obtenez , si paradoxalement que les gens finiraient par ne pas réutiliser le code, même s'il est techniquement plus réutilisable.
... ce qui mène à la dernière subtilité: la réutilisation du code concerne l' interface People | Code , pas seulement le code. OOP fait un travail décent en servant cette interface car elle correspond bien au nombre de personnes qui pensent à de nombreux types de code écrits de nos jours. La PF pourrait être préférable pour la réutilisation du code, mais pas pour le type de code que les gens ont réellement besoin d'écrire de nos jours. Cela changera en tant que type de code dont nous avons besoin pour écrire les modifications.
PS Et si quelqu'un veut dire que "OO ne concerne pas l'état mutable, vous pouvez également avoir OO avec un état immuable" ... J'appelle cela "FP utilisant des classes comme espaces de noms". C’est génial lorsque cela fonctionne pour vous, cela évite certaines lacunes des systèmes de modules de certaines langues et peut générer davantage de code réutilisable. Mais ce n'est pas OO;)
la source