Qu'est-ce qu'un processus simple pour concevoir un système POO avant de le coder?

10

Chaque fois que je devais construire un projet, je réussissais toujours à le construire, pas avant de concevoir un plan ou une conception, mais après avoir d'abord écrit une classe qui était nécessaire, étoffer tout le projet, construire à partir de la base. Maintenant, je sais que ce n'est pas la bonne façon de créer un logiciel, mais il n'est pas facile pour moi de comprendre ce qu'on appelle l'analyse et la conception orientées objectivement. Je peux plus facilement comprendre la conception procédurale descendante, car elle consiste à simplement décomposer les tâches en sous-tâches, des choses qui ont leur contrepartie en code, des fonctions. Mais l'analyse et la conception orientées objet ne me sont pas faciles à comprendre, car je ne comprends pas comment on peut savoir de quelles classes ils auront besoin et comment ils interagiront, à moins de savoir comment ils les coderont.

Pour une fois que nous introduisons le concept de classes et d'objets dans le processus de conception, nous ne pouvons plus concevoir de haut en bas, car nous ne décomposons plus nos problèmes en ces choses qui peuvent être implémentées en tant que procédures. Au lieu de cela, selon ce que j'ai lu sur le sujet, nous devons déterminer quelles classes sont nécessaires et créer divers artefacts en langage de modélisation unifié, que nous pouvons ensuite utiliser lorsque nous implémentons le logiciel. Mais je ne comprends pas ce genre de processus de conception. Car comment sait-on de quelles classes ils auront besoin et comment ils interagiront, à moins d'avoir déjà conçu l'ensemble du système?

C'est alors mon problème. Je ne comprends pas comment concevoir un système orienté objet, bien que je comprenne les concepts de la programmation orientée objet, et je peux utiliser ces concepts dans n'importe quel langage de programmation orientée objet que je connais. Par conséquent, j'ai besoin que quelqu'un m'explique quel processus simple je peux utiliser pour concevoir des systèmes orientés objets d'une manière qui me semble logique.

g.arbia777
la source
8
"Maintenant, je sais que ce n'est pas la bonne façon de créer un logiciel" - qui vous l'a dit? Il semble que vous tombiez dans le piège populaire de croire que "le design est quelque chose que vous faites avant de coder, peut-être en dessinant des diagrammes UML fantaisistes". Pour vous guérir de cette idée fausse, je recommande de commencer par "Code as Design" par Jack Reeves.
Doc Brown
@DocBrown. Ne pensez-vous pas que le design tout en codant est ce qui rend notre travail si artisanal? Je ne peux pas imaginer d'autres usines fonctionnant de la même façon. Imaginez un architecte piller des briques et du mortier et concevoir le bâtiment / pont sur le chemin.
Laiv
5
@Laiv: « codage » fait partie de ce que dans les autres disciplines du génie est appelé la conception. Dans la construction de maisons, l'étape de la conception au produit final se fait à l'aide de briques et de mortier de boulochage. En programmation, cette étape est effectuée par le compilateur lors de la traduction de la conception (= programme) en produit final (= binaire exécutable). Et ce n'est pas une nouvelle sagesse. Les essais Reeves ont 25 ans.
Doc Brown
@DocBrown, le développeur. * N'est-il plus organisé? Le bouton d'abonnement est cassé par exemple.
radarbob

Réponses:

20

Le style de cascade de haut en bas OOAD ne garantit pas du tout que le code que vous écrivez est orienté objet. J'ai vu des montagnes de code strictement produit par OOAD qui le prouvent. Si OO vous déroute, ne cherchez pas ici de l'aide. Vous ne le trouverez pas. OO ne vous oblige PAS à concevoir de haut en bas.

Si vous plongez dans une classe, c'est comme vous aimez coder, tant pis. Permettez-moi de vous donner un indice. Remettre à plus tard.

C'est incroyable comme il est facile de concevoir des classes en écrivant du code qui les utilise même lorsqu'elles n'existent pas encore. Oubliez la procédure. Oubliez la structure. Obtenez-vous simplement un bon niveau d'abstraction cohérent et respectez-le. Ne vous laissez pas tenter et mélangez-y des détails supplémentaires. Tout ce qui vous sort de l'abstraction actuelle peut être fait dans une méthode qui pourrait être sur un autre objet qui sait en quelque sorte tout ce qu'il a besoin de savoir. Ne construisez rien que vous puissiez simplement demander à vous remettre.

Apprenez à écrire comme ça et vous constaterez que vous faites OO sans même essayer très fort. Cela vous oblige à regarder vos objets du point de vue de la façon dont ils sont utilisés (leur interface) et quels objets connaissent quels autres objets. Devinez quels sont les deux principaux points d'un diagramme UML?

Si vous pouvez entrer dans ce mode de pensée, ce qui reste est l'architecture. Nous sommes tous encore en train de comprendre cela. Du MVC à l'architecture propre à la conception pilotée par domaine. Étudiez-les et jouez. Utilisez ce qui fonctionne. Si vous trouvez quelque chose de 100% fiable, revenez me le faire savoir. Je fais ça depuis des décennies et je cherche toujours.

candied_orange
la source
2
Ou vous vous retrouvez ne pas faire OO et pourtant tout "en quelque sorte" fonctionne bien de toute façon ...
Derek Elkins a quitté le SE
2
"C'est incroyable comme il est facile de concevoir des classes en écrivant du code qui les utilise même lorsqu'elles n'existent pas encore" - j'appelle cette conception descendante, mais il semble que je me trompe. Qu'est-ce que la conception descendante et quelle est cette chose que j'ai appelée ainsi? S'agit-il d'une programmation vers une interface?
Piovezan
Ce n'est pas simplement de haut en bas. Vous devez également être prêt à ne pas construire des choses que vous pouvez simplement demander en acceptant des paramètres.
candied_orange
@Piovezan vous pouvez le faire même lorsque l'interface n'existe pas encore. Ignorez juste un peu votre compilateur. Plus tard, vous le ferez exister.
candied_orange
@CandiedOrange "Vous devez également être disposé à ne pas construire des choses que vous pouvez simplement demander en acceptant des paramètres." - Je ne suis pas sûr de comprendre, pourriez-vous clarifier / fournir un court exemple (ou un contre-exemple d'ailleurs)?
Piovezan
4

Vous prétendez pouvoir utiliser des techniques orientées objet dans votre code, de sorte que vous savez déjà comment concevoir un système orienté objet , je pense que votre problème est plus une question de moment , pas si vous le pouvez ou non. Vous semblez à l'aise avec la conception orientée objet de manière itérative à court terme, au lieu d'une méthode de planification à long terme.

Lors du premier développement d'un projet, il peut être très difficile de planifier et de concevoir, c'est alors que le développement agile est préféré au développement en cascade , car la grande portée d'un plan en cascade ne capturera souvent pas toutes les complexités d'un projet logiciel.

Vous affirmez que développer à la volée sans «plan initial», c'est:

"... pas la bonne façon de créer un logiciel ..."

Si votre problème est que votre plan initial n'est pas suffisamment détaillé, prenez un peu plus de temps pour expliquer vos premières réflexions. Quelle est la première partie du programme que vous prévoyez d'écrire? De quoi aura-t-il besoin ? Peut-être ne pensez même pas à quels objets commencer, pensez plutôt aux fonctionnalités et au plan à partir de là.

Si votre problème est que vous n'avez pas confiance en vos compétences en documentation / conception / UML , entraînez-vous en documentant un projet existant.

Personnellement, je recommanderais de ne pas vous soucier que vos conceptions soient parfaitement orientées objet, la plupart des systèmes ne sont pas 100% orientés objet. Le but est de créer une meilleure compréhension et visualisation du système, pas une abstraction parfaite. L'orientation des objets n'est pas la solution miracle, c'est juste un autre outil sur la ceinture.

Erdrik Ironrose
la source
Je voulais également mentionner, bien qu'un peu hors sujet pour la réponse ... Vos plans n'ont pas besoin d'être très grands! Parfois, un plan est simplement une question de «je veux l'exécuter et ça fait quelque chose». C'est assez bien, si c'est vraiment tout ce qu'il va faire.
Erdrik Ironrose
2

OOAD est une utopie. Je ne veux pas dire par là que c'est la meilleure approche, je veux dire qu'elle n'est jamais vraiment réalisable à mon humble avis. D'après mon expérience, quelque chose change toujours, qu'il s'agisse d'exigences ou de spécificités, ou même d'un conflit de dépendance qui vous oblige à remplacer entièrement une dépendance. Que ce soit parce que j'ai appris de cette façon ou parce que c'est ce qui me vient le plus naturellement, mes idées de design viennent plus facilement lorsque j'écris du code. Si je suis sur le point de coder et que je n'ai pas une idée claire de la façon dont je vais structurer le code, je m'attacherai à consacrer du temps à vraiment comprendre le problème d'abord, bien que plus souvent qu'autrement, je vois le nécessité d'une classe et je vais le faire.

Mon conseil serait que la meilleure chose que vous puissiez faire pour vous-même est d'utiliser du code en utilisant des façades , fournissant une interface simple pour les entrées et les sorties, et j'espère que les entrées et les sorties ne changent pas souvent. Même si c'est le cas, sachez qu'il ne s'agit pas tant d'un problème de conception que d'un problème de spécifications (changement de nécessité / fonctionnement / fonctionnalité). Cela rendra votre programme quelque peu résistant aux problèmes qui résonnent dans votre programme envers ceux qui appellent votre programme ou section de code et vice versa.

En ce qui concerne la conception d'un système orienté objet, quelque chose devrait être dit pour essayer de tout orienter objet alors qu'il ne devrait pas l'être. C'est une erreur courante parmi les langages de programmation OOP comme C # et Java est d'essayer de tout traiter comme un objet, ce qui entraîne souvent la création d'une seule instance d'une classe pour exécuter ce qui serait autrement des méthodes statiques qui ne changent pas d'état. Cela dit, bien sûr, vous devez utiliser la conception OOP le cas échéant, mais ne vous sentez pas comme si vous le faisiez mal quand il semble plus naturel d'écrire une méthode statique. Ce n'est pas toujours le mauvais instinct.

Vous devriez envisager d'utiliser un cours lorsque vous répondez oui à l'une des questions suivantes:

  • Ai-je un groupe d'informations concernant le même concept (c.-à-d. Prénom, nom, adresse)?
  • Dois-je effectuer une opération nécessitant plusieurs informations (par exemple calculatePrice(basePrice, quantity, tax))?
  • Ai-je un autre si avec de gros blocs de code effectuant des opérations légèrement différentes avec les mêmes informations ou des informations similaires (ie if(type == "cat") { meow(name); } else if (type == "dog") { bark(name); }==> animal.speak())
  • Ai-je une classe existante qui effectue plus d'une tâche spécifique et s'agrandit un peu trop?

Après un certain temps, il deviendra une seconde nature de créer des classes. N'ayez pas peur de les utiliser si votre code tombe dans l'un des cas ci-dessus. J'espère que ça aide!

Neil
la source
2

Je pense que les remarques faites par Doc Brown dans les commentaires méritent beaucoup plus de visibilité qu'un commentaire puisqu'il a absolument raison:

" Maintenant, je sais que ce n'est pas la bonne façon de créer un logiciel " - qui vous l'a dit? Il semble que vous tombiez dans le piège populaire de croire que "le design est quelque chose que vous faites avant de coder, peut-être en dessinant des diagrammes UML fantaisistes". Pour vous guérir de cette idée fausse, je recommande de commencer par "Code as Design" par Jack Reeves. - Doc Brown 21 juin à 5:27

@Laiv: le "codage" fait partie de ce que l'on appelle dans d'autres disciplines de l'ingénieur la conception. Dans la construction de maisons, l'étape de la conception au produit final se fait à l'aide de briques et de mortier de boulochage. En programmation, cette étape est effectuée par le compilateur lors de la traduction de la conception (= programme) en produit final (= binaire exécutable). Et ce n'est pas une nouvelle sagesse. Les essais Reeves ont 25 ans. - Doc Brown 21 juin à 6h39

Ce même sentiment se retrouve également ailleurs. Considérez les exposés de Glenn Vanderburg sur le "Real Software Engineering", et dans une certaine mesure ses discours "Craft, Engineering, and the Essence of Programming" et "Craft and Software Engineering". Voir également les WhatIsSoftwareDesign et TheSourceCodeIsTheDesign pages / discussions sur le wiki C2.

Le concept du code étant la conception n'est spécifique à aucun paradigme. Il peut être appliqué de manière égale à orienté objet, fonctionnel, procédural, logique ou autre. L'idée sous-jacente est la même - la conception est le code source lui-même. L'acte de construction est le processus par lequel le code source (la conception) est transformé en une chose utilisable par un interprète ou un compilateur.

Dans un système complexe, il y aura probablement une conception architecturale de niveau supérieur - en identifiant les sous-systèmes, composants, modules, services et en leur allouant des exigences avant de commencer à écrire du code. Vous pouvez utiliser UML comme un moyen de créer, documenter et faciliter les discussions autour de cette conception architecturale. Considérez l'idée des modes UML dont Martin Fowler discute , en particulier UML en tant que croquis et UML en tant que notes . Examinez également quelques idées de la modélisation agile - modélisation de l' architecture initiale , modélisation de l'itération et modèles à peine assez bons .

Tout cela signifie que la bonne façon de créer un logiciel n'est pas d'étoffer l'ensemble du projet. Il s'agit de passer juste assez de temps à comprendre les exigences les plus critiques (à l'heure actuelle), à ​​identifier les dépendances techniques et les compromis entre les exigences, puis à tirer parti du fait que le logiciel est souple. Reconnaissez également que le coût de prendre votre conception et de produire quelque chose est incroyablement bas (en particulier par rapport à prendre une conception et produire quelque chose dans de nombreuses autres disciplines d'ingénierie). Parcourez donc vos activités de conception (codage) et profitez de la facilité et de la rentabilité de construire ou de modifier progressivement ce que vous avez fait.

Thomas Owens
la source
1

OOAD consiste à identifier des entités et à modéliser des objets ou des concepts de la vie réelle à un degré d'abstraction. Vous le percevrez comme étant plus facile si au lieu d'écrire des classes, vous écrivez des interfaces au début, car vous n'avez pas encore vraiment à les implémenter, mais le code se compile.

OOAD n'exclut pas la possibilité de penser dans le système comme de grands modules. Vous pouvez toujours faire ça. Chaque module existe pour satisfaire un ensemble de user stories (cas d'utilisation). De telles histoires d'utilisateurs ont besoin de classes qui collaborent pour les réaliser.

Une différence clé entre les approches procédurales et OO est que, généralement, la pensée procédurale mappe les exigences aux écrans, tandis que OOD a tendance à penser à ce qui se passe sous le capot, laissant le devant être fait par une autre personne ou de manière non OO.

Il y a une technique dans la programmation extrême appelée CRC Cards . CRC signifie "classe-responsabilités-collaborateurs".

Fondamentalement, vous identifiez les classes évidentes et attribuez une carte à chacune. Disons que la classe Invoicea sa propre carte.

Pour chaque classe détentrice de cartes, vous écrivez quelles seraient les responsabilités de cette classe, par exemple "calcule un grand total" .

Aussi pour chaque classe détentrice de cartes, vous écrivez quelles autres classes cette classe doit demander pour remplir ses propres responsabilités. Ici, vous pouvez découvrir les Invoicebesoins de la collaboration InvoiceDetailou même découvrir qu'une telle classe est nécessaire en premier lieu.

Vous découvrirez peut-être que certaines responsabilités auxquelles vous pensiez appartenir Invoceappartiennent vraiment à l'un de ses collaborateurs.

Après l'exercice, chaque carte devient une classe, chaque responsabilité devient une méthode et chaque relation de collaboration peut devenir une composition, une agrégation ou un simple appel.

Cet exercice peut (et devrait) être fait en groupe, où même les gens d'affaires participent.

Vous pouvez en savoir plus sur cette technique dans ces liens:

http://en.wikipedia.org/wiki/Class-responsibility-collaboration_card

http://www.extremeprogramming.org/rules/crccards.html

Exemples de cartes CRC:

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

Tulains Córdova
la source
0

Le principal défi pour nous, en tant que communauté de praticiens du logiciel; plus spécifiquement les praticiens de la conception orientée objet, est celui de matérialiser tous nos problèmes / tâches en une partie routeur de programmation. Que ce soit des tâches - représentées comme des fonctions ou des acteurs des tâches - représentées comme des interfaces / classes [conduisant vers OOAD]. Au fur et à mesure que nous évoluons nos habitudes de conception de logiciels, en acquérant continuellement des connaissances sur diverses méthodologies / cadres. Notre point de vue s'affine de plus en plus vers une séparation claire des objets et quel objet remplirait quelle fonction.

Quant à décomposer vos problèmes en sous-problèmes avec la présence d'objets autour, vous pouvez toujours le faire facilement, car VOUS avez le contrôle total de tous les objets que vous souhaitez être présents. Vous avez également la possibilité de conférer un caractère et un but à vos objets et interfaces. Tout ce que vous avez à faire est de visualiser l'énoncé du problème et de penser à quel but / fonctionnalité peut être transmis à quel objet.

J'essaierai d'expliquer davantage à l'aide d'un exemple de la gamme d'automobiles et je mettrai en évidence deux façons différentes de visualiser le même modèle d'objet.

Prenons un exemple du constructeur automobile qui couvre plusieurs catégories d'automobiles: véhicules utilitaires, voitures de consommation (berlines, hayon, break), etc.

Pour que le fabricant ait clairement une séparation de catégorie et d'objet, il existe plusieurs façons de créer des classes.

Fabricant de véhicules OOAD

  1. Basé sur la catégorie (secteur de marché) du véhicule: véhicule lourd, véhicule de consommation [berline, hayon, break, etc.]

  2. Basé sur la capacité du moteur et la manière de conduire: 800-1500 CC,> 1500 CC, etc.

En utilisant la meilleure façon dont le fabricant peut conférer individuellement des fonctions à des objets appartenant à chacune de ces classifications, ils peuvent choisir une conception d'objet sous-jacente appropriée et y construire un modèle par-dessus.

Akash Mishra
la source
Vous commencez bien, mais le dernier morceau ressemble à l'erreur que OOD vise à catégoriser les choses plutôt qu'à grouper des comportements similaires.
Pete Kirkham