Avons-nous vraiment besoin des langages OO pour gérer la complexité logicielle?

209

Ce sera une question très peu technique et douce et je ne suis pas sûr que ce soit la bonne plate-forme. Mais je suis un étudiant débutant en CS, alors j'espère que vous allez le tolérer.

Au cours du premier semestre, nous avons découvert les concepts de la programmation orientée objet tels que l'encapsulation, le masquage des données, la modularité, l'héritage, etc. via Java et UML. (Java est mon premier langage de programmation)

Si je comprends bien, la programmation orientée objet est un moyen de gérer la complexité des logiciels. Mais ses principes ne sont ni nouveaux ni uniques, ils sont en un sens universels pour tous les domaines de l'ingénierie.

Par exemple, une voiture est une structure très complexe dont la complexité est gérée par une hiérarchie de composants modulaires et encapsulés avec des comportements et des interfaces bien définis.

Mais je ne comprends pas la raison de l’introduction d’un nouveau paradigme de programmation. Je pense que tous les principes utilisés pour gérer la complexité peuvent être réalisés par les langages de programmation procéduraux. Par exemple, pour la modularité, nous pouvons simplement diviser le programme en plusieurs petits programmes qui exécutent des tâches bien définies dont le code est contenu dans des fichiers séparés. Ces programmes interagiraient les uns avec les autres grâce à leurs entrées et sorties bien définies. Les fichiers peuvent être protégés (cryptés?) Pour réaliser l’encapsulation. Pour la réutilisation du code, nous pouvons simplement appeler ces fichiers quand ils sont nécessaires dans de nouveaux programmes. Cela ne reflète-t-il pas tout ce qu'est la POO ou manque-t-il quelque chose de très évident?

Je ne demande pas de preuve que la POO gère la complexité. À mon avis, c'est le cas. Mais je pense que tous les principes utilisés pour gérer la complexité, tels que la modularité, l’encapsulation, la dissimulation de données, etc., peuvent être très facilement mis en œuvre par les langages procéduraux. Alors, pourquoi vraiment OOP si nous pouvons gérer la complexité sans elle?

échange de steak
la source
41
Il vous manque la séparation entre interface et implémentation. Etre capable de permuter une implémentation pour une autre lors de l'exécution est une fonctionnalité très importante. En gros, ceci est réalisé par la méthode dynamique de dispatching des langages OO avec héritage. Les langages procéduraux peuvent aussi le faire (lire: pointeurs vides), mais sans sécurité.
Marstato
81
Dans une large mesure, l'idée des langages et de la conception orientés objet vise précisément à rendre ces concepts universels et intuitifs aussi faciles que possible à représenter et à reproduire en code. Si vous aviez un schéma ou un ensemble de directives sur la manière de réaliser toutes ces choses sans un langage intrinsèquement orienté objet, vos propositions sur la manière de faire les choses seraient effectivement la méthodologie orientée objet utilisée. Les langues OO réelles ne sont qu'un moyen de formaliser et de simplifier cela.
Standback
14
@RobbieDee avez-vous lu ma question? Il s'agit d'essayer de comprendre OO à un niveau plus fondamental en posant des questions sur le fait que la complexité du logiciel peut être gérée sans OO. Je ne cherche pas à saper OO, ni à inventer quelque chose de nouveau, mais simplement à mieux le comprendre et si la question est si évidente, pourquoi a-t-il reçu l'excellente réponse de Jorg?
steakexchange
12
Le cryptage d'un fichier n'est pas une encapsulation. Vous avez peut-être masqué le fait de voir le contenu du code d'un autre développeur, mais vous n'avez pas nécessairement protégé le fonctionnement interne du code d'un autre code. L'auteur d'origine pourrait le faire avant ou après le chiffrement s'il peut se rappeler comment.
JeffO
8
Vous n'avez besoin de rien d'autre que du langage machine - laissez le programmeur mémoriser les opcodes et écrire les uns et les zéros lui-même. Mais avoir une sorte de langage "symbolique" est très utile en termes de réduction des erreurs et d’augmentation de la productivité, et, comme Dijkstra l’a observé, un langage qui impose une "structure" (ou au moins facilite le maintien de "structure") aide considérablement. Les langages OO ne sont peut-être pas la technologie idéale, compte tenu du niveau actuel de sophistication des langages, mais ils conviennent plutôt à de nombreuses applications. L'idée est de gérer la complexité sans vous gêner.
Daniel R Hicks

Réponses:

177

Laissez-moi essayer avec une réponse très basse théorie :)

Ce que vous demandez réellement, c'est: Pourquoi inclure la prise en charge de l'Object Object Orientation (OO) directement dans le langage quand des langages procéduraux peuvent être utilisés pour concevoir et écrire du code OO?

Et la réponse est: avoir un standard pour la façon dont OO est exprimé dans le code source afin de ne pas vous retrouver avec 22 implémentations différentes pour la même abstraction.

Par exemple, disons que je crée un MagicButtonet un MagicSliderqui peut être utilisé dans un système d'interface utilisateur. Il me faut un moyen de regrouper les méthodes utilisables avec MagicButton, celles qui ne peuvent être utilisées qu'avec MagicSlider et les méthodes pouvant être utilisées par les deux. Ces objets partagent certaines méthodes car ils sont tous deux des objets gui magiques.

Je peux faire le regroupement en nommant des fonctions de manière spéciale MagicSlider_DoSomething ..., en incluant les méthodes dans des fichiers spécifiques nommés de manière spéciale MagicSliderMethods.XXX, ou je pourrais trouver un autre moyen spécial de faire la même chose. S'il n'y a pas de moyen standard dans la langue de le faire, je le ferai différemment de vous et de quiconque. Cela rend le partage de code beaucoup plus difficile.

Oui, l'envoi tardif (méthodes virtuelles dans les langages OO) peut être implémenté dans les langages procéduraux, mais il existe de nombreuses façons de l'implémenter. En fonction de l'auteur du code, vous obtiendrez différentes implémentations d'OO dans le même programme.

Pensez au mauvais développeur de maintenance. Cette personne doit gérer différentes abstractions d'objet et différentes manières d'appeler des méthodes virtuelles en fonction de l'auteur du code d'origine.

De plus: le fait d'avoir les abstractions dans le langage permet aux éditeurs de code avancés tels qu'Eclipse de faire beaucoup d'analyses statiques sur le code. Par exemple, Eclipse peut proposer une liste de toutes les méthodes pouvant être utilisées sur un objet, ainsi que l'implémentation automatique de "méthodes TODO" vides. Eclispe sait exactement quelles méthodes votre classe doit implémenter en fonction des classes que vous étendez et des interfaces que vous implémentez. Cela serait presque impossible s’il n’existait pas de norme linguistique pour faire de l’OA.

Tandis que
la source
40
Exemple classique: Lua. Ce n'est pas nativement OO, mais on peut le faire, mais cela signifie qu'il y a environ 5 bibliothèques OO différentes et tout aussi connues qui ne sont pas entièrement interopérables.
Kroltan
55
@steakexchange Vous vous concentrez trop sur les absolus. Très peu a un "seul but". Les langues font toutes beaucoup de choses différentes à différents degrés de qualité. Choisir une langue, c'est choisir l'ensemble des compromis qui conviennent le mieux à l'objectif pour lequel vous en avez besoin.
Tim B
42
@nocomprende Normaliser les abstractions est littéralement à quoi servent les langages de programmation. Même le langage d'assemblage résume les différences entre dix générations de matériel informatique au cours d'une décennie et demie.
David Moles
56
@DavidMoles Les abstractions standardisées sont littéralement ce que sont les langages de programmation. Ne perdez pas une occasion parfaite d'utiliser "littéralement" littéralement!
Clement Cherlin
12
Il est possible de normaliser cela. Lorsque j'étais à l'université, au milieu des années 90, j'ai effectué un travail assez considérable sous X-Windows (principalement basé sur Motif, pour ceux qui se souviennent de ce genre de choses). X-Windows vous a effectivement permis d’implémenter toutes les fonctionnalités d’orientation des objets en C normal . La gymnastique mentale nécessaire était cependant assez importante et reposait sur les personnes qui ne regardaient pas à l'intérieur de la surface (à ce moment-là, le code du widget de Schroedinger finissait généralement par être mort). Les langages OO cachent cela aux codeurs, comme le fait un compilateur classique pour les assembleurs, et la vie est plus facile.
Graham
211

Au cours du premier semestre, nous avons découvert les concepts de la programmation orientée objet tels que l'encapsulation, le masquage des données, la modularité, l'héritage, etc. via Java et UML. (Java est mon premier langage de programmation)

Aucun de ceux-ci ne sont des concepts de POO. Ils existent tous en dehors de OO, indépendamment de OO et beaucoup ont même été inventés avant OO.

Donc, si vous pensez que c'est ça le but de OO, alors votre conclusion est juste: vous pouvez faire tout cela dans des langages procéduraux, car ils n'ont rien à voir avec OO .

Par exemple, l’un des principaux articles sur la modularité concerne les critères à utiliser pour la décomposition de systèmes en modules . Il n'y a aucune mention de OO là-dedans. (Il a été écrit en 1972, alors que OO était encore un créneau obscur, alors qu’il avait déjà plus de dix ans.)

Bien que l’ abstraction de données soit importante pour l’OA, c’est davantage une conséquence de la principale caractéristique de OO (messagerie) qu’elle est déterminante. En outre, il est très important de se rappeler qu’il existe différents types d’abstraction de données. Les deux types d'abstraction de données les plus couramment utilisés aujourd'hui (si nous ignorons "aucune abstraction", qui est probablement encore plus utilisé que les deux autres combinés), sont les types de données abstraits et les objets . Donc, juste en disant « Hiding information », « Encapsulation » et « Data Abstraction », vous avez rien dit sur OO, puisque OO est seulement une forme d'abstraction de données, et les deux sont en fait fondamentalement différentes:

  • Avec les types de données abstraits, le mécanisme d’abstraction est le système de types ; c'est le système de types qui cache l'implémentation. (Le système de types ne doit pas nécessairement être statique.) Avec Objects, l'implémentation est cachée derrière une interface procédurale , qui ne nécessite pas de types. (Par exemple, il peut être implémenté avec des fermetures, comme dans ECMAScript.)
  • Avec les types de données abstraits, les instances de différents types de TDA sont encapsulées les unes par rapport aux autres, mais les instances du même TDA peuvent inspecter et accéder à la représentation et à l'implémentation privée de l'autre. Les objets sont toujours encapsulés de tout . Seul l'objet lui-même peut inspecter sa propre représentation et accéder à sa propre implémentation privée. Aucun autre objet , pas même d'autres objets du même type, d'autres instances de la même classe, d'autres objets ayant le même prototype, des clones de l'objet ou quoi que ce soit ne peut le faire. Aucun .

Soit dit en passant, cela signifie qu'en Java, les classes ne sont pas orientées objet. Deux instances de la même classe peuvent accéder à la représentation et à l'implémentation privée de l'autre. Par conséquent, les instances de classes ne sont pas des objets, elles sont en fait des instances ADT. Java interfaces, cependant, ne fournir abstraction de données orientée objet. Donc, en d'autres termes: seules les instances d'interfaces sont des objets en Java, les instances de classes ne le sont pas.

Fondamentalement, pour les types, vous ne pouvez utiliser que des interfaces. Cela signifie que les types de paramètres de méthodes et de constructeurs, les types de méthodes retournés, les types de champs d'instance, les champs statiques et les champs locaux, l'argument d'un instanceofopérateur ou d'un opérateur de conversion et les arguments de type d'un constructeur de type générique doivent toujours être des interfaces. Une classe ne peut être utilisée que directement après l' newopérateur, nulle part ailleurs.

Par exemple, pour la modularité, nous pouvons simplement diviser le programme en plusieurs petits programmes qui exécutent des tâches bien définies dont le code est contenu dans des fichiers séparés. Ces programmes interagiraient les uns avec les autres grâce à leurs entrées et sorties bien définies. Les fichiers peuvent être protégés (cryptés?) Pour réaliser l’encapsulation. Pour la réutilisation du code, nous pouvons simplement appeler ces fichiers quand ils sont nécessaires dans de nouveaux programmes. Cela ne reflète-t-il pas tout ce qu'est la POO ou manque-t-il quelque chose de très évident?

Ce que vous décrivez est OO.

C'est en effet une bonne façon de penser à OO. En fait, c'est à peu près exactement ce que les inventeurs originaux d'OO avaient en tête. (Alan Kay est allé un peu plus loin: il a envisagé de nombreux ordinateurs se transmettant des messages via le réseau.) Ce que vous appelez "programme" est généralement appelé "objet" et au lieu de "appel", nous disons habituellement "envoyer un message" ".

L'orientation des objets est entièrement centrée sur la messagerie (également appelée répartition dynamique ). Le terme "orienté objet" a été inventé par Alan Kay, concepteur principal de Smalltalk, et il le définit ainsi :

La POO pour moi ne signifie que la messagerie, la rétention et la protection locales et le masquage du processus d'état, et la liaison tardive extrême de toutes choses.

Décomposons cela:

  • messagerie ("envoi de méthode virtuelle", si vous n'êtes pas familier avec Smalltalk)
  • processus d'état devrait être
    • conservé localement
    • protégé
    • caché
  • liaison tardive extrême de toutes choses

En ce qui concerne l'implémentation, la messagerie est un appel de procédure à liaison tardive, et si les appels de procédure sont à liaison tardive, vous ne pouvez pas savoir au moment de la conception comment vous allez appeler, vous ne pouvez donc pas émettre d'hypothèses sur la représentation concrète de l'état. Donc, en réalité, il s’agit de messagerie, la liaison tardive est une implémentation de la messagerie et l’encapsulation en est la conséquence.

Il a ensuite précisé que " la grande idée est la" messagerie " " et regrette de l'avoir appelée "orientée objet" au lieu de "orientée message", car le terme "orienté objet" met l'accent sur l'élément sans importance (objets ) et distrait de ce qui est vraiment important (messagerie):

Juste un rappel gentil que j’ai pris quelques efforts lors du dernier OOPSLA pour essayer de rappeler à tout le monde que Smalltalk n’est PAS seulement sa syntaxe ou sa bibliothèque de classes, il ne s’agit même pas de classes. Je suis désolé, il y a longtemps que j'ai inventé le terme "objets" pour ce sujet, car beaucoup de gens se concentrent sur la moindre idée.

La grande idée est la "messagerie" - c’est l’objet même de Smalltalk / Squeak (et c’est quelque chose qui n’a jamais été complètement achevé au cours de la phase PARC de Xerox). Les Japonais ont un petit mot - ma - pour "ce qui est entre les deux" - peut-être l'équivalent anglais le plus proche est "interstitiel". La clé pour créer des systèmes performants et évolutifs réside bien plus dans la conception de la façon dont ses modules communiquent que sur leurs propriétés et leurs comportements internes. Pensez à Internet - pour vivre, il (a) doit permettre différents types d’idées et de réalisations qui dépassent toutes les normes et (b) permettre un degré variable d’interopérabilité en toute sécurité entre ces idées.

(Bien sûr, aujourd'hui, la plupart des gens ne se concentrent même pas sur des objets mais sur des classes, ce qui est encore plus faux.)

La messagerie est fondamentale pour OO, à la fois en tant que métaphore et en tant que mécanisme.

Si vous envoyez un message à quelqu'un, vous ne savez pas ce qu'il en fait. La seule chose que vous pouvez observer, c'est leur réponse. Vous ne savez pas s'ils ont traité le message eux-mêmes (c'est-à-dire si l'objet a une méthode), s'ils ont transmis le message à quelqu'un d'autre (délégation / proxy), s'ils l'ont même compris. C’est ce que l’encapsulation est, l’objet OO. Vous ne pouvez même pas distinguer un proxy de la réalité, tant qu'il répond à vos attentes.

Un terme plus "moderne" pour "messagerie" est "envoi de méthode dynamique" ou "appel de méthode virtuelle", mais il perd la métaphore et se concentre sur le mécanisme.

Il y a donc deux façons de regarder la définition d'Alan Kay: si vous la regardez seule, vous remarquerez peut-être que la messagerie est essentiellement un appel de procédure à liaison tardive et que la liaison tardive implique une encapsulation, ce qui permet de conclure que # 1 et # 2 sont en fait redondants, et OO est tout au sujet de la liaison tardive.

Cependant, il a plus tard précisé que l’important était la messagerie, et nous pouvons donc la regarder sous un angle différent: la messagerie est en retard. Maintenant, si la messagerie était la seule chose possible, alors le n ° 3 serait trivialement vrai: s'il n'y a qu'une seule chose, et que cette chose est en retard, toutes les choses sont en retard. Et encore une fois, l’encapsulation découle de la messagerie.

Des points similaires sont également présentés dans le document intitulé Comprendre l'abstraction des données, revisité par William R. Cook, ainsi que dans sa proposition de définitions modernes et simplifiées des termes "objet" et "orienté objet" :

La répartition dynamique des opérations est la caractéristique essentielle des objets. Cela signifie que l'opération à appeler est une propriété dynamique de l'objet lui-même. Les opérations ne peuvent pas être identifiées statiquement, et il n’ya généralement aucun moyen de [savoir] exactement quelle opération sera exécutée en réponse à une demande donnée, sauf en l’exécutant. C'est exactement la même chose que pour les fonctions de première classe, qui sont toujours distribuées dynamiquement.

Dans Smalltalk-72, il n'y avait même pas d'objets! Il n'y avait que des flux de message qui a obtenu analysables, réécrite et réacheminés. Les premières méthodes sont venues (méthodes standard pour analyser et rediriger les flux de messages), puis les objets (groupes de méthodes qui partagent un état privé). L'héritage est venu beaucoup plus tard, et les classes n'ont été introduites que comme un moyen de supporter l'héritage. Si le groupe de recherche de Kay était déjà au courant des prototypes, ils n'auraient probablement jamais introduit de cours.

Benjamin Pierce, dans Types et langages de programmation, affirme que la caractéristique qui définit l’objet Orientation est la récursion ouverte .

Donc: selon Alan Kay, OO est tout sur la messagerie. Selon William Cook, OO concerne la répartition dynamique des méthodes (ce qui est en réalité la même chose). Selon Benjamin Pierce, OO est une affaire de récursivité ouverte, ce qui signifie essentiellement que les auto-références sont résolues de manière dynamique (ou du moins que c'est une façon de penser), ou, en d'autres termes, la messagerie.

Comme vous pouvez le constater, la personne qui a inventé le terme "OO" a une vision plutôt métaphysique des objets, Cook a une vision plutôt pragmatique et Pierce une vision mathématique très rigoureuse. Mais l’important est que le philosophe, le pragmatiste et le théoricien soient tous d’accord! La messagerie est le seul pilier de OO. Période.

Notez qu'il n'y a aucune mention d'héritage ici! L'héritage n'est pas essentiel pour OO. En général, la plupart des langages OO ont un moyen de réutiliser une implémentation, mais cela ne doit pas nécessairement être un héritage. Cela pourrait aussi être une forme de délégation, par exemple. En fait, le Traité d’Orlando examine la délégation comme une alternative à l’héritage et explique comment les différentes formes de délégation et d’héritage conduisent à différents points de conception dans l’espace de conception des langages orientés objet. (Notez qu'en réalité, même dans les langages qui supportent l'héritage, comme Java, les gens apprennent à l'éviter, ce qui indique encore une fois que ce n'est pas nécessaire pour OO.)

Jörg W Mittag
la source
16
+100 - Nous accusons les choses de manière inhérente parce qu'elles sont mal utilisées.
JeffO
55
Désolé, mais c'est incroyablement faux. Alan Kay a peut-être inventé le terme, mais les principes existaient avant Smalltalk. La programmation orientée objet dérive de Simula et son style orienté objet n'a rien à voir avec les "messages". Presque tous les langages OO qui ont réussi ont suivi les principes de base énoncés dans Simula - les mêmes que ceux de Java - et le style OO de Smalltalk a été un échec sur le "marché des idées" chaque fois qu'il est réintroduit, parce que ça ne marche pas du tout. Le nom était la seule chose vraiment significative que Kay a contribué.
Mason Wheeler
23
@steakexchange No. "L'essence de OO," ce qui le rend vraiment distinctif, ce sont les objets avec des méthodes virtuelles. Il y a une raison pour laquelle personne n'utilise Smalltalk: le système de transmission de messages fonctionne très mal à l'échelle d'un ordinateur individuel. Chaque fois qu'un concepteur de langage bien intentionné mais naïf essaie de réimplémenter les principes de Smalltalk, cela échoue. (L’exemple le plus récent serait Objective-C, que personne n’aurait jamais utilisé si Steve Jobs ne l’avait pas rejetée dans l’ensemble de la communauté iOS. Elle n’a jamais trouvé de lien avec l’écosystème Apple, et il ya une raison à cela. )
Mason Wheeler
28
@MasonWheeler Pourriez-vous préciser votre commentaire dans une réponse puisque vous avez un point de vue totalement opposé à ce que dit Jorg?
échange de steak
20
Il convient également de noter que le concept de langues orientées objet a beaucoup évolué. Ces concepts ancestraux ne sont peut-être plus aussi vrais de nos jours, car de nombreux langages abandonnent les anciens modèles et englobent des paradigmes multiples. Regardez C #, par exemple - ce langage mélange presque tout sous le soleil en même temps et, bien que référencé principalement comme langage OO, il est en réalité un mélange de paradigmes différents. Cela lui permet d'être un outil vraiment expressif pour les développeurs tout autour. En outre, l'OO basé sur les classes est l'un des nombreux types de programmation OO tout aussi valables.
T. Sar
66

Mais je pense que tous les principes utilisés pour gérer la complexité, tels que la modularité, l’encapsulation, la dissimulation de données, etc., peuvent être très facilement mis en œuvre par les langages procéduraux.

Lorsque vous dites "très facilement", vous faites une déclaration très audacieuse. La façon dont je l'ai lu est: "Je ne vois pas la difficulté, alors ça ne doit pas être très gros." Lorsque vous le formulez ainsi, il devient clair que vous ne demandez pas "pourquoi avons-nous besoin d'OO", mais "pourquoi les difficultés rencontrées par les autres paradigmes de programmation qui ont conduit à l'invention d'OO ne sont-elles pas immédiatement apparentes? "

Une réponse à cette question est que bon nombre de ces difficultés n'existent pas dans les types de programmes sur lesquels vous travaillez. On ne vous demande pas de mettre à jour du code spaghetti vieux de 40 ans. Vous n'essayez pas d'écrire un nouveau gestionnaire d'affichage pour un système d'exploitation. Vous ne déboguez pas d'applications distribuées multithreads.

Pour beaucoup de types de programmes de jouets que nous, les étudiants CS, sommes chargés d’écrire, nous pourrions aussi bien les écrire en BASIC ou les assembler que Java ou Python. En effet, la complexité inhérente des tâches est si faible, il n'y a qu'un seul développeur, il n'y a pas de problèmes d'interopérabilité hérités, les performances importent peu et le code ne sera probablement exécuté que très peu de fois sur une seule machine.

Imaginez que vous preniez un élève conducteur et lui demandiez de se joindre à une rue animée aux heures de pointe, avec une boîte de vitesses manuelle sans synchro, en montant une colline abrupte. Catastrophe. Pourquoi? Ils sont incapables de gérer le niveau de complexité requis pour respecter simultanément toutes les règles requises par la tâche.

Maintenant, imaginez le même élève, le même véhicule, conduisant à une vitesse de marche dans un parking vide. Ils vont bien parce que leur niveau de compétence est adapté à la tâche. Il n'y a pas de pression, peu de risque, et ils peuvent prendre les sous-tâches individuelles de démarrage, embrayage, changement de vitesse, accélération, direction, une à la fois.

Cet étudiant pourrait demander pourquoi nous avons des transmissions automatiques, si un conducteur qualifié peut faire toutes ces choses en même temps? La réponse est qu’un pilote suffisamment qualifié n’a pas besoin d’un système automatique dans des conditions optimales. Mais nous ne sommes pas tous des pilotes professionnels en pleine forme, et nous souhaitons généralement que les concepteurs de la voiture prennent en charge toute cette complexité.

Un programmeur assez expérimenté et discipliné peut en effet créer un système très complexe fonctionnant en C ou en assembleur. Mais nous ne sommes pas tous Linus Torvalds. Nous ne devrions pas non plus être obligés de créer des logiciels utiles.

Je n'ai personnellement aucun intérêt à devoir réinventer toutes les fonctionnalités d'un langage moderne avant même de pouvoir résoudre le problème. Si je peux tirer parti d'un langage qui inclut des solutions à des problèmes déjà résolus, pourquoi ne le ferais-je pas?

Je vais donc retourner votre question et vous demander si les langages fournissent des fonctionnalités pratiques comme l’encapsulation et le polymorphisme, pourquoi ne devrions-nous pas les utiliser?

Clément Cherlin
la source
13
Donc, fondamentalement, il est possible de faire de l’utilisation directe avec un langage procédural, mais le fait de procéder manuellement tout en utilisant un langage d’utilisation normalisé automatise et simplifie.
échange de steak
6
@steakexchange C'est à peu près cela.
Tim B
3
@steakexchange est un bon exemple historique: le modèle d'objet de X Windows à l'époque. Il était écrit en C mais reposait sur un système orienté objet. Donc, vous deviez suivre certaines conventions pour interfacer avec elle afin que vos classes jouent bien avec celles des autres.
Ukko
7
@nocomprende Certainement. Mais on peut rendre son ordinateur non démarrable en faisant des écritures sur disque au lieu de s’appuyer sur le système de fichiers, et il sera vraiment difficile de résoudre les problèmes dans un système d’objets ad-hoc construit par un novice. L’encapsulation, quand elle est faite correctement, nous empêche de nous ingérer, intentionnellement ou non, avec des choses que nous ne devrions pas.
Clement Cherlin
3
Il est intéressant pour moi que les exemples que vous donnez d'applications pouvant tirer profit de OO ne soient souvent pas écrits dans des langages OO. Le spaghetti de 40 ans est probablement écrit en C, COBOL, FORTRAN ou REXX. Le gestionnaire d'affichage est probablement écrit en C (bien qu'avec des conventions OO-ish), et de nombreux systèmes multithread distribués à succès sont écrits en Erlang, Go ou C.
James_pic
22

Ce que vous décrivez n'est pas de la programmation orientée objet, c'est de l'abstraction. L'abstraction est présente dans tous les modèles de conception modernes, même ceux qui ne sont pas la POO. Et la POO est un type d'abstraction très spécifique.

Tout d’abord, il convient de noter qu’il n’existe pas de définition unique de la programmation orientée objet. Il se peut donc que certaines personnes ne soient pas d’accord avec ce que je qualifie de programmation orientée objet.

Deuxièmement, il est important de rappeler que la programmation orientée objet a été inspirée par les modèles de conception traditionnels. Les similitudes avec la conception des voitures ne sont donc pas une coïncidence.

Cependant, voici comment la POO est plus nuancée que ce que vous avez dit:

  • Encapsulation: il ne s'agit pas simplement d'avoir une interface définie pour un module (c'est-à-dire une abstraction), il s'agit d'interdire l'accès au-delà de cette interface. En Java, accéder à une variable privée est une erreur de compilation, alors que dans la conception de votre voiture, vous pouvez (dans certains cas) utiliser les choses d’une manière différente de l’interface souhaitée.

  • Héritage: C'est vraiment ce qui rend la POO unique. Une fois que vous avez défini une interface, vous pouvez créer plusieurs choses pour la mettre en œuvre. Vous pouvez le faire de manière hiérarchique, en modifiant des parties spécifiques de leur implémentation, tout en héritant de toutes les parties précédentes, ce qui réduit considérablement la duplication de code.

    Si vous pensez en termes de composants encapsulés d'une voiture, il n'y a pas vraiment d'équivalent à ceci. Il n'y a pas moyen pour moi de passer à la vitesse supérieure en passant à une autre vitesse et en modifiant une partie spécifique de sa mise en œuvre. (Au moins, je ne pense pas, je ne sais pas grand chose des voitures).

  • Polymorphisme : une fois que vous avez défini une interface, il est impossible de distinguer tout élément utilisant cette interface, du point de vue des opérations disponibles, et vous n'avez pas besoin de savoir quelle implémentation est utilisée pour utiliser une interface. C’est là que le sous-typage et le principe de substitution de Liskov deviennent importants.

  • Couplage : Un aspect clé de la programmation orientée objet est que nous associons étroitement les choses avec les mêmes opérations et que nous étendions les différentes formes qu’elles peuvent avoir. Les données sont regroupées avec des opérations sur ces données. Cela signifie qu'il est très facile d'ajouter une nouvelle forme de données (une nouvelle implémentation), mais qu'il est très difficile d'ajouter une nouvelle opération à une interface (car vous devez mettre à jour chaque classe qui implémente l'interface). Cela contraste avec les types de données algébriques des langages fonctionnels, où il est très facile d’ajouter une nouvelle opération (vous écrivez simplement une fonction qui traite tous les cas), mais difficile d’ajouter une nouvelle variante (car vous devez ajouter une nouvelle cas à toutes vos fonctions).

jmite
la source
1
Bonne réponse! Une partie avec laquelle je ne suis pas d'accord: la distinction que vous établissez à propos de l'encapsulation n'est pas valide. Encapsulation signifie toujours "interdire l'accès au-delà de cette interface" - cela s'applique aussi bien aux paramètres OOP qu'aux paramètres non-OOP. Donc, cette partie n'est pas vraiment quelque chose qui est unique à la programmation orientée objet.
DW
@DW J'ai essayé de clarifier cela, en disant non pas que c'est unique à la POO, mais que c'est la différence entre encapsulation et abstraction. Merci pour les commentaires!
Jmite
2
D'ACCORD. Mais j’ai toujours un point de vue différent sur ce qui est écrit ici à ce sujet. Vous avez écrit que "voici certains aspects de la programmation orientée objet est plus nuancée que ce que vous avez dit", mais l'encapsulation n'est pas une manière pour que la programmation orientée objet soit plus nuancée que ce qui était écrit dans la question. L'encapsulation est ce qu'elle est, dans n'importe quel paradigme. Et là où vous avez écrit que "Ce que vous décrivez n'est pas de la POO, c'est de l'abstraction", je pensais que la question initiale cherchait à décrire l'encapsulation (pas seulement l'abstraction). Je suppose que je vais laisser ce commentaire dans une perspective différente. Je pense que la réponse est très utile!
DW
L'héritage est une caractéristique commune, mais il manque à plusieurs langues OO importantes.
Bradd Szonye
Bonne réponse, mais à notre connaissance, vous exagérez l'exemple de la voiture. Un moteur pour un modèle donné a une interface bien définie (arbre à cames, support de montage "réceptacles", etc.). Vous pouvez remplacer un vieux carburateur ordinaire par un autre à injection de carburant, ajouter un turbocompresseur, etc. sans affecter la transmission. (Bien qu'un moteur diesel nécessite un réservoir de carburant modifié IIRC.) À l'inverse, vous pouvez remplacer une transmission manuelle par une transmission automatique et AFAIK n'affectant en rien le moteur.
David
11

Avons-nous vraiment besoin des langages OO pour gérer la complexité logicielle?

Cela dépend de la signification du mot "besoin".

Si "besoin" signifie besoin, non, nous n'en avons pas besoin.

Si "besoin" signifie "procure de solides avantages", alors je dirais "Oui", nous le désirons.

Grande image

Les langages OO lient la fonctionnalité aux données.

Vous pouvez éviter cette liaison et écrire des fonctions qui transmettent des valeurs de données.

Mais alors, vous allez probablement vous retrouver avec des constellations de données qui vont ensemble, et vous allez commencer à transmettre des n-uplets, des enregistrements ou des dictionnaires de données.

Et en réalité, tous les appels de méthode sont: des fonctions partielles sur des ensembles de données liés.

Caractéristique par caractéristique

Caractéristiques de la POO:

  • L'héritage permet la réutilisation de code (mixins) et de concept (classes de base abstraites / interfaces) - mais vous pouvez l'obtenir en redécorant des fonctions et des variables dans un sous-périmètre.
  • L'encapsulation permet de cacher des informations afin que nous puissions travailler à des niveaux d'abstraction plus élevés - mais vous pouvez le faire avec des fichiers d'en-tête, des fonctions et des modules.
  • Le polymorphisme nous permet d'utiliser des arguments de types différents tant qu'ils supportent les mêmes interfaces, mais nous pouvons également le faire avec des fonctions.

Cependant, aucune de ces choses ne se produit aussi facilement qu'avec un langage orienté objet avec un support de première classe de ces fonctionnalités.

Références

Il y a beaucoup de critiques de la programmation orientée objet .

Cependant, des études semblent indiquer que la réutilisation de code via la POO améliore la productivité des programmeurs. Cette découverte est controversée et certains chercheurs affirment qu’ils ne peuvent pas reproduire ces gains de productivité compte tenu de certaines contraintes. (la source)

Conclusion

Nous n'avons pas "besoin" de la POO. Mais dans certains cas, l'utilisateur veut la POO.

Je crois comprendre que les programmeurs matures peuvent être assez productifs dans le style orienté objet. Et lorsque les packages ont des objets de base dotés d'interfaces simples et faciles à comprendre, même les nouveaux programmeurs peuvent devenir très productifs rapidement.

Aaron Hall
la source
10

J'essaierai d'être bref.

Le principe de base de OO est la combinaison de données et de comportement dans une seule unité organisationnelle (un objet).

C’est ce qui nous permet de contrôler la complexité et c’était un concept assez novateur lorsqu’il est apparu. Comparez cela aux fichiers d'une part (données pures), aux programmes qui les lisent et les traitent d'autre part (logique pure) et à la sortie (encore des données pures).

Une fois que vous avez réuni ce paquet de données et cette logique, en modélisant une entité réelle, vous pouvez commencer à échanger des messages, créer des classes enfants, séparer les données et les comportements privés des données et comportements publics, implémenter un comportement polymorphe, effectuer toute cette magie propre à OO.

Donc, oui, OO est un gros problème. Et non, ce n'est pas juste un tas de vieux trucs avec un nom de fantaisie.

Tout casser, regarder les éléments, puis dire «ah, ben, il n’ya rien que je n’ai jamais vu», c’est ne pas reconnaître l’assemblée qui détient l’innovation. Le résultat est plus que la somme de ses parties.

Martin Maat
la source
8

Il n'y a pas de définition "officielle" de la programmation orientée objet, et des personnes raisonnables ne sont pas d'accord sur ce qui définit réellement la qualité de OO. Certains disent que la messagerie, d'autres le sous-typage, certains l'héritage, d'autres le groupement de données et de comportements. Cela ne veut pas dire que le terme n'a pas de sens, mais simplement que vous ne devriez pas vous perdre dans des querelles sur ce qu'est le vrai OO.

L'encapsulation et la modularité sont des principes de conception plus fondamentaux et devraient être appliqués à tous les paradigmes de programmation. Les partisans de l'OO ne prétendent pas que ces propriétés ne peuvent être obtenues qu'avec de l'OO, mais seulement que l'OO est particulièrement bien adapté à cet objectif. Bien entendu, les partisans d’autres paradigmes comme la programmation fonctionnelle affirment la même chose pour leur paradigme. Dans la pratique, de nombreuses langues réussies sont multi-paradigmes et le langage OO, fonctionnel, etc., doivent être considérés comme des outils plutôt que comme une "solution unique".

Je pense que tous les principes utilisés pour gérer la complexité peuvent être réalisés par les langages de programmation procéduraux.

C'est vrai, car à la fin, vous pouvez tout faire dans n'importe quel langage de programmation. Cela pourrait être plus facile dans certaines langues que dans d'autres, car toutes les langues ont des forces et des faiblesses différentes.

JacquesB
la source
7

Quelque chose que les autres réponses n'ont pas mentionné: l'état.

Vous parlez de OO en tant qu'outil de gestion de la complexité . Quelle est la complexité? C'est un terme flou. Nous avons tous ce sens gestalt de ce que cela signifie, mais il est plus difficile de le cerner. Nous pourrions mesurer la complexité cyclomatique, c'est-à-dire le nombre de chemins d'exécution dans le code, mais j'ignore si c'est ce dont nous parlons lorsque nous utilisons OO pour gérer la complexité.

Je pense que nous parlons de la complexité liée à l’état.

Il y a deux idées principales derrière l’ encapsulation . L'un d'eux, la dissimulation de détails de mise en œuvre , est assez bien couvert dans les autres réponses. Mais un autre cache son état d' exécution . Nous ne marchons pas avec les données internes des objets; nous transmettons des messages (ou des méthodes d’appel si vous préférez les détails d’implémentation au concept, comme l'a souligné Jörg Mittag). Pourquoi?

Les gens ont déjà mentionné que c'est parce que vous ne pouvez pas modifier la structure interne de vos données sans modifier le code, mais vous voulez le faire à un endroit (la méthode d'accès) au lieu de 300.

Mais c'est aussi parce que cela rend le code difficile à raisonner : le code de procédure (que ce soit dans un langage de procédure ou simplement écrit dans ce style) aide peu à imposer des restrictions à la mutation d'état. Tout peut changer à tout moment et de n'importe où. Les fonctions / méthodes d’appel peuvent avoir une action fantasmagorique à distance. Le test automatisé est plus difficile, car le succès des tests est déterminé par la valeur des variables non locales largement utilisées / accessibles.

Les deux autres grands paradigmes de programmation (OO et fonctionnel) offrent des solutions intéressantes, mais presque diamétralement opposées, au problème de la complexité liée à l'état. En programmation fonctionnelle, on essaie de l'éviter complètement: les fonctions sont généralement pures, les opérations sur les structures de données renvoient des copies plutôt que de mettre à jour l'original en place, etc.

OO d'autre part offre des outils pour gérer l' état de gestion (au lieu des outils pour l'éviter). Outre les outils au niveau de la langue tels que les modificateurs d'accès (protégé / public / privé), les accesseurs, les régleurs, etc., il existe également un certain nombre de conventions connexes, telles que la loi de Demeter, qui déconseillent de chercher dans des objets pour accéder à d'autres objets. .

Notez que vous n’avez pas besoin que les objets fassent vraiment cela: vous pouvez avoir une fermeture qui contient des données inaccessibles et renvoie une structure de données de fonctions pour la manipuler. Mais n'est-ce pas un objet? Cela ne correspond-il pas à notre conception de ce qu'est un objet, intuitivement? Et si nous avons ce concept, ne vaut-il pas mieux le reformuler dans le langage plutôt que (comme d’autres réponses l’ont dit) en s’appuyant sur une explosion combinatoire d’applications ad-hoc concurrentes?

Jared Smith
la source
5

Avons-nous vraiment besoin des langages OO pour gérer la complexité logicielle?

Non, mais ils peuvent aider dans de nombreuses situations.

J'ai utilisé principalement un seul langage OO pendant des décennies, mais la plupart de mon code est en fait strictement procédural. Cependant, pour tout ce qui implique une interface graphique, j'utilise la vaste bibliothèque de méthodes et d'objets intégrés OO du langage, car elle simplifie énormément mon code.

Par exemple, une application Windows utilisant l'API Windows de bas niveau d'origine pour afficher un formulaire, un bouton et un champ d'édition nécessite beaucoup de code, alors que l'utilisation des bibliothèques d'objets livrées avec Visual Basic ou C # ou Delphi est identique. programme minuscule et trivial. Ainsi, mon code OO est généralement relativement petit et pour l'interface graphique, alors que le code invoqué par ces objets est généralement beaucoup plus volumineux et ne concerne généralement pas OO (bien qu'il puisse varier en fonction du problème que je tente de résoudre).

J'ai vu des programmes OO trop compliqués, basés sur des règles ésotériques compliquées sur la manière dont les objets étaient implémentés, et auraient pu être beaucoup plus simples s'ils avaient été écrits sans les concepts OO. J'ai également vu le contraire: des systèmes complexes qui exigent d'être réimplémentés et simplifiés à l'aide d'objets.

En acquérant de l'expérience, vous constaterez que différentes situations requièrent différents outils et solutions et qu'une même taille ne convient pas à tous.

Joe Snyder
la source
3

En tant que personne impliquée dans un très grand projet entièrement écrit en C, je peux certainement dire que la réponse est clairement un "non".

La modularité est importante. Mais la modularité peut être mise en œuvre dans pratiquement n'importe quelle langue décente. Par exemple, C prend en charge la compilation modulaire, les fichiers d’en-tête et les types de structure. Cela suffit pour 99% des cas. Définissez un module pour chaque nouveau type de données abstrait dont vous avez besoin, puis définissez les fonctions à utiliser pour le type de données. Parfois, vous voulez des performances et ces fonctions sont dans le fichier d'en-tête en tant que fonctions en ligne, d'autres fois, vous utiliserez des fonctions standard. Tout est invisible pour l'utilisateur quel chemin est choisi.

Structures supportent la composition. Par exemple, vous pouvez avoir une table de hachage verrouillée composée d'un verrou mutex et d'une table de hachage normale. Ce n'est pas une programmation orientée objet; aucun sous-classement n'est fait. La composition est un outil beaucoup plus ancien que l’idée de la programmation orientée objet.

Dans les 1% des cas où la modularité au niveau de la compilation n'est pas suffisante et que vous avez besoin de la modularité à l'exécution, il existe un élément appelé pointeurs de fonction. Ils permettent d’avoir des implémentations individuelles d’une interface bien définie. Notez qu'il ne s'agit pas d'une programmation orientée objet dans un langage non orienté objet. C'est définir une interface et ensuite l'implémenter. Par exemple, le sous-classement n'est pas utilisé ici.

Considérez peut-être le projet open source le plus complexe qui existe. À savoir, le noyau Linux. Il est entièrement écrit en langage C. Cela se fait principalement en utilisant les outils de modularité de niveau de compilation standard, y compris la composition, et parfois lorsque la modularité à l'exécution est nécessaire, des pointeurs de fonction sont utilisés pour définir et implémenter une interface.

Si vous essayez de trouver un exemple de programmation orientée objet dans le noyau Linux, je suis certain que trouver cet exemple est très difficile, sauf si vous étendez la programmation orientée objet pour inclure des tâches standard telles que "définir une interface puis l'implémenter".

Notez que même le langage de programmation C prend en charge la programmation orientée objet si vous en avez vraiment besoin. Par exemple, considérons le kit d'outils de l'interface utilisateur graphique GTK. En réalité, il est orienté objet, même s'il est écrit dans un langage non orienté objet. Cela montre donc que l’idée selon laquelle vous avez besoin d’un "langage orienté objet" est profondément erronée. Il n'y a rien qu'un langage orienté objet puisse faire qu'un autre type de langage ne puisse pas faire. De plus, si vous êtes un programmeur expert, vous savez écrire très facilement un code orienté objet dans n’importe quelle langue. Ce n'est pas un fardeau d'utiliser C, par exemple.

Les conclusions sont donc que les langages orientés objet ne sont probablement utiles que pour les programmeurs débutants qui ne comprennent pas comment le concept est réellement implémenté. Cependant, je ne voudrais pas être à proximité d'un projet où les programmeurs sont de tels programmeurs novices.

juhist
la source
1
"[...] les conclusions sont que les langages orientés objet ne sont probablement utiles que pour les programmeurs débutants qui ne comprennent pas comment le concept est réellement implémenté." Intéressant. Quelles langues as-tu en tête? Avez-vous des exemples de projets open source écrits dans ces langues qui ont échoué ou n'ont pas échoué?
Vincent Savard
3
Vous soulevez de bons points, mais votre idée principale est imparfaite. Oui, il est possible d'implémenter des concepts OO tels que l'encapsulation, la répartition virtuelle, l'héritage et même la récupération de place dans un langage tel que C. Il est également possible de le faire en assembleur. Cela ne facilite pas la programmation. Programmer et particulièrement concevoir dans un langage comme C est nettement plus difficile que dans un langage OO. En C, vous devez mapper les concepts sur leur implémentation. Dans un langage OO, vous n'avez pas besoin de faire cette étape (du moins pas pour les concepts OO).
fishinear
1
"[Les pointeurs de fonction] permettent d’avoir des implémentations individuelles d’une interface bien définie. Notez qu’il ne s’agit pas d’une programmation orientée objet dans un langage non orienté objet. C’est la définition d’une interface, puis sa mise en oeuvre." Désolé, mais c'est complètement faux, car c'est exactement ce qu'est la POO. "Par exemple, le sous-classement n'est pas utilisé ici" Le sous-classement n'est pas une fonctionnalité obligatoire de la POO. Notez, par exemple, que JavaScript est un langage orienté objet qui ne comporte pas de sous-classes (ni même de classes ... uniquement des objets contenant des références de fonctions).
Jules
1
Pour clarifier mon dernier commentaire, mon point important est que le principal facteur de distinction entre la POO (pas nécessairement un langage spécifique de OO) et les autres méthodes est que dans la POO, nous définissons des interfaces qui fonctionnent de manière abstraite sur des données sans avoir besoin de connaître le format de ces données. liant l'implémentation des interfaces aux données elles-mêmes. C'est ce que la POO est. La méthode d'implémentation est indifférente, qu'il s'agisse d'une classe de style Java, d'un objet JavaScript (en fait, une carte de nom à attribuer, qui peut être soit des données ou du code), ou une structure contenant des pointeurs de fonction et un void * pour les données.
Jules
1
"Donc, les conclusions sont que les langages orientés objet ne sont probablement utiles que pour les programmeurs débutants qui ne comprennent pas comment le concept est réellement mis en œuvre." ... Et, franchement, c'est insultant. Je sais assez bien comment ces concepts sont mis en œuvre. J'ai déjà fait suffisamment de travail pour être efficace, même. J'ai même déjà implémenté à la fois un interprète et un compilateur pour les langages OO. Mais parce que je préfère travailler dans des langages de niveau supérieur avec des objets de première classe, je dois être un programmeur débutant avec qui vous préférez ne pas travailler?!
Jules
2

L’introduction de paradigmes de programmation, y compris des méthodes orientées objet, a pour but de faciliter la création de programmes plus sophistiqués et plus puissants. Dans le numéro d'août 1981 de Byte Magazine, Daniel Ingalls , l'un des principaux créateurs de Smalltalk, définissait "orienté objet" comme impliquant les capacités suivantes:

  • gestion automatique du stockage
  • possibilité d'échanger des messages
  • une métaphore uniforme qui s'applique à toutes les opérations de la langue
  • aucun composant ne dépend des composants internes d'un autre composant (modularité)
  • programme définit uniquement le comportement des objets, pas leur représentation (polymorphisme)
  • chaque composant doit apparaître dans un seul endroit (factorisation)
  • l'utilisation d'une machine virtuelle indépendante du matériel
  • chaque composant accessible à l'utilisateur doit être disponible pour l'observation et le contrôle (principe réactif)
  • il ne devrait y avoir aucun contrôleur global (pas de système d'exploitation)

Ingalls a identifié ces principes comme étant les facteurs déterminants de la conception de SmallTalk-80 développés par Xerox Parc Research. Dans l'article de magazine susmentionné, vous pouvez lire une description détaillée de chacun de ces principes et de la façon dont ils contribuent au paradigme orienté objet selon Ingalls.

Tous ces principes peuvent être appliqués avec n’importe quel langage complet Turing, qu’il s’agisse de la procédure, du langage d’assemblage ou autre. Ce sont des principes de conception, pas une spécification de langage. Un langage orienté objet est destiné à faciliter l'utilisation de ces principes lors de la création de logiciels.

Par exemple, pour reprendre le premier des principes d'Ingall (gestion automatique du stockage), tout le monde peut écrire son propre système de gestion automatique du stockage dans un langage procédural, mais cela demanderait beaucoup de travail. Lorsque vous utilisez un langage tel que SmallTalk ou Java doté d'une gestion de stockage automatique intégrée, le programmeur n'a pas à effectuer autant de travail de gestion de la mémoire. Le compromis est que le programmeur obtient moins de contrôle sur la façon dont la mémoire est utilisée. Donc, il y a un avantage et un inconvénient. L'idée d'un paradigme de conception comme la programmation orientée objet est que les avantages de ce paradigme l'emporteront sur les inconvénients pour au moins certains programmeurs.

Tyler Durden
la source
Je pense que les mêmes règles s’appliqueraient dans le cas des langages spécifiques à un domaine. Mêmes avantages et inconvénients ... La seule différence réside dans le fait que les utilisateurs finaux peuvent travailler avec des DSL assez simples, car le «langage» correspond à leur compréhension de l'espace du problème et rien d'autre n'est inclus.
0

Un moyen de gérer la complexité logicielle consiste à séparer complètement la structure des actions souhaitées à l'aide d'un langage spécifique à un domaine . Cela signifie que le niveau de code de programmation est distinct du niveau auquel les résultats souhaités sont configurés - un langage ou un système complètement différent. Lorsque cela est fait correctement, le code conventionnel devient essentiellement une bibliothèque et l'utilisateur ou toute autre personne créant les résultats souhaités associe des éléments à un langage de script ou à un outil de conception visuelle, tel qu'un générateur de rapports.

Pour fonctionner, cela nécessite de tracer une limite stricte autour des opérations qui seront possibles et de la manière dont elles sont reliées (langage de script ou conception visuelle, comme un outil de construction de formulaire). Les métadonnées constituent un moyen important de soustraire la configuration d'exécution aux détails de codage, permettant ainsi à un système de prendre en charge un large éventail de résultats souhaités. Si les limites sont définies et respectées (en n'acceptant pas chaque demande d'extension), vous pouvez avoir un système robuste et durable qui fonctionne pour les utilisateurs, sans qu'ils aient besoin d'être programmeurs pour accomplir ce qu'ils veulent.

Martin Fowler a écrit un livre à ce sujet, et la technique est presque aussi vieille que la programmation elle-même. On pourrait presque dire que tous les langages de programmation sont des langages spécifiques à un domaine. L'idée est donc endémique, négligée car tellement évidente. Mais vous pouvez toujours créer vos propres outils de script ou de conception visuelle pour vous simplifier la vie. Parfois, généraliser un problème le rend beaucoup plus facile à résoudre!


la source
0

C'est une très bonne question et je pense que les réponses données ici n'ont pas rendu justice, alors je vais y aller et ajouter mes pensées.

L’objectif est: gérer la complexité des logiciels . L'objectif n'est pas "utiliser le langage OO".

Il n’ya pas de «raison» derrière l’introduction d’un nouveau paradigme. C'est quelque chose qui s'est passé naturellement lorsque le codage est devenu plus mature. Il est plus logique d'écrire du code dans lequel nous ajoutons un entraîneur à la fin du train (le train modélisé à l'aide d'une liste chaînée) plutôt que d'ajouter un nouveau nœud à la fin de la liste chaînée.


Codage en termes d'entités du monde réel est tout simplement la manière évidente et correcte au code lorsque nous sommes de codage sur les entités du monde réel.


Un ordinateur peut travailler avec l'ajout d'un nœud à la fin de la liste chaînée aussi facilement que l'ajout d'un coach supplémentaire à la fin du train. Mais pour les humains, il est plus facile de travailler avec le train et l'entraîneur qu'avec la liste chaînée et les nœuds, même si, lorsque nous atteignons un niveau, le train est modélisé au moyen d'une liste chaînée.

Protéger ou chiffrer les fichiers ne peut pas être encapsulé. Le contraire du cryptage est le décryptage. Le contraire de l'encapsulation est Decapsulation, qui consiste à décomposer les structures et les classes dans les langages de programmation pour améliorer les performances. Performances obtenues en réduisant le trafic mémoire et en évitant les vérifications de règles de POO.

Par conséquent, vous pouvez écrire un code à la fois crypté et bien encapsulé, car ces deux concepts sont différents.

L’encapsulation aide à gérer la complexité du fait qu’elle est proche de la réalité.

Par conséquent, programmez dans des objets car il est plus facile pour vous de coder et pour vous et tout le monde plus rapidement de comprendre.

Afficher un nom
la source
0

La seule chose à retenir est la suivante: la
POO ne concerne pas les fonctionnalités du langage; il s'agit de la façon dont vous structurez votre code .

La programmation orientée objet est une manière de penser et de concevoir l'architecture de votre code, et cela peut être fait dans à peu près n'importe quelle langue. Cela inclut en particulier les langages de bas niveau non OO, appelés assembleur et C. Vous pouvez effectuer une programmation parfaitement orientée objet dans assembleur, et le noyau Linux, écrit en C, est assez orienté objet à bien des égards. .

Cela dit, les fonctionnalités OO dans une langue réduisent considérablement la quantité de code passe-partout que vous devez écrire pour obtenir les résultats souhaités . Lorsque vous devez définir explicitement une table de fonction virtuelle et la remplir avec les pointeurs de fonction appropriés en C, vous ne faites rien en Java et vous avez terminé. Les langages OO suppriment simplement tout ce qui permet cruel du code source, en le cachant derrière de belles abstractions de niveau de langage (telles que des classes, des méthodes, des membres, des classes de base, des appels implicites de constructeur / destructeur, etc.).

Donc, non, nous n'avons pas besoin des langages OO pour faire de la programmation orientée objet. C'est juste que la POO est tellement plus facile à faire avec un langage OO décent.

cmaster
la source
-1

La programmation orientée objet est plus que de simples modules + encapsulation. Comme vous le dites, il est possible d’utiliser des modules + encapsulation dans un langage (procédural) non orienté objet. La POO implique plus que cela: elle implique des objets et des méthodes. Donc, non, cela ne capture pas la POO. Voir, par exemple, https://en.wikipedia.org/wiki/Object-oriented_programming ou l'introduction d'un bon manuel à la programmation orientée objet.

DW
la source
Merci pour la réponse. Pourriez-vous en recommander un?
échange de steak
-2

La principale raison est qu’au fur et à mesure que le programme se complexifie, vous devez en rendre certaines parties invisibles, sinon la complexité de l’application et le nombre de fonctions rendront votre cerveau dribbler.

Imaginons un système de 100 classes, chacune avec environ 20 opérations pouvant être effectuées sur elles. c'est 2.000 fonctions. Cependant, parmi celles-ci, seules 500 sont peut-être des opérations complètes telles que «Enregistrer» et «Supprimer», tandis que 1500 sont des fonctions internes qui effectuent un peu de maintenance ou jouent un rôle utilitaire. Considérer;

// intentionally in a non-specific language!

setName(person, name) {
    nameParts = splitPersonName(name);
    person.firstName = nameParts[0];
    person.lastName = nameParts[1];
    person.modified = true;
}

splitPersonName(name) {
    var result = [];
    result.add(name.substring(0, name.indexOf(" ")));
    result.add(name.substring(name.indexOf(" ") + 1));
    return result;
}

C'est donc SetNameune fonction que les gens devraient faire à une personne, mais SplitPersonNameune fonction utilitaire utilisée par la personne.

Une programmation procédurale simple ne fait aucune distinction entre ces deux opérations. Cela signifie que vos 2 000 fonctionnels se disputent votre attention. Cependant, si nous pouvions marquer ces fonctions comme "disponibles pour tous ceux qui ont une fiche personne" et "utilisées uniquement comme fonction utilitaire dans la fiche personne", notre attention porte désormais sur 500 fonctions "accessibles à tous" et 15 "utilitaires". fonctions pour la classe que vous éditez.

C'est quoi publicet privatefaire;

public class Person {
    public void setName(...) {...}
    private string[] splitPersonName(...) { ...}
}
utilisateur62575
la source
1
Je ne sais pas si vous avez bien compris ma question. Je suis déjà conscient de l'encapsulation et de la dissimulation de données en tant que moyen de gérer la complexité. Je pense simplement que cela peut être facilement réalisé dans les langages procéduraux en divisant le programme en modules qui exécutent des tâches simples bien définies dont le fonctionnement interne est spécifié dans des sources protégées séparées. Alors pourquoi la POO alors que nous pouvons faire ces choses dans des langages procéduraux? C'est ma question.
échange de steak
2
Je suppose que ma réponse est que si vous voulez faire ce genre de chose, vous devrez écrire des outils spéciaux et des constructions de langage pour le faire (par exemple, un appel spécial 'include' à un fichier include qui peut ne pas être inclus ailleurs). Une fois que vous avez commencé sur cette voie, vous avez réellement commencé à implémenter un langage orienté objet à votre manière. Par exemple, C ++ était à l' origine un préprocesseur qui produisait du C en clair , et je suppose qu'une fois que vous implémentez votre système, il ressemble beaucoup au C ++ au-dessus de C.
user62575 Le
3
@steakexchange Notez que la POO a été développée à une époque où de nombreux langages procéduraux n'avaient pas de modules de ce type. Certains n'appelleraient même pas de tels langages procéduraux. En effet, rien ne dit qu'un langage procédural ne doit pas être OO ou vice versa. Faites attention aux étiquettes - elles peuvent facilement vous induire en erreur. Si votre langage procédural prend en charge les modules qui ont des champs et des procédures publics et privés, vous êtes bien :) ne sais jamais quel code tu appelles.
Luaan
2
@steakexchange Dans les langages de la famille ML, les modules fonctionnent très bien et, en combinaison avec lambdas, ils vous donnent toute la puissance d'un langage OO (après tout, une fonction est une interface avec une seule méthode. N'est-ce pas ce que recommande fortement "bon code" les gars dans OO?: P). Pour diverses raisons, ils sont encore moins utilisés que les langages plus procéduraux tels que C ++ ou Java, mais ils ont tout de même leur attrait, et de nombreuses personnes essaient d'éduquer les gens sur la façon de simplifier leur vie (avec plus ou moins de succès).
Luaan
C a effectivement ces choses. Il a des modules (fichiers .c) avec des interfaces (fichiers .h) et peut avoir des méthodes (fonctions) publiques (extern) et non publiques (extern). Vous pouvez même avoir le polymorphisme du pauvre avec des tableaux de pointeurs de fonction, je ne dis pas que OO est facile en C (ou peut-être sain d'esprit) mais que l'encapsulation est assez facile,
Nick Keighley