Responsabilité unique principe: faire toutes les méthodes publiques d'une classe doivent utiliser toutes les dépendances de classe?

StackOverflow https://stackoverflow.com/questions/1118463

Question

Dire que j'ai une classe qui ressemble à ce qui suit:

internal class SomeClass
{
    IDependency _someDependency;

    ...


    internal string SomeFunctionality_MakesUseofIDependency()
    {
    ...
    }
}

Et je veux ajouter une fonctionnalité qui est liée, mais utilise une dépendance différente pour atteindre son objectif . Peut-être quelque chose comme ce qui suit:

internal class SomeClass
{
    IDependency _someDependency;

    IDependency2 _someDependency2;

    ...


    internal string SomeFunctionality_MakesUseofIDependency()
    {
    ...
    }

    internal string OtherFunctionality_MakesUseOfIDependency2()
    {
    ...
    }
}

Quand j'écris des tests unitaires pour cette nouvelle fonctionnalité (ou mettre à jour les tests unitaires que j'ai pour les fonctionnalités existantes), je me trouve la création d'une nouvelle instance de SomeClass (SUT) tout en passant nulle pour la dépendance que je don « t besoin pour le bit particulier de fonctionnalité que je suis à la recherche à tester.

Cela semble être une mauvaise odeur pour moi, mais la raison pour laquelle je me retrouve dans cette voie est parce que je me suis retrouvé la création de nouvelles classes pour chaque morceau de nouvelles fonctionnalités que je présentais. Cela semblait être une mauvaise chose aussi bien et donc je commencé à essayer de fonctionnalités similaires de groupe ensemble.

Ma question: doit toutes les dépendances d'une classe être consommée par toutes ses fonctionnalités à savoir si différents bits de fonctionnalité utilisent des dépendances différentes, il est un indice que ceux-ci devraient probablement vivre dans des classes séparées

Était-ce utile?

La solution

Est-ce que SomeClass maintenir un état interne, ou est-il juste « assemble » divers morceaux de fonctionnalité? Pouvez-vous réécrire cette façon:

internal class SomeClass
{
    ...


    internal string SomeFunctionality(IDependency _someDependency)
    {
    ...
    }

    internal string OtherFunctionality(IDependency2 _someDependency2)
    {
    ...
    }
}

Dans ce cas, vous ne pouvez pas briser SRP si SomeFunctionality et OtherFunctionality sont en quelque sorte (fonctionnellement) liées qui ne sont pas apparents à l'aide des espaces réservés.

Et vous avez la valeur ajoutée de pouvoir sélectionner la dépendance à utiliser du client, et non pas au moment de la création / DI. Peut-être que certains tests définissant les cas d'utilisation de ces méthodes contribueraient à clarifier la situation. Si vous pouvez écrire un test significatif où les deux méthodes sont appelées même objet, vous ne cassez pas SRP

En ce qui concerne le modèle de façade, je l'ai vu trop de fois gone wild à l'aimer, vous savez, quand vous vous retrouvez avec une classe 50+ méthodes ... La question est la suivante: Pourquoi avez-vous besoin? Pour des raisons d'efficacité à La oldtimer EJB?

Autres conseils

Quand chaque méthode d'instance touche chaque variable d'instance alors la classe est au maximum de cohésion. En l'absence de méthode d'instance partage une variable d'instance avec une autre, la classe est peu cohérente. Il est vrai que nous aimons la cohésion élevée, il est également vrai que la règle 80-20 applique. Obtenir cette dernière petite augmentation de la cohésion peut nécessiter un effort Mamoth.

En général, si vous avez des méthodes qui n'utilisent pas certaines variables, il est une odeur. Mais une petite odeur ne suffit pas à factoriser complètement la classe. Il est quelque chose à se préoccuper, et de garder un oeil, mais je ne recommande pas une action immédiate.

Je méthode généralement dans des catégories si elles utilisent un morceau partagé de l'Etat qui peut être encapsulé dans la classe. Ayant des dépendances qui ne sont pas utilisés par toutes les méthodes dans une classe peut être une odeur de code, mais pas très forte. Je habituellement seulement séparer les méthodes des classes quand la classe est trop grande, la classe a trop de dépendances ou les méthodes ne pas l'état partagé.

  

Ma question: doit toutes les dépendances d'une classe être consommée par toutes ses fonctionnalités à savoir si différents bits de fonctionnalité utilisent des dépendances différentes, il est un indice que ceux-ci devraient probablement vivre dans des classes séparées

Il est un indice, ce qui indique que votre classe peut être un peu incohérent ( « faire plus d'une chose »), mais comme vous dites, si vous prenez trop loin, vous vous retrouvez avec une nouvelle classe pour chaque pièce de nouvelles fonctionnalités. Donc, vous voulez introduire des objets de façade pour les rassembler à nouveau (il semble qu'un objet de façade est exactement le contraire de cette règle de conception particulière).

Vous devez trouver un bon équilibre qui fonctionne pour vous (et le reste de votre équipe).

On dirait de me surcharger. Vous essayez de faire quelque chose et il y a deux façons de le faire, d'une façon ou d'une autre. Au niveau de SomeClass, j'ai une dépendance à faire le travail, ont alors que le soutien classe dépendante unique des deux (ou plus) les moyens de faire la même chose, très probablement avec des paramètres d'entrée mutuellement exclusifs. En d'autres termes, j'ai le même code que vous avez pour SomeClass, mais le définir comme SomeWork au lieu et EXCLUT tout autre code sans rapport.

HTH

Une façade est utilisée lorsque vous souhaitez masquer la complexité (comme une interface à un système existant) ou que vous souhaitez consolider la fonctionnalité tout en étant rétrocompatible du point de vue de l'interface.

La clé dans votre cas est pourquoi vous avez deux méthodes différentes dans la même classe. Est-ce l'intention d'avoir une classe qui regroupe des types similaires de comportement, même si elle est mise en œuvre par le code sans rapport, comme dans l'agrégation. Ou, vous essayez de soutenir le même comportement, mais ont des implémentations alternatives en fonction des spécificités, ce qui serait un indice pour un type de solution héritage / surcharge.

Le problème sera de savoir si cette classe va continuer à croître et dans quelle direction. Deux méthodes ne seront pas faire une différence, mais si cela se répète avec plus de 3, vous devrez décider si vous voulez déclarer comme une façade / adaptateur ou que vous avez besoin pour créer des classes d'enfants pour les variations.

Vos soupçons sont corrects, mais l'odeur est juste le fétu de fumée d'un tison. Vous devez garder un oeil sur lui au cas où il flambe et vous devez prendre une décision que la façon dont vous voulez éteindre le feu avant qu'il ne brûle hors de contrôle.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top