Question

Je suis un développeur de longue date (je suis 49), mais plutôt nouveau pour le développement orienté objet. Je l'ai lu sur OO depuis Eiffel de Bertrand Meyer, mais ont fait vraiment peu de programmation orientée objet.

Le point est chaque livre commence conception OO avec un exemple d'un bateau, voiture ou tout autre objet commun que nous utilisons très souvent, et ils commencent à ajouter des attributs et des méthodes, et expliquer comment ils modéliser l'état de l'objet et ce qui peut être fait avec elle.

Alors, ils vont généralement quelque chose comme « le meilleur modèle plus il représente l'objet dans l'application et le meilleur tout sort ».

Jusqu'à présent, si bon, mais, d'autre part, je l'ai trouvé plusieurs auteurs qui donnent des recettes telles que « une classe doit correspondre à juste une seule page » (je voudrais ajouter « sur la taille de l'écran? » Maintenant nous essayons de ne pas imprimer le code!).

Prenons par exemple une classe PurchaseOrder, qui a une machine à états finis contrôler son comportement et une collection de PurchaseOrderItem, l'un des arguments ici au travail est que nous devrions utiliser une classe simple PurchaseOrder, avec certaines méthodes (un peu plus d'un classe de données), et une PurchaseOrderFSM « classe expert » qui gère la machine à états finis pour la PurchaseOrder.

Je dirais que dans la tombe « Feature Envy » ou « Intimacy inappropriée » classement de Jeff Atwood poste de code Smells sur Coding Horror. Je venais de l'appeler le bon sens. Si je peux émettre, approuver ou annuler mon ordre réel d'achat, puis la classe PurchaseOrder devrait avoir des méthodes issuePO, approvePO et cancelPO.

ne pas va de pair avec la « cohésion Maximize » et « minimiser le couplage » âge vieux principes que je comprends comme les pierres angulaires de OO?

Par ailleurs, ne pas aide vers la maintenabilité de la classe?

Était-ce utile?

La solution

classe A doit utiliser le principe de responsabilité unique. La plupart des très grandes classes, je l'ai vu faire beaucoup de choses qui est la raison pour laquelle ils sont trop grands. Regardez chaque méthode et le code décider doit-il être dans cette classe ou séparée, le code en double est un indice. Vous pourriez avoir une méthode issuePO mais il contient 10 ne lignes de code d'accès aux données par exemple? Ce code devrait probablement pas être là.

Autres conseils

Dans ma taille de la classe d'opinion n'a pas d'importance tant que les variables, fonctions et méthodes sont pertinentes à la classe en question.

Le plus gros problème avec les grandes classes est quand il s'agit de tester ces classes, ou leur interaction avec d'autres classes. Grande taille de la classe elle-même est pas un problème, mais comme toutes les odeurs, il indique un potentiel problème. D'une manière générale, lorsque la classe est grande, qui est une indication que la classe est en train de faire plus d'une seule classe devrait.

Pour votre analogie de voiture, si la classe car est trop grande, qui est probablement une indication qu'il doit être divisé en engine de classe, doors de classe et windshields de classe, etc.

Je ne pense pas qu'il y ait une définition spécifique d'une classe trop grande. Cependant, je voudrais utiliser les directives suivantes pour déterminer si je factoriser ma classe ou redéfinir la portée de la classe:

  1. Y at-il de nombreuses variables indépendantes les unes des autres? (Ma tolérance personnelle est d'environ 10 à 20 dans la plupart des cas)
  2. Y at-il de nombreuses méthodes conçues pour les cas d'angle? (Ma tolérance personnelle est ... eh bien, cela dépend fortement de mon humeur, je suppose)

En ce qui concerne 1, imaginez que vous définissez la taille de votre pare-brise, la taille roue, queue modèle ampoule, et 100 autres détails dans votre car de classe. Bien qu'ils soient tous « pertinents » à la voiture, il est très difficile de tracer le comportement de ces car de classe. Et quand un jour votre collègue accidentellement (ou, dans certains cas, intentionnellement) modifie la taille du pare-brise en fonction de la queue modèle d'ampoule, il vous faut toujours savoir pourquoi pas le pare-brise plus fits dans votre voiture.

En ce qui concerne 2, imaginez que vous essayez de définir tous les comportements d'une voiture peut avoir dans le car de classe, mais car::open_roof() ne sera disponible que pour les cabriolets et car::open_rear_door() ne vaut pas pour les voitures 2 portes. Bien que les cabriolets et les voitures 2 portes sont « voitures » par définition, leur application dans la car de classe complique la classe. La classe devient plus difficile à utiliser et plus difficile à maintenir.

Autre que ces 2 lignes directrices, je suggère une définition claire de la portée de la classe. Une fois que vous définissez la portée, la mise en œuvre de la classe strictement basée sur la définition. La plupart du temps, les gens une classe « trop grand » en raison de la mauvaise définition du champ d'application, ou en raison des caractéristiques arbitraires ajoutées à la classe

Dites ce que vous avez besoin dans 300 lignes

Remarque: cette règle suppose que vous suivez l'approche « une classe par fichier », qui est en soi une bonne idée de maintenabilité

Il est pas une règle absolue, mais si je vois plus de 200 lignes de code dans une classe que je me méfie. 300 lignes et sonnettes d'alarme sont allumés. Quand j'ouvre le code quelqu'un d'autre et de trouver 2000 lignes, je sais que ça refactorisation temps sans même lire la première page.

La plupart du temps cela se résume à maintenabilité. Si vous vous opposez est si complexe que vous ne pouvez pas exprimer son comportement dans 300 lignes, il va être très difficile pour quelqu'un d'autre à comprendre.

Je trouve que je me penche cette règle dans le modèle -> ViewModel -> Voir le monde où je suis en train de créer un « objet de comportement » pour une page de l'interface utilisateur, car il faut souvent plus de 300 lignes pour décrire la série complète des comportements sur une page. Cependant, je suis encore nouveau pour ce modèle de programmation et de trouver de bons moyens de refactorisation / réutilisation des comportements entre les pages / viewmodels qui réduit progressivement la taille de mes ViewModels.

Regardons les choses en nous mettre au travail en arrière:

ne pas va de pair avec la « cohésion Maximize » et « minimiser le couplage » âge vieux principes que je comprends comme les pierres angulaires de OO?

En fait, il est une des pierres angulaires de la programmation, dont OO est un paradigme, mais.

Je vais laisser Antoine de Saint-Exupéry répondre à votre question (parce que je suis paresseux;)):

La perfection est atteinte, non pas lorsqu'il n'y a plus rien à ajouter, mais quand il n'y a rien à enlever.

Le plus simple la classe, plus confiant que vous serez c'est juste, plus il sera pleinement tester.

Je suis avec l'OP sur la classification Envy fonction. Rien ne me énerve plus que d'avoir un tas de classes avec un tas de méthodes que les travaux sur les parties internes d'une autre classe. OO suggère que vous modèle de données et les opérations sur ces données. Cela ne signifie pas que vous mettez les opérations dans un endroit différent à partir des données! Il essaie de vous faire mettre les données et les méthodes ensemble .

Avec les modèles car et person si répandue, ce serait comme mettre le code pour faire la connexion électrique ou même tourner le démarreur, dans la classe person. Je souhaite que ce serait évidemment faux pour tout programmeur expérimenté.

Je n'ai pas vraiment une classe idéale ou la taille méthode, mais je préfère garder mes méthodes et ajustement des fonctions sur un seul écran afin que je puisse voir leur intégralité en un seul endroit. (J'ai configuré pour ouvrir Vim une fenêtre 60 en ligne, qui se trouve être juste autour du nombre de lignes sur une page imprimée.) Il y a des endroits où cela ne fait pas beaucoup de sens, mais ça fonctionne pour moi. J'aime suivre la même ligne directrice pour les définitions de classe, et essayer de garder mes fichiers sous quelques « pages » longues. Tout ce que plus de 300, 400 lignes commence à se sentir trop compliqué (surtout parce que la classe a commencé à prendre trop de responsabilités directes).

Quand une définition de classe a quelques centaines de méthodes, il est trop grand.

Je suis entièrement d'accord avec l'utilisation du principe seule responsabilité pour les classes, mais si cela est suivi et les résultats dans les grandes classes, puis soit. L'objectif réel devrait être que les méthodes individuelles et les propriétés ne sont pas trop grandes, cyclomatique complexité devrait être le guide il et à la suite qui peut donner lieu à de nombreuses méthodes privées qui permettront d'accroître la taille globale de la classe, mais laissera lisible et testable à un niveau granulaire. Si le code reste lisible taille alors est hors de propos.

L'émission d'un ordre d'achat est souvent un processus complexe qui implique plus que l'ordre d'achat. Dans ce cas, en gardant la logique métier dans une catégorie distincte et de faire l'ordre d'achat plus simple est probablement la bonne chose à faire. En général, cependant, vous avez raison - vous ne voulez pas les classes « structure de données ». Par exemple, votre méthode d'affaires classe issue() « POManager » devrait probablement appeler la méthode de issue() du PO. Le PO peut alors définir son statut « Délivré » et notez la date d'émission, alors que le POManager peut alors envoyer une notification aux comptes à payer pour leur faire savoir d'attendre une facture, et une autre notification à l'inventaire afin qu'ils sachent qu'il ya quelque chose à venir et la date prévue.

Toute personne qui pousse « règles » pour la taille méthode / classe n'a évidemment pas passé assez de temps dans le monde réel. Comme d'autres l'ont mentionné, il est souvent un indicateur de refactoring, mais parfois (surtout dans « le traitement des données » travail -type) vous avez vraiment besoin d'écrire une classe avec une méthode unique qui couvre plus de 500 lignes. Ne vous attardez pas sur le sujet.

Je l'ai trouvé plusieurs auteurs qui donnent recettes telles que « une classe devrait correspondre juste une seule page »

En ce qui concerne seulement la taille physique d'une classe, voir une grande classe est une indication d'une odeur de code, mais ne signifie pas nécessairement qu'il y ait toujours des odeurs. (En général, ils sont cependant) Comme les pirates dans les Pirates des Caraïbes diraient, ce qui est plus ce que vous appelez « lignes directrices » que les règles actuelles. Je l'avais essayé en suivant strictement le « plus d'une centaine LOC dans une classe » une fois et le résultat était beaucoup d'over-engineering inutile.

Alors, ils vont habituellement quelque chose comme « la mieux le modèle mieux ce représente l'objet dans la l'application et le mieux tout sort ».

Je commence habituellement mes dessins avec cela. Qu'est-ce que cette classe faire dans le monde réel? Comment ma classe reflète cet objet comme indiqué dans ses exigences? Nous ajoutons un peu d'état ici, un champ là, une méthode pour travailler sur ces champs, ajouter un peu plus et le tour est joué! Nous avons une classe ouvrière. Maintenant, remplissez les signatures avec les implémentations appropriées et nous sommes bon pour aller, ou si vous pensez. Maintenant, nous avons bien grande classe avec toutes les fonctionnalités dont nous avons besoin. Mais le problème est, il ne prend pas la façon dont le monde réel fonctionne en compte. Et que je veux dire qu'il ne prend pas en compte, « CHANGE ».

La raison pour laquelle les classes sont de préférence divisés en parties plus petites est qu'il est difficile de changer les grandes classes plus tard sans affecter la logique existante ou l'introduction d'un nouveau bug ou deux faire sans le vouloir ou tout simplement tout difficile à réutiliser. C'est là refactorisation, design patterns, SOLID, etc. entrent en jeu et le résultat final est généralement une petite classe ouvrière sur d'autres plus petites, sous-classes plus granulaires.

En outre, dans votre exemple, en ajoutant IssuePO, ApprovePO et Annuler PO dans la classe PurchaseOrder semble illogique. Les commandes d'achat ne sont pas délivrés, approuver ou annuler eux-mêmes. Si PO doit avoir des méthodes, puis les méthodes devraient travailler sur son état non sur la classe dans son ensemble. Ils sont vraiment seulement des données / classes que d'autres classes records travaillent.

assez grand pour contenir toute la logique nécessaire pour exécuter son travail.

assez petit pour être maintenable et suivez les unique Responsabilité Principe .

Licencié sous: CC-BY-SA avec attribution
scroll top