Je programme dans des langages procéduraux depuis un certain temps maintenant, et ma première réaction à un problème est de commencer à le décomposer en tâches à effectuer plutôt que de considérer les différentes entités (objets) qui existent et leurs relations.
J'ai suivi un cours universitaire en POO et je comprends les principes fondamentaux de l'encapsulation, de l'abstraction des données, du polymorphisme, de la modularité et de l'héritage.
J'ai lu /programming/2688910/learning-to-think-in-the-object-oriented-way et /programming/1157847/learning-object-oriented-thinking , et se penchera sur certains des livres mentionnés dans ces réponses.
Je pense que plusieurs de mes projets de taille moyenne à grande bénéficieront d'une utilisation efficace de la POO, mais en tant que novice, je voudrais éviter les erreurs courantes et chronophages.
D'après vos expériences, quels sont ces écueils et quels sont les moyens raisonnables de les contourner? Si vous pouviez expliquer pourquoi ils sont des pièges et comment votre suggestion est efficace pour résoudre le problème, ce serait apprécié.
Je pense à quelque chose comme "Est-il courant d'avoir un bon nombre de méthodes d'observateur et de modificateur et d'utiliser des variables privées ou existe-t-il des techniques pour les consolider / réduire?"
Je ne suis pas inquiet d'utiliser C ++ comme un langage OO pur, s'il y a de bonnes raisons de mélanger les méthodes. (Réminiscence des raisons d'utiliser les GOTO, quoique avec parcimonie.)
Je vous remercie!
la source
Réponses:
Une grande chose que j'ai apprise est de concevoir des classes de l'extérieur. Concevez l'interface avant même de commencer à penser à l'implémentation. Cela rendra la classe beaucoup, beaucoup plus intuitive pour vos utilisateurs (ceux qui utilisent la classe) que d'écrire les algorithmes sous-jacents et de construire la classe, et d'écrire de nouvelles fonctions de membre public au besoin.
la source
Eh bien, le premier est l'écueil d'exposer trop d'informations. La valeur par défaut devrait être
private
nonpublic
.Après cela vient trop de getters / setters. Disons que j'ai un membre de données. Ai-je vraiment besoin de ces données dans une autre classe? Ok, fais un getter. Ai -je vraiment, vraiment besoin de changer ces données pendant la durée de vie de l'objet? Faites ensuite un setter.
La plupart des programmeurs novices ont la valeur par défaut pour créer un getter / setter pour chaque membre de données. Cela encombre les interfaces et constitue souvent de mauvais choix de conception.
la source
Lorsque j'ai traversé ce gouffre, j'ai opté pour l'approche suivante:
0) J'ai commencé lentement, avec des applications procédurales de petite / moyenne taille, et aucun truc essentiel à la mission au travail.
1) une simple cartographie de premier passage sur la façon dont j'écrirais le programme à partir de zéro dans le style OO - le plus important pour moi à ce moment-là, et cela EST subjectif - était de comprendre toutes les classes de base. Mon objectif était d'encapsuler autant que possible dans les classes de base. Méthodes virtuelles pures pour tout ce qui est possible dans les classes de base.
2) Ensuite, l'étape suivante a été de créer les dérivations.
3) l'étape finale était - dans le code de procédure d'origine, séparer les structures de données du code obsever / modifier. Ensuite, utilisez les données masquées et mappez toutes les données communes dans les classes de base, et dans les sous-classes, les données qui n'étaient pas communes à l'ensemble du programme sont entrées. Et le même traitement pour le code observateur / modificateur procédural - toute la logique «utilisée partout» est entrée dans les classes de base. Et la logique de visualisation / modification qui n'agissait que sur un sous-ensemble des données est entrée dans les classes dérivées.
C'est subjectif mais c'est RAPIDE, si vous connaissez bien le code procédural et les structures de données. Un ÉCHEC dans une révision de code, c'est quand un peu de données ou de logique n'apparaît pas dans les classes de base mais est utilisé partout.
la source
Jetez un oeil à d'autres projets réussis qui utilisent la POO pour avoir une idée du bon style. Je recommande de regarder Qt , un projet que je regarde toujours lorsque je prends mes propres décisions de conception.
la source
Selon la personne à qui vous parlez, toutes les données de la POO doivent être privées ou protégées, et uniquement disponibles via des accesseurs et des mutateurs. En général, je pense que c'est une bonne pratique, mais il y a des occasions où je diverge de cette norme. Par exemple, si vous avez une classe (en Java, disons) dont le seul but est de regrouper certains éléments de données dans une unité logique, il est logique de laisser les champs publics. S'il s'agit d'une capsule immuable, il suffit de les marquer comme finales et de les initialiser dans le constructeur. Cela réduit la classe (dans ce cas) à un peu plus qu'une structure (en fait, en utilisant C ++, vous devez en fait appeler cela une structure. Fonctionne comme une classe, mais la visibilité par défaut est publique et votre intention est plus claire), mais Je pense que vous constaterez que son utilisation est beaucoup plus confortable dans ces cas.
Une chose que vous ne voulez certainement pas faire est d'avoir un champ dont la cohérence doit être vérifiée dans le mutateur et de le laisser public.
la source
struct
s - cela ne fait aucune différence sémantique, mais cela clarifie l'intention et rend leur utilisation plus naturelle, en particulier pour les programmeurs C.Le livre de Kent Beck, Implementation Patterns, est une excellente base pour savoir comment utiliser, et non abuser, les mécanismes orientés objet.
la source
Je ne suis pas inquiet d'utiliser C ++ comme un langage OO pur, s'il y a de bonnes raisons de mélanger les méthodes. (Réminiscence des raisons d'utiliser les GOTO, quoique avec parcimonie.)
Je ne pensais pas vraiment que j'avais beaucoup à offrir la conversation jusqu'à ce que je voie ce morceau. Je dois être en désaccord avec le sentiment. La POO n'est qu'un des paradigmes qui peuvent et doivent être utilisés en C ++. Franchement, à mon avis, ce n'est pas l'une de ses caractéristiques les plus fortes.
Du point de vue OO, je pense que C ++ est en fait un peu insuffisant. L'idée d'avoir des fonctions non virtuelles par exemple est une tique à cet égard. J'ai eu des arguments avec ceux qui ne sont pas d'accord avec moi, mais les membres non virtuels ne correspondent tout simplement pas au paradigme en ce qui me concerne. Le polymorphisme est un composant clé de l'OO et les classes avec des fonctions non virtuelles ne sont pas polymorphes au sens de l'OO. Donc, en tant que langage OO, je pense que C ++ est en fait plutôt faible par rapport à des langages comme Java ou Objective-C.
La programmation générique, d'autre part, C ++ a celui-ci assez bon. J'ai entendu dire qu'il y avait aussi de meilleurs langages pour cela, mais la combinaison d'objets et de fonctions génériques est quelque chose de très puissant et expressif. De plus, il peut être sacrément rapide en temps de programmation ET en temps de traitement. C'est vraiment dans ce domaine que je pense que le C ++ brille, mais il est vrai que cela pourrait être mieux (support du langage pour les concepts par exemple). Quelqu'un pensant qu'ils devraient s'en tenir au paradigme OO et traiter les autres dans l'ordre de la déclaration goto en termes d'immoralité est vraiment absent en ne regardant pas ce paradigme.
La capacité de métaprogrammation des modèles est également assez impressionnante. Consultez la bibliothèque Boost.Units par exemple. Cette bibliothèque fournit un support de type pour les quantités dimensionnelles. J'ai beaucoup utilisé cette bibliothèque dans la firme d'ingénierie pour laquelle je travaille actuellement. Il fournit simplement une rétroaction beaucoup plus immédiate pour un aspect du programmeur possible, ou même une erreur de spécification. Il est impossible de compiler un programme qui utilise une formule où les deux côtés de l'opérateur '=' ne sont pas dimensionnellement équivalents sans transtypage explicite. Personnellement, je n'ai aucune expérience avec un autre langage dans lequel cela est possible, et certainement pas avec un autre qui a également la puissance et la vitesse de C ++.
La métaprogrammation est un paradigme purement fonctionnel.
Donc vraiment, je pense que vous entrez déjà dans le C ++ avec quelques malentendus malheureux. Les autres paradigmes en dehors de l'OO ne sont pas à éviter, ils doivent être LEVERAGÉS. Utilisez le paradigme naturel pour l'aspect du problème sur lequel vous travaillez. Ne forcez pas les objets sur ce qui n'est essentiellement pas un problème sujet. En ce qui me concerne, OO n'est même pas la moitié de l'histoire de C ++.
la source
Je voulais accepter une réponse à cette question, mais je ne pouvais pas décider d'une réponse à laquelle accorder la coche. En tant que tel, j'ai surévalué les auteurs originaux et créé cela comme une réponse sommaire. Merci à tous ceux qui ont pris quelques minutes, j'ai trouvé que la perspicacité que vous m'avez fournie m'a donné une bonne direction et un peu d'assurance que je n'étais pas déraillé.
@nightcracker
J'ai senti que j'avais observé ce problème en action dans le passé. Vos commentaires m'ont également rappelé qu'en masquant les variables sous-jacentes et leur implémentation, je suis libre de modifier leur implémentation sans détruire quoi que ce soit qui en dépende.
Dominic Gurto
Je pensais que le commentaire de Dominic était un grand idéal auquel aspirer, mais je pense que le commentaire de Gene frappe vraiment la réalité de la situation. Jusqu'à présent, j'ai vu cela en action ... et je me sens un peu mieux que ce n'est pas rare. Je pense qu'à mesure que je serai mature en tant que programmeur, je m'orienterai vers des conceptions plus complètes, mais en ce moment je souffre toujours de sauter dedans et d'obtenir du code écrit.
wantTheBest
Cela a beaucoup de sens ... J'ai aimé l'idée de garder les choses au travail, mais de remanier certaines des choses non critiques avec les classes.
jpm
Je sais depuis un certain temps que c'est l'une des forces de l'encapsulation des données ... être en mesure d'imposer la cohérence et, par ailleurs, les conditions / plages / etc.
Crazy Eddie
À l'origine, j'ai manqué beaucoup de choses dans la réponse de Crazy Eddie, je pense parce que je n'avais pas lu certains des sujets mentionnés ... comme la métaprogrammation. Je pense que le grand message dans le post de CE était que C ++ est un tel mélange de capacités et de styles que chacun devrait être utilisé à son meilleur potentiel ... y compris impératif si c'est ce qui a du sens.
Encore une fois, merci à tous ceux qui ont répondu!
la source
Le plus grand écueil est la croyance que la POO est une solution miracle, ou le «paradigme parfait».
la source