7 votes

La surutilisation des mixins est un mal et quelles sont les solutions alternatives ?

Parfois, en utilisant mixin avec un héritage multiple peut nous aider à améliorer la réutilisabilité de notre code.

Par exemple, le modèle suivant

class FollowableMixin(object):
    def get_followers(self):
        ...
    ...

class User(FollowableMixin):
    ...

peut être mieux réutilisé que de simplement ajouter get_followers a User :

class User(object):
    def get_followers(self):
        ...
    ...

parce que plus tard, nous pourrions envisager de soutenir d'autres entités à suivre qui sont des clients potentiels de get_followers :

class BookStore(FollowableMixin):
    ...

Toutefois, si ce modèle est trop utilisé, le code peut devenir trop complexe.

class User(FollowableMixin, RunnableMixin, FlyableMixin, WhatMixin ...):
    ...

Avec toutes ces classes mixines injectant des propriétés et des méthodes à votre classe, il devient très difficile de comprendre votre code. Par exemple, vous ne savez pas d'où vient la méthode que vous appelez, et cette méthode peut à son tour inclure une invocation d'une méthode dans une autre mixine ...

Que dois-je faire pour simplifier ce programme ?

6voto

Mark Byers Points 318575

Parfois, il peut être utile de rassembler des caractéristiques apparentées dans une seule classe si elles sont souvent utilisées ensemble.

class FooMixin(FollowableMixin, RunnableMixin):
    pass

Ainsi, lorsque vous l'utilisez, vous n'avez qu'une ou deux classes de base directes au lieu de plusieurs.

Évidemment, vous ne devez le faire que si cela a un sens - il peut y avoir des abus. Sans en savoir plus sur votre exemple spécifique, il est difficile de savoir si cela a du sens ou non dans votre cas.

6voto

Ned Batchelder Points 128913

Si votre classe d'utilisateurs possède vraiment autant de caractéristiques appropriées, il se peut que vous ayez simplement une application complexe. Avoir cinq mixins est mieux que d'avoir cinq fonctions copiées d'autres endroits.

Quelques possibilités de simplification :

  1. Votre classe d'utilisateur essaie d'en faire trop. Divisez-la en plusieurs classes plus petites.

  2. Agréger certains de vos mixins. Par exemple, tu peux trouver qu'il y a cinq classes dont chacune est Followable, Runnable et Flyable. Créez une classe intermédiaire FollowRunFly qui dérive de ces trois mixins, puis utilisez FollowRunFly dans vos cinq classes.

  3. Vous n'avez peut-être pas besoin de découper vos mixines aussi finement. Faites un grand mixin, et utilisez-le sur vos classes, et laissez le code déterminer au moment de l'exécution si l'objet peut voler ou être suivi.

4voto

Duncan Points 25356

Utilisez des adaptateurs au lieu de mixins. Ainsi, dans votre cas, vous auriez une interface IFollowable et des adaptateurs de BookStore ou User à IFollowable.

Voir http://ginstrom.com/scribbles/2009/03/27/the-adapter-pattern-in-python/ pour une description des adaptateurs en Python et en particulier les commentaires de Martijn Faassen sur l'utilisation des fabriques et des interfaces et grokcore.component .

4voto

unutbu Points 222216

Avec un papier et un crayon, notez les classes concrètes qui sont effectivement instanciées (par exemple, User et BookStore). Énumérez toutes les méthodes que vous voulez que ces classes exécutent. Ce n'est qu'en voyant cette liste que vous pourrez décider rationnellement de la hiérarchie de classes la mieux adaptée à votre situation. La lenteur de l'écriture à la main peut vous obliger à réfléchir aux relations entre vos objets d'une manière nouvelle. Essayez d'expliquer vos classes en détail à un ami imaginaire (ou à nous !) qui est intelligent mais qui ne connaît rien à votre problème. La lenteur de l'articulation des détails peut vous permettre de mieux comprendre.

Les mixins peuvent vous donner beaucoup de généralité pour permettre à votre projet de se développer, mais vous êtes souvent obligé de faire un compromis entre la généralité (qui est complexe) et l'aspect pratique (qui est souvent plus simple). Quatre mixins permettent de créer 2**4 classes concrètes possibles. Si, dans la pratique, vous avez beaucoup moins de classes concrètes, alors les mixins ne sont peut-être pas l'outil idéal pour ce travail.

Si vous avez l'impression que la généralité vous dépasse, je pense qu'il serait sage d'abandonner la généralité, de geler les fonctionnalités et de coder de la manière la plus simple possible en tenant compte de ces fonctionnalités. Ensuite, lorsque vous aurez un produit fonctionnel, vous pourrez réfléchir à l'ajout de nouvelles fonctionnalités, et refactoriser si nécessaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X