Remarque : cette question est un extrait modifié d'un billet de blog que j'ai écrit il y a quelques mois. Après avoir placé un lien vers le blog dans un commentaire sur Programmers.SE, quelqu'un m'a demandé de poster une question ici pour pouvoir y répondre. Cette publication est ma plus populaire, car les gens semblent taper "Je ne reçois pas beaucoup de programmation orientée objet" dans Google . N'hésitez pas à répondre ici, ou dans un commentaire sur Wordpress.
Qu'est-ce que la programmation orientée objet? Personne ne m'a donné une réponse satisfaisante. Je sens que vous n'obtiendrez pas une bonne définition de la part de quelqu'un qui dit "objet" et "orienté objet" avec le nez en l'air. Vous n'obtiendrez pas non plus une bonne définition de la part de quelqu'un qui n'a fait que de la programmation orientée objet. Personne qui comprend à la fois la programmation procédurale et la programmation orientée objet ne m'a jamais donné une idée cohérente de ce que fait réellement un programme orienté objet.
Quelqu'un peut-il me donner s'il vous plaît leurs idées sur les avantages de la programmation orientée objet?
la source
Réponses:
Pensez au logiciel comme à une machine ou une chaîne d’assemblage existant dans l’ordinateur. Certaines matières premières et certains composants sont introduits dans la machine, qui suit un ensemble de procédures pour les transformer en produit final. Les procédures sont configurées pour effectuer une opération spécifique sur une matière première ou un composant avec un ensemble de paramètres spécifique (par exemple, le temps, la température, la distance, etc.) dans un ordre particulier. Si les détails de l'opération à exécuter étaient incorrects, ou si les capteurs de la machine n'étaient pas correctement calibrés, ou si une matière première ou un composant ne respectait pas les normes de qualité attendues, cela pourrait changer le résultat de l'opération et le produit ne se révélerait pas. comme prévu.
Une telle machine est très rigide dans son fonctionnement et des entrées acceptables. Les machines ne remettent pas en question l'intelligence des concepteurs ni son environnement d'exploitation actuel. Il continuera à suivre les procédures tant qu'il est dirigé vers. Même si un changement de matières premières ou de composants pouvait avoir un effet considérable sur ce qui se passait lors d'opérations ultérieures, la machine continuerait néanmoins à exécuter ses procédures. Il faudrait revoir le processus pour voir quels changements dans les procédures étaient nécessaires pour compenser et produire le résultat souhaité. Une modification de la conception ou de la configuration du produit peut également nécessiter une modification significative des opérations effectuées ou de leur ordre. Bien que les responsables de la production aient rapidement compris l’importance d’isoler le plus possible les opérations afin de réduire les effets indésirables entre elles, de nombreuses hypothèses sont formulées concernant l'état des composants au fur et à mesure de leur traitement; des hypothèses qui pourraient ne pas être détectées tant que le produit final ne sera pas entre les mains de l'utilisateur dans un environnement d'exploitation différent.
C'est ce que la programmation procédurale est comme.
Ce que l'orientation objet fournit est un moyen de supprimer les hypothèses de l'état des composants; ainsi, les opérations à effectuer sur ce composant et comment l’intégrer dans le produit final. En d'autres termes, la programmation orientée objet revient à prendre les détails du processus pour traiter un composant particulier et le confier à une machine plus petite. La plus grande machine responsable du processus indique à la machine spécifique au composant quelle opération elle s'attend à effectuer, tout en laissant les détails des étapes à la machine à gérer.
En ce qui concerne les avantages de l'orientation objet par rapport aux logiciels non orientés objet:
la source
Sur votre blog, il semble que vous maîtrisiez à la fois la programmation impérative et la programmation fonctionnelle, ainsi que les concepts de base de la programmation orientée objet, mais vous ne l’avez jamais vraiment fait. le rend utile. J'essaierai d'expliquer cette connaissance en espérant que cela vous sera utile.
Fondamentalement, la programmation orientée objet est un moyen d'utiliser le paradigme impératif pour mieux gérer les hauts niveaux de complexité en créant des structures de données "intelligentes" qui modélisent le domaine du problème. Dans un programme (procédural standard non orienté objet), vous avez deux éléments de base: les variables et le code qui sait quoi faire avec. Le code reçoit les entrées de l'utilisateur et de diverses autres sources, les stocke dans des variables, les exploite et génère des données de sortie qui parviennent à l'utilisateur ou à divers autres emplacements.
La programmation orientée objet est un moyen de simplifier votre programme en reprenant ce modèle de base et en le répétant à une plus petite échelle. Tout comme un programme est une vaste collection de données avec du code qui sait quoi en faire, chaque objet est un petit morceau de données lié à du code qui sait quoi faire avec.
En décomposant le domaine problématique en parties plus petites et en s'assurant que le maximum de données est lié directement à du code qui sait quoi en faire, il est beaucoup plus facile de raisonner sur le processus dans son ensemble et également sur le sous-système. questions qui composent le processus.
En regroupant les données dans des classes d'objets, vous pouvez centraliser le code associé à ces données, ce qui facilite la recherche et le débogage du code pertinent. Et en encapsulant les données derrière les spécificateurs d'accès et en n'y accédant que par des méthodes (ou des propriétés, si votre langue les prend en charge), vous réduisez considérablement le risque de corruption des données ou de violation des invariants.
Et en utilisant l'héritage et le polymorphisme, vous pouvez réutiliser des classes préexistantes, en les personnalisant pour répondre à vos besoins spécifiques, sans avoir à modifier les originaux ou à tout réécrire. (Ce qui est une chose que vous ne devriez jamais faire , si vous pouvez l'éviter.) Veillez simplement à bien comprendre votre objet de base, sinon vous pourriez vous retrouver avec des kangourous tueurs .
Pour moi, ce sont les principes fondamentaux de la programmation orientée objet: gestion de la complexité, centralisation du code et modélisation améliorée du domaine des problèmes par la création de classes d'objets, héritage et polymorphisme, et sécurité accrue sans sacrifier le pouvoir ou le contrôle grâce à l'encapsulation et Propriétés. J'espère que cela vous aidera à comprendre pourquoi tant de programmeurs le trouvent utile.
EDIT: En réponse à la question de Joel dans les commentaires,
Un petit avertissement ici. Mon modèle de "programme orienté objet" est essentiellement le modèle Delphi, qui est très similaire au modèle C # / .NET puisqu'il a été créé par d'anciens membres de l'équipe Delphi. Ce que je dis ici peut ne pas s'appliquer, ou pas, autant, dans d'autres langues OO.
Un programme orienté objet est un programme dans lequel toute la logique est structurée autour d'objets. Bien sûr, cela doit être démarré quelque part. Votre programme Delphi typique contient un code d’initialisation qui crée un objet singleton appelé
Application
. Au début du programme, il appelleApplication.Initialize
, puis appelleApplication.CreateForm
pour chaque formulaire que vous souhaitez charger en mémoire depuis le début, puisApplication.Run,
affiche le formulaire principal à l'écran et lance la boucle de saisie / événement qui constitue le cœur de tout programme. programmes informatiques interactifs.Application et vos formulaires interrogent les événements entrants provenant du système d'exploitation et les traduisent en appels de méthode sur votre objet. Une chose très courante est l'utilisation de gestionnaires d'événements ou de "délégués" dans .NET. Un objet a une méthode qui dit: "Faites X et Y, mais vérifiez également si ce gestionnaire d'événements particulier est assigné et appelez-le si c'est le cas". Un gestionnaire d'événements est un pointeur de méthode, une fermeture très simple contenant une référence à la méthode et une référence à l'instance d'objet, utilisé pour étendre le comportement des objets. Par exemple, si j'ai un objet bouton sur mon formulaire, je personnalise son comportement en attachant un gestionnaire d'événements OnClick, ce qui oblige un autre objet à exécuter une méthode lorsque l'utilisateur clique sur le bouton.
Ainsi, dans un programme orienté objet, la plupart du travail est effectué en définissant des objets avec certaines responsabilités et en les reliant, soit par des pointeurs de méthode, soit par un objet appelant directement une méthode définie dans l'interface publique d'un autre objet. (Et maintenant, nous sommes de retour à l’encapsulation.) C’est une idée que je ne connaissais pas avant de prendre des cours de POO à l’université.
la source
Je pense que la POO n’est en gros qu’un nom donné à quelque chose que vous pourriez avoir été tenté de faire en cours de route, comme j’étais.
Il y a bien longtemps, lorsque j'étais programmeur pour bébés, même à Fortran, le pointeur sur un sous-programme existait déjà. Il est vraiment utile de pouvoir passer un pointeur sur un sous-programme en tant qu’argument à un autre sous-programme.
Ensuite, la prochaine chose qui serait vraiment utile serait de stocker un pointeur sur un sous-programme à l'intérieur d'un enregistrement d'une structure de données. De cette façon, vous pourriez dire que le dossier "sait" comment effectuer des opérations sur lui-même.
Je ne suis pas sûr qu'ils l'aient déjà construit en Fortran, mais c'est facile à faire en C et ses descendants.
En dessous, c’est une idée simple et utile que vous auriez peut-être tenté de faire vous-même. C’est plus facile à faire dans les langues plus récentes, même si certaines personnes en ont fait un fourgon gigantesque plein de mots à la mode effrayants.
la source
Il existe différents types de systèmes OO, et il est difficile d'obtenir une définition sur laquelle tout le monde sera d'accord. Plutôt que d'essayer de montrer en quoi l'OO de Java est similaire au système d'objet Common Lisp, je commencerai par quelque chose de plus conventionnel, étape par étape.
Supposons que de nombreux objets existent sous forme de données dispersées. Les points, par exemple, peuvent être des éléments dans un tableau X, un tableau Y et un tableau Z. Afin d'examiner un point lui - même, il est logique de tirer toutes les données ensemble dans quelque chose comme un C
struct
.Maintenant, pour tout objet de données, nous avons toutes les données. Cependant, dans un programme procédural, le code est dispersé. Supposons que nous avons affaire à des formes géométriques. Il y a une grande fonction pour dessiner des formes, et il faut connaître toutes les formes. Il y a une grande fonction pour trouver une zone et une autre pour un périmètre. Le code pour un cercle est dispersé à travers plusieurs fonctions, et afin d'ajouter un autre type de forme, nous devons savoir quelles fonctions modifier. Dans un système orienté objet, nous regroupons les fonctions dans le même genre de chose (
class
) que les données. Par conséquent, si nous voulons examiner tout le code du cercle, il se trouve dans laCircle
définition, et si nous voulons ajouter un,Quartercircle
nous écrivons simplement sa classe et nous avons le code.L’un des avantages de cela est que nous pouvons conserver des invariants de classe, ce qui est vrai pour chaque membre de la classe. En empêchant le code en dehors de la classe de gêner directement avec les membres de données de classe, nous avons tout le code qui peut changer les données de classe en un seul endroit, et nous pouvons confirmer qu'il ne fait rien de crasseux (comme avoir un triangle avec une jambe plus long que les deux autres combinés). Cela signifie que nous pouvons compter sur certaines propriétés de chaque membre de la classe et ne pas avoir à vérifier si un objet est sain à chaque utilisation.
Le principal avantage est l'héritage et le polymorphisme. En définissant toutes ces différentes formes comme des sous-classes d'une classe appelée
Shape
, nous pouvons avoir notre code manipulerShape
s, et c'est le travail des sous-objets de forme de faire ce que les manipulations appellent. Cela signifie que nous n'avons pas besoin de toucher à l'ancien code testé lorsque nous ajoutons de nouvelles formes ou que nous affinons le comportement des anciennes. Nous avons automatiquement l'ancien code qui peut directement tirer parti du nouveau code. Au lieu de faire prendre conscience au code de contrôle de toutes les formes possibles et de maintenir des fonctions prenant en compte toutes les formes possibles, nous nous occupons simplement des formes et de leurs propriétés, tout en maintenant lesShape
sous-classes. Cela simplifie le code de contrôle.Nous avons plusieurs avantages ici. Comme nous avons des invariants de classe, nous pouvons raisonner sur des objets de données plus grands de la même façon que nous raisonnons sur les types intégrés, ce qui signifie que nous pouvons souvent scinder des concepts complexes en concepts plus simples. Comme le code de cercle est largement contenu dans
Circle
, nous avons augmenté la localité. Comme il n'y a pas de concepts de cercle dispersés dans plusieurs fonctions différentes à des endroits différents, nous obtenons moins de couplage entre les routines et nous n'avons pas à nous soucier de les maintenir synchronisées. Comme les classes sont en fait des types, nous pouvons tirer parti du système de types existant pour détecter les utilisations incompatibles de nos classes.la source
OO a beaucoup de définitions différentes, oui. Je suis sûr que vous pouvez en trouver beaucoup vous-même. Personnellement, j'aime bien Rees Re: OO pour leur donner un sens. Je suppose que vous avez déjà lu cela depuis que vous citez Paul Graham. (Je le recommande à toute personne intéressée par OO.) Je vais adopter plus ou moins la définition de Java ici {1,2,3,7,8,9}.
La question de l'utilité de OO, en particulier de la façon dont je l'aborde, mérite une réponse beaucoup plus large avec quelques milliers de lignes de code (en partie pour ne pas être un tas d'assertions). Cependant, voici un résumé de ce document hypothétique.
Je ne pense pas que OO soit terriblement utile à petite échelle, disons, quelques centaines de lignes. En particulier, les langages OO sans bonnes influences fonctionnelles ont tendance à rendre très pénible l'exécution de tâches simples avec n'importe quel type de collection ou nécessitant de nombreux types de données. C’est là que la plupart des modèles de conception entrent en jeu; ce sont des pansements sur la faible puissance de la langue sous-jacente .
Avec environ un millier de lignes, il devient de plus en plus difficile de suivre toutes les opérations et les structures de données et leurs relations. À ce stade, il est utile de disposer d’un moyen d’organiser explicitement les structures et les opérations de données, de définir les limites des modules et de définir les responsabilités, ainsi que de disposer d’un moyen pratique de comprendre ces définitions pendant la programmation.
Java-ish OO est une solution à mi-chemin à ces problèmes qui ont remporté le concours de popularité. Parce que c'est le même mécanisme que les gens de Java appliquent aux problèmes à petite échelle créés par un langage peu puissant, il a tendance à commencer à ressembler davantage à une solution magique à tout, qu'à un simple moyen de rester organisé. Les personnes familiarisées avec la programmation fonctionnelle ont tendance à préférer d'autres solutions, telles que CLOS ou les classes de types de Haskell, ou la métaprogrammation des modèles bloqués en C ++, ou bien (comme moi, travaillant quotidiennement en C #), utilisez OO mais ne vous excitez pas tout autant. .
la source
OOP tente de modéliser des concepts du monde réel en termes d'objets et d'interactions entre eux. En tant qu'humains, nous avons tendance à traiter le monde en termes d'objets. Le monde regorge d'objets dotés de certaines propriétés et capables d'interagir avec d'autres objets. OOP permet de modéliser le monde en termes similaires. Par exemple,
Mais une voiture ne peut pas bouger toute seule, il lui faut une personne pour la conduire - interaction entre objets.
la source
POO = structures de données + transmission de messages + héritage, qui constituent toutes des évolutions logiques dans les modèles de programmation.
La POO peut être comprise (par les programmeurs) en 90 secondes environ (voir mon profil pour un lien). Les concepts sont très simples.
Comment l'appliquer est une autre affaire. Ce n’est pas parce que vous savez balancer un marteau que vous savez concevoir et construire une maison. ;-)
la source
Il y a quelque temps, j’ai écrit un article de blog qui pourrait vous être utile: Procédure contre la POO expliquée .
la source
La première fois que j'ai compris cela, c'est:
Avant la programmation orientée objet, vous utilisiez la programmation structurée . Tout est centré sur le processus. La première question que vous devez vous poser est " Qu'est-ce que je veux faire avec l'information? ".
Avec la programmation orientée objet, elle est centrée sur les données. La première question que vous devez vous poser est la suivante: "Des informations sur la sorcière dont j'ai besoin? ". Cela facilite l'abstraction.
la source
Puisque vous comprenez les structures, et que vous comprenez les pointeurs de fonction, et que vous comprenez les structures avec des pointeurs de fonction, de votre point de vue, je définirais la programmation orientée objet comme une simple "programmation, avec une utilisation intensive de structures comportant des pointeurs de fonction". C'est toujours la programmation au sens traditionnel - ce sont toutes des données et un code qui agit sur les données. La différence réside simplement dans la définition de toutes ces informations et dans votre approche.
Une simplification excessive est peut-être que la programmation traditionnelle est "du code, avec certaines structures de données", et la programmation orientée objet est "des structures de données, avec du code". Les deux ont toujours des structures de données et les deux ont encore du code. La programmation orientée objet n’est donc rien de plus que l’acte de définir des types de données à l’avance et d’appliquer des contrats pour la façon dont ils communiquent via des ensembles de fonctions.
Comme vous l'avez fait remarquer, il existe une énorme classe d'applications pour lesquelles ce n'est pas un excellent moyen de mettre en œuvre une solution. Vous semblez vivre dans un monde principalement constitué de telles applications. Dans votre article de blog, vous mentionnez la mise en œuvre du problème des "99 bouteilles de bière" (votre "vitrine de programmation préférée"). 99 bouteilles de bière font certainement partie de cette catégorie. Essayer de comprendre la programmation orientée objet en examinant les implémentations de 99 bouteilles de bière, c'est un peu comme essayer de comprendre l'architecture en hauteur en regardant une cabane dans les arbres. Même une cabane dans les arbres très bien construite ne peut que vous en apprendre beaucoup.
TL; DR: La programmation OO ressemble à la programmation traditionnelle, sauf que vous vous concentrez davantage sur la définition des structures de données à l’avance et que ces structures communiquent entre elles via des pointeurs de fonction.
la source
Je pense que la page Wikipedia est un bon endroit pour obtenir les bases:
http://en.wikipedia.org/wiki/Object-oriented_programming
En gros, l’idée est que la programmation procédurale, ce que l’OOP essayait d’améliorer, était axée sur les processus modélisés. La POO passe à un modèle où l'accent est mis sur les "choses" que vous modélisez, et les processus et les données de ces choses sont contenus dans ces choses.
Ainsi, à titre d'exemple, supposons que vous conceviez une application pour suivre une liste de tâches. En programmation procédurale, les entités de niveau supérieur du modèle sont les processus en cours, tels que la création d’une tâche, la suppression d’une tâche, la modification des informations de la tâche, etc. Dans un modèle POO, vous devez plutôt vous concentrer sur la création d’une tâche. Réfléchissez aux données et aux processus dont cette tâche devrait être responsable. Puis concentrez-vous sur les autres objets avec lesquels la tâche devrait interagir, par exemple une note ou quelque chose si vous souhaitez conserver des notes sur les tâches.
J'espère que ça aide. Continuez simplement à lire à ce sujet et à regarder le code et il va soudainement "cliquer". C'était mon expérience.
la source