Pensez-vous que la programmation orientée objet est une solution à la complexité. Pourquoi? Ce sujet peut être un peu controversé mais mes intentions de connaître la réponse du Pourquoi des experts ici!
18
Pensez-vous que la programmation orientée objet est une solution à la complexité. Pourquoi? Ce sujet peut être un peu controversé mais mes intentions de connaître la réponse du Pourquoi des experts ici!
Réponses:
Il n'y a pas de solution à la complexité.
Dans "The Mythical Man-Month", Fred Brooks discute de la différence entre la complexité accidentelle et la complexité essentielle de la programmation. La complexité accidentelle est causée par nos outils et méthodes, comme devoir écrire et tester du code supplémentaire dans un langage parce que nous ne pouvons pas exprimer nos idées directement, et des choses comme ça. De nouvelles méthodes et techniques peuvent réduire la complexité accidentelle. Je peux écrire des programmes plus rapidement et mieux que je ne le pouvais il y a vingt-cinq ans, car j'ai de meilleurs langages et outils.
La complexité essentielle vient du fait que ce que nous essayons de faire avec la programmation est intrinsèquement compliqué et qu'il existe une complexité irréductible. "Essentiel", dans ce contexte, signifie "se rapportant à l'essence de la chose" plutôt que "très nécessaire".
Par conséquent, il a affirmé qu'il n'y aurait pas de solution miracle, que l'écriture de logiciels continuerait d'être difficile.
Je vous recommande fortement de lire son livre: en particulier, je recommande l'édition Silver Anniversary, avec un essai supplémentaire "No Silver Bullet". En cela, il passe en revue les solutions proposées à la complexité et considère leur impact. (Ce qu'il trouve le plus efficace, c'est un logiciel d'emballage rétractable - écrivez quelque chose de complexe une fois et vendez des milliers ou des millions d'exemplaires.)
Maintenant, la programmation orientée objet aide, lorsqu'elle est bien faite, en créant des abstractions et en cachant la complexité. Un objet d'une classe a un certain comportement défini que nous pouvons raisonner, sans se soucier de la complexité de l'implémentation. Les classes correctement écrites ont un faible couplage les unes avec les autres, et diviser pour mieux régner est un excellent moyen de gérer la complexité si vous pouvez vous en sortir. Ils ont également une cohésion élevée, car ils constituent un ensemble de fonctions et de données qui sont étroitement liées les unes aux autres.
la source
J'espère que vous obtiendrez de meilleures réponses sous peu, mais en voici une simple:
La POO aide * à la complexité en modélisant les logiciels d'une manière plus proche de la façon dont nous modélisons tout le reste du monde. Il est généralement plus facile d'imaginer un objet boule interagissant avec un objet mur que d'imaginer une série de routines et de structures de données pour faire la même chose, car c'est plus proche de la façon dont nous interagissons avec le monde réel.
* Parce que rien ne peut «résoudre» la complexité
la source
Je pense que la définition courante courante de la POO n'est pas une bonne solution pour gérer la complexité.
Si vous revenez à ses racines, je crois qu'Alan Kay a été beaucoup influencé par "lisp".
Parce que Lisp n'a pas été corrompu par l'adoption générale, il a probablement réussi à conserver ses valeurs fondamentales. Je pense donc que l'examen de la façon dont Lisp s'attaque à ce problème de complexité pourrait nous donner un aperçu, et nous pouvons l'utiliser comme une base pour juger de l'utilité de la POO pour gérer la complexité.
Si vous regardez à la fin de la "Conférence 3a: Exemple Henderson Escher" de SICP , Hal Abelson propose que la complexité soit gérée non pas en divisant la tâche en sous-tâches plus petites, mais en créant des couches d'abstraction. Au plus haut niveau, vous exprimez la solution au problème compliqué en termes de solution au niveau d'abstraction inférieur.
Je pense que la POO était à l'origine conçue comme un mécanisme pour créer ces couches d'abstractions.
Malheureusement de nos jours, la POO est (ab) utilisée pour écrire du code / des structures spaghetti.
Je vais vous donner un exemple: un jeu multi-joueurs FPS.
Au plus haut niveau, le jeu fonctionne en ayant un groupe de joueurs qui courent autour d'une carte et se tirent dessus avec des armes.
Au niveau inférieur suivant, nous devons parler des cartes et des armes et des joueurs. Peut-être pouvons-nous en parler comme des objets physiques qui interagissent dans le monde du jeu.
Au niveau inférieur suivant, nous pouvons parler de la façon dont les objets interagissent physiquement (mouvement, collisions, etc.).
Et ainsi de suite.
Ce que cela signifie, (et je cite en quelque sorte le SICP ..), c'est qu'à chaque couche, nous résolvons non seulement un problème spécifique particulier, mais une classe de problèmes qui tombent en quelque sorte dans le voisinage du problème que nous ' re essayant de résoudre. Donc, s'il y a un petit changement dans la description du problème, il ne nécessitera probablement qu'un petit changement dans la solution.
Donc, la meilleure façon d'utiliser la POO est de créer des couches d'abstractions, à chaque niveau d'abstraction, vous résolvez le problème en utilisant les "objets" du niveau qui est directement en dessous.
Voici le morceau que je citais de la conférence: http://www.youtube.com/watch?v=CYtrfncMqHQ
la source
Comme d'habitude, je suis en désaccord avec tout le monde. Loin de vous donner des outils pour gérer la complexité, la POO crée une énorme quantité de complexité car c'est un paradigme inadéquat et mathématiquement faux. Il confond les programmeurs sans fin, pour essayer de modéliser avec OOP des choses qui ne peuvent pas être modélisées avec OOP.
À mon avis, le travail fondateur est la construction de logiciels orientés objet de Meyer. Il détaille un ensemble d'exigences, dont une que je considère comme cruciale: le principe ouvert-fermé. Cela signifie qu'une chose doit être ouverte pour extension mais fermée pour utilisation, en même temps.
Meyer procède à dériver l'orientation objet de ces exigences, telles qu'elles sont incarnées dans Eiffel. L'encapsulation fournit une fermeture, une ouverture d'héritage et la «chose» mentionnée est la classe.
Je considère ce travail comme une bonne science parce que Meyer avait manifestement tort, et il est possible en raison de la qualité de son travail, d'identifier l'erreur et de la corriger.
L'erreur fait de la classe, ou du type, l'unité de modularité. C'est faux, et cela est prouvé. Même Meyer a reconnu le problème (appelé problème de covariance), que la POO ne peut pas gérer des relations d'arité supérieures à une (c'est-à-dire que la POO fonctionne bien pour les propriétés mais échoue sur les relations binaires). A Eiffel, ce problème a provoqué un mauvais fonctionnement du système de typage!
La solution est assez claire. L'unité de modularité doit être plus grande qu'un seul type. Il doit être composé de plusieurs types et des méthodes les concernant.
Il n'est guère surprenant que ce modèle d'abstraction soit soutenu par la théorie mathématique de l'abstraction, à savoir la théorie des catégories: les types sont des objets d'une catégorie et les méthodes (fonctions) sont des flèches.
Avec ce modèle, les représentations de plusieurs types sont connues d'un ensemble de fonctions. La représentation est cachée au public, c'est donc de l'encapulsation, mais nous utilisons des modules, pas des classes.
Le méta-langage standard (SML) et Ocaml sont directement basés sur ce modèle. Ocaml a également des classes et OOP: ce n'est pas inutile car OOP vous donne la répartition sur les propriétés, alias la liaison dynamique. Cependant, la plupart des problèmes du monde réel impliquent des relations et il n'est pas surprenant que les classes ne soient pas beaucoup utilisées dans Ocaml.
Il n'est guère surprenant que l'héritage soit à peine utilisé dans la bibliothèque de modèles C ++ Standard.
Le fait est que la POO ne vous donne pas les bons outils pour gérer la complexité, elle ne vous donne même pas les outils pour gérer des problèmes vraiment simples, au lieu de cela, elle a induit en erreur et confondu deux générations de programmeurs. Loin d'aider, OOP est la chose la plus mauvaise et la plus mauvaise qui soit arrivée à la programmation depuis que C, Fortran et Cobol ont commencé à se fatiguer.
la source
La programmation orientée objet a des racines qui remontent aux années 1960. À mesure que le matériel et les logiciels devenaient de plus en plus complexes, la facilité de gestion devenait souvent une préoccupation. Les chercheurs ont étudié les moyens de maintenir la qualité des logiciels et développé une programmation orientée objet en partie pour résoudre les problèmes courants en mettant fortement l'accent sur les unités discrètes et réutilisables de la logique de programmation.
Un programme orienté objet peut ainsi être considéré comme une collection d'objets en interaction, contrairement au modèle conventionnel, dans lequel un programme est considéré comme une liste de tâches (sous-programmes) à exécuter. Dans la POO, chaque objet est capable de recevoir des messages, de traiter des données et d'envoyer des messages à d'autres objets. Chaque objet peut être considéré comme une «machine» indépendante avec un rôle ou une responsabilité distincte. Les actions (ou "méthodes") sur ces objets sont étroitement associées à l'objet lui-même.
http://en.wikipedia.org/wiki/Object-oriented_programming
Cette séparation des préoccupations, ainsi que d'autres caractéristiques de l'orientation d'objet telles que le polymorphisme, l'héritage, le passage de messages, le découplage et l'encapsulation, fournissent un cadre logique et conceptuel par lequel la complexité des grands programmes peut être gérée de manière très efficace.
la source
Il existe de nombreux types de complexité dans le développement de logiciels. Au niveau de la programmation, la POO cherche à résoudre la complexité en utilisant des objets et des classes pour modéliser le domaine problématique. Un gourou bien connu a déclaré que la résolution de problèmes représentait simplement le problème afin que la solution soit la représentation elle-même. Par conséquent, par l'abstraction à l'aide de classes, l'encapsulation à l'aide de modificateurs d'accès et de méthodes, l'héritage pour spécifier la relation et la réutilisation, la composition pour établir la relation et la collaboration entre les classes, le polymorphisme comme moyen de simplifier la détermination de différents comportements dans des objets similaires, la complexité peut être gérée.
Il existe également d'autres façons de gérer la complexité des logiciels, par exemple la programmation logique (Prolog) et fonctionnelle (Haskell).
À un niveau supérieur à la programmation, nous avons besoin de modèles et de principes de conception pour guider la POO. Par conséquent, la POO gère la complexité à un niveau bas (codage) tandis que ces méthodologies telles que les modèles et principes de conception guident la conception de la solution à un niveau supérieur (système et application) et rendent le développement et la gestion des complexités plus faciles à gérer.
Pour répondre à votre question, oui, la POO n'est qu'une solution pour gérer la complexité parmi de nombreuses autres solutions. C'est une solution à un bas niveau. Nous avons besoin de modèles et de principes de conception pour guider la POO à un niveau supérieur.
la source
La programmation orientée objet gère la complexité essentielle et facultative, mais ne la réduit pas non plus.
Je préfère la définition fournie par Eric Steven Raymond dans The Art of Unix Programming , car elle délimite entre complexité essentielle, facultative et accidentelle. http://www.faqs.org/docs/artu/ch13s01.html#id2964646
La POO ne fait rien pour la complexité essentielle ou facultative, elles sont fonction des exigences du programme. Cela peut avoir un effet sur la complexité accidentelle, dans la mesure où vous pouvez parfois créer un design plus élégant avec OOP. Parfois, cependant, la conception est pire lors de l'utilisation de la POO.
la source
Les problèmes complexes ne peuvent pas être simplifiés par la technologie, ils ne peuvent être gérés que par la technologie.
La POO est une technologie, un concept et une façon d'aborder un problème.
La POO vous donne les outils pour appliquer une conception qui peut faciliter la gestion de la complexité, mais vous pouvez tout aussi facilement avoir une mauvaise conception qui augmente votre complexité. En d'autres termes, s'il n'est pas utilisé correctement, vous pouvez avoir une complexité induite par la technologie dans vos problèmes.
Gardez à l'esprit qu'il existe de nombreux autres aspects qui détermineront le succès de votre projet (style de gestion de projet, définition de problème, gestion du changement, etc.). La technologie que vous utilisez n'est pertinente que dans la mesure où elle vous aidera à gérer le problème.
En fin de compte, la programmation orientée objet ne peut pas être une solution à la complexité; c'est juste un outil pour le gérer. (si utilisé correctement)
la source
L'orientation d'objet (telle qu'elle est utilisée de manière conventionnelle) est un outil utile dans de nombreuses circonstances, mais ce n'est pas une solution suffisante à la complexité.
En particulier, cela ajoute souvent beaucoup de « complexité incidente ». Des exemples sont la complexité entourant l'héritage de l'implémentation, la nécessité de fournir beaucoup de "fonctionnalités standard" comme equals () et hashCode () etc. Une belle présentation de Stuart Halloway sur ce sujet: "La simplicité n'est pas facile "
Les objets dans la plupart des langues ont également tendance à encapsuler beaucoup d' états mutables - qui, dans un monde simultané, commencent de plus en plus à ressembler à une mauvaise décision de conception. Encore une fois, une vidéo intéressante de Rich Hickey examine la distinction entre l'identité et l'état de l'objet, et comment ce pourrait être une erreur de confondre les deux.
la source
La programmation orientée objet est une façon de représenter un problème, rien de plus, rien de moins. Il n'est pas moins complexe en soi que tout autre paradigme de programmation. Un système OOP bien conçu gère et réduit la complexité, mais il est également très facile de concevoir un système beaucoup plus complexe que nécessaire et qui gêne tout.
Comme souvent dit de C ++, OOP vous donne assez de corde pour vous pendre.
la source
Je pense que oui , juste parce qu'il vous permet de découper la complexité en petits «blocs de construction» autonomes qui cachent les détails, puis de les utiliser pour créer les fonctionnalités dont vous avez besoin, étape par étape, couche par couche.
Diviser et conquérir.
la source
La POO est une tentative de solution.
La meilleure façon de gérer la complexité est de créer des abstractions. Si je peux transformer mes données en collections utiles, avec des fonctions reconnaissables qui opèrent sur ces collections, je peux commencer à considérer les collections comme des «choses» discrètes. C'est la base des classes et des méthodes. À cet égard, une POO correctement conçue peut aider à gérer la complexité.
Quelque part en cours de route, quelqu'un a décidé que nous pourrions utiliser la POO pour aider à résoudre le problème de la réutilisation du code. Je veux dire, pourquoi réinventer la roue? Si quelqu'un d'autre a fait une grande partie du travail pour résoudre ce problème, tirez parti de ce qu'il a fait, ajoutez les ajustements que votre projet particulier requiert et le tour est joué! Vous avez créé une application puissante et sophistiquée avec relativement peu de travail de votre part. Les programmeurs OO peuvent être des programmeurs très productifs.
Le résultat final est que les programmeurs OO finissent par être des "apprentis sorciers", où ils relient un tas de grandes bibliothèques lourdes avec quelques lignes de "colle" et obtiennent quelque chose qui fonctionne. Sorta. Un peu. La plupart du temps. Y a-t-il des effets secondaires potentiels de l'utilisation de cette bibliothèque avec celle-ci? Peut être. Mais qui a le temps de vraiment fouiller dans le code contenu dans ces bibliothèques? Surtout quand les bibliothèques évoluent. Le résultat est que nous nous retrouvons avec des applications gonflées, où un programmeur avait besoin d'une poignée de classes et de méthodes de cette bibliothèque, mais l'application doit supporter le poids de toutes les AUTRES choses dont elles n'avaient pas besoin.
Le résultat final est que vous vous retrouvez avec beaucoup plus de complexité que nécessaire.
Un autre mécanisme pour gérer la complexité que vous souhaitez séparer des fonctionnalités. Vous voulez que toutes vos fonctions d'accès aux données au même endroit. Vous voulez que toutes vos fonctionnalités d'interface utilisateur en un seul endroit. Vous voulez que tous vos contrôleurs soient au même endroit. Vous créez donc différentes classes qui gèrent différentes parties de la fonctionnalité. Jusqu'ici tout va bien. Et cela évolue, dans une certaine mesure; vos développeurs qui sont compétents avec l'accès aux données peuvent écrire ces classes, vos gens de l'interface utilisateur peuvent écrire les classes de l'interface utilisateur, etc. Tout va bien.
Jusqu'à ce que vous deviez conserver quelque chose écrit par quelqu'un d'autre.
Oui, il est bon de savoir que toutes les fonctions d'accès aux données se trouvent ici. Mais comment les appelle-t-on?
Cette méthode appelle cette méthode sur cette classe. Mais quand je regarde la définition de classe, il n'y a pas de méthode avec ce nom. Oh, c'est hérité de quelque chose d'autre une ou deux couches dans la chaîne d'héritage. Attends une minute; cette classe a implémenté une interface? Combien de classes différentes implémentent cette interface? Et nous utilisons un système d'exécution compliqué (je vous regarde, Spring) pour "relier" des instances de classes au moment de l'exécution? Où N'IMPORTE QUELLE classe qui implémente cette interface peut être utilisée?
Vous vous retrouvez avec plein de petites méthodes discrètes qui font des choses précises. Mais celui-ci l'appelle, dans une autre classe. Qui appelle ça, dans une autre classe. Ce qui appelle ça, dans encore une autre classe. Qui appelle ça, dans une classe supplémentaire. Qui renvoie un résultat d'un type particulier. Sur lequel vous devez appeler une méthode pour faire une certaine chose. Qui renvoie un résultat d'un autre type. Etc.
Il y a un terme pour cela: code spaghetti.
Vous vous retrouvez avec un système très complexe nécessaire juste pour composer le code. D'où les IDE comme Visual Studio, Eclipse et NetBeans. Tous ont une courbe d'apprentissage importante. En effet, beaucoup d'entre eux sont capables d'encapsuler / d'agréger plusieurs outils, développés par différents groupes, chacun ayant sa propre courbe d'apprentissage.
C'est gérer la complexité?
Le débogage du code est deux fois plus difficile que de l'écrire. Bonne chance pour déboguer certains de ces trucs. Surtout s'il utilise plusieurs bibliothèques, "câblées ensemble" au moment de l'exécution en utilisant une sorte de système d'injection de dépendance.
En résumé: la POO fournit ce qui ressemble à un outil prometteur pour aider à gérer la complexité. La réalité est que le code résultant a tendance à être horriblement gonflé (car vous ne pouvez pas extraire uniquement les éléments dont vous avez besoin de toutes ces bibliothèques liées) et vous avez besoin d'outils sophistiqués juste pour naviguer dans le code. Cela devient rapidement un cauchemar de maintenance.
À mon humble avis, c'est une perte nette; il ajoute plus de complexité qu'il n'en élimine. Cela vous permet de faire des choses qui seraient extrêmement difficiles, voire impossibles, sans cela. Mais tout grand projet évolue rapidement en un gâchis impossible à maintenir.
Si vous savez déjà comment cela fonctionne et que vous vous en souvenez, vous pourriez avoir une chance de le maintenir.
N'oubliez pas d'appliquer la loi d'Eagleson: n'importe quel code que vous n'avez pas consulté depuis six mois pourrait tout aussi bien être écrit par quelqu'un d'autre.
la source
Dans une certaine mesure...
Pourquoi? Parce qu'il facilite une modularité très logique. Au moins par rapport à la programmation procédurale où il est trop tentant d'écrire simplement d'énormes piles de code spaghetti.
la source
La raison pour laquelle la programmation orientée objet semble nous aider à gérer la complexité est qu'elle nous oblige à écrire du code d'une manière spécifique au lieu d'une grande variété de façons. La programmation orientée tâche est beaucoup plus intuitive, c'est pourquoi la programmation a commencé de cette façon. L'orientation objet nécessite une formation et une pratique pour comprendre et utiliser efficacement, mais en contraignant la programmation à un certain chemin, elle permet aux personnes formées de maintenir efficacement le code qui a été écrit.
Ce n'est pas plus logique ou réel que toute autre méthode, c'est juste un moyen de concentrer notre résolution de problèmes à travers des lentilles similaires. De nombreuses spécialités techniques utilisent le paradigme d'une méthodologie rigide non intuitive pour gérer la complexité de leurs tâches.
Une troisième méthode pour gérer la complexité serait la programmation fonctionnelle, et il y aura probablement d'autres nouvelles méthodes à l'avenir également.
la source
Je pense que c'est plus une solution pour la maintenabilité, car, en tant que programmeur, vous êtes censé mettre des méthodes là où vous avez les données, créant ainsi un modèle objet de votre application.
oui, c'est aussi une solution à la complexité en vous fournissant un modèle pour "voir" votre code de manière naturelle, comme des objets qui ont des propriétés et des actions possibles
la source