Question

Prémisse

Je crois qu'il ya un moyen de définir objectivement « bonnes » et « mauvaises » techniques de conception orienté objet et que, en tant que communauté, nous pouvons déterminer ce que ceux-ci sont. Ceci est un exercice académique. Si cela est fait avec sérieux et détermination, je crois qu'il peut être très bénéfique pour la communauté dans son ensemble. La communauté bénéficiera en ayant un endroit où nous pouvons tous citer dire: « Cette technique est « bon » ou « mauvais » et nous devrions ou ne devrait pas l'utiliser à moins que des circonstances particulières ».

plan

Pour cet effort, nous devons nous concentrer sur des principes orientés objet (par opposition à fonctionnelle, basé sur un ensemble ou un autre type de langues).

Je ne prévois pas d'accepter une réponse, au lieu que je voudrais les réponses de contribuer à la collecte finale ou un débat rationnel des questions.

Je me rends compte que cela peut controverse, mais je crois que nous pouvons repasser quelque chose. Il y a des exceptions à la plupart de chaque règle et je crois que c'est là le désaccord tombera. Nous devons faire des déclarations et noter les exceptions pertinentes et les objections des contestataires.

Base

Je voudrais prendre un coup de poignard à définir « bon » et « Bad »:

  • "Good" - Cette technique fonctionnera la première fois et être une solution durable. Il sera facile de changer plus tard et payer l'investissement en temps de sa mise en œuvre rapidement. Elle peut être appliquée de manière cohérente et facilement reconnu par les programmeurs de maintenance à l'avenir. Dans l'ensemble, elle contribue à la bonne fonction et réduit les coûts d'entretien pendant la durée du produit.

  • « Bad » - Cette technique peut fonctionner à court terme, mais devient rapidement un passif. Il est difficile de changer immédiatement ou devient plus difficile au fil du temps. L'investissement initial peut être petite ou grande, mais il devient rapidement un coût de plus en plus, par la suite devenir un coût irrécupérable et doit être enlevé ou travaillé autour en permanence. Il est subjectivement appliquée et incohérente et peut-être une surprise ou non facilement reconnaissable par les programmeurs de maintenance à l'avenir. Dans l'ensemble, elle contribue à l'ultime augmentation des coûts de maintien et / ou l'utilisation du produit et inhibe ou empêche les modifications au produit. En inhibant ou la prévention du changement, il devient non seulement un coût direct, mais un coût d'opportunité et une responsabilité importante.

Starter

À titre d'exemple de ce que je pense qu'une bonne contribution ressemblerait, je voudrais proposer un principe de « bon »:

Séparation des préoccupations

[Courte description]

Exemple

[Code ou un autre type d'exemple]

Objectifs

[Explication de ce que les problèmes ce principe empêche]

Application

[Pourquoi, où et quand devrais-je utiliser ce principe?]

Exceptions

[Quand je n'utiliser ce principe, ou où pourrait-il? Être nuisible]

Oppositions

[Note des opinions dissidentes ou des objections de la communauté ici]

Était-ce utile?

La solution

Séparation des préoccupations

L'agrégation à l'héritage Je préfère mixin style

Alors que la fonctionnalité peut être acquise en héritant d'une classe utilitaire, dans de nombreux cas, il peut tous être acquis au moyen d'un membre de ladite classe.

Exemple (Boost.Noncopyable):

Boost.Noncopyable est une classe C ++ qui n'a pas un constructeur de copie ou opérateur d'affectation. Il peut être utilisé en tant que classe de base pour empêcher la sous-classe d'être copié ou affecté (ce qui est le comportement commun). Il peut également être utilisé en tant que membre direct

Convertir ceci:

class Foo : private boost::noncopyable { ... };

Pour cela:

class Foo {
    ...
private:
    boost::noncopyable noncopyable_;
};

Exemple (objet verrouillable):

Java introduit le mot-clé comme un idiome synchronized pour permettre un objet à utiliser d'une manière threadsafe. Cela peut se refléter dans d'autres langues pour fournir mutex à des objets arbitraires. Un exemple courant est des structures de données:

class ThreadsafeVector<T> : public Vector<T>, public Mutex { ... };

Au lieu de cela, les deux classes pourraient être regroupées ensemble.

struct ThreadsafeVector<T> {
    Vector<T> vector;
    Mutex mutex;
}

Objectifs

L'héritage est souvent abusé comme mécanisme de réutilisation de code. Si l'héritage est utilisé pour quoi que ce soit en plus d'une relation Is-A, le code général de clarté est réduite.

Avec des chaînes plus profondes, les classes de base mixins augmentent considérablement la probabilité d'un scénario « diamant de la mort », dans laquelle une sous-classe finit par hériter plusieurs copies d'une classe mixin.

Application

Toute langue qui prend en charge l'héritage multiple.

Exceptions

tous les cas où la classe mixin fournit ou exige des membres de surcharge. Dans ce cas, l'héritage implique généralement une Is-Mis en œuvre-In-termes de relation, et un agrégat ne sera pas suffisante.

Oppositions

Le résultat de cette transformation peut conduire à des membres du public (par exemple MyThreadSafeDataStructure peuvent avoir une en tant que composant Mutex accessible au public).

Autres conseils

Je pense que la réponse courte est que la conception OO « bons » sont robustes face au changement, au moins une rupture de code pour toutes les exigences changent. Si l'on considère toutes les règles habituelles, ils tendent tous à la même conclusion.

La difficulté est que vous ne pouvez pas évaluer la « bonté » de la conception sans contexte; il est, je crois, un théorème que pour tout modularisation, il existe une modification des exigences qui maximiseront la rupture, ce qui provoque toutes les classes à toucher dans chaque méthode.

Si vous voulez être rigoureux à ce sujet, vous pouvez développer une collection de « cas de changement » et les commander afin de probabilité, de sorte que vous réduisez au minimum la rupture pour les changements les plus probables.

Sur la plupart des cas, cependant, une certaine intuition bien développée aide beaucoup: des choses spécifiques spécifiques à l'appareil ou la plate-forme ont tendance à changer, les règles métier et processus d'affaires ont tendance à changer, alors que les mises en œuvre de, disons, l'arithmétique, changent très rarement . (Non, comme vous pouvez l'imaginer, jamais. Considérons, par exemple, un système d'affaires qui peuvent ou peuvent ne pas être en mesure d'utiliser l'arithmétique BCD pris en charge la plate-forme.)

scroll top