Злоупотребление миксином - зло, и каковы альтернативные решения? - PullRequest
7 голосов
/ 26 сентября 2010

Иногда использование mixin с множественным наследованием может помочь нам улучшить возможность повторного использования нашего кода.

Например, следующий дизайн

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

class User(FollowableMixin):
    ...

может быть лучше повторно использован, чемпросто добавив get_followers к User:

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

, потому что позже мы можем рассмотреть возможность поддержки других последующих объектов, которые являются потенциальными клиентами get_followers:

class BookStore(FollowableMixin):
    ...

Однако, если этошаблон перегружен, код может быть слишком сложным.

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

Со всеми этими смешанными классами, внедряющими свойства и методы в ваш класс, становится очень трудно понять ваш код.Например, вы не знаете, откуда вызывается метод, и этот метод может, в свою очередь, включать вызов метода в другом миксине ...

Что я должен сделать, чтобы упростить эту программу?

Ответы [ 4 ]

6 голосов
/ 26 сентября 2010

Иногда это может помочь собрать вместе связанные функции в одном классе, если они часто используются вместе.

class FooMixin(FollowableMixin, RunnableMixin):
    pass

Тогда, когда вы его используете, у вас будет только один или два прямых базовых класса вместо многих.

Очевидно, вы должны делать это только в том случае, если это имеет смысл - им можно злоупотреблять. Не зная больше о вашем конкретном примере, трудно понять, имеет ли смысл делать это или нет в вашем случае.

6 голосов
/ 26 сентября 2010

Если ваш класс User действительно имеет столько подходящих характеристик, то у вас может быть просто сложное приложение.Наличие пяти миксов лучше, чем копирование пяти функций из других мест.

Некоторые возможности для упрощения:

  1. Ваш класс User пытается сделать слишком много.Разбейте его на более мелкие классы.

  2. Объедините некоторые из ваших миксинов.Например, вы можете обнаружить, что существует пять классов, каждый из которых является Followable, Runnable и Flyable.Создает промежуточный класс FollowRunFly, производный от этих трех миксов, а затем использует FollowRunFly в ваших пяти классах.

  3. Возможно, вам не нужно так тонко нарезать миксины.Сделайте один большой миксин и используйте его в своих классах, и пусть код определит во время выполнения, может ли объект летать или следовать за ним.

4 голосов
/ 26 сентября 2010

Используйте адаптеры вместо миксинов.Так что в вашем случае у вас был бы интерфейс IFollowable и адаптеры от BookStore или User до IFollowable.

См. http://ginstrom.com/scribbles/2009/03/27/the-adapter-pattern-in-python/ для одного описания адаптеров в Python и, в частности, комментариев от Мартин Фаассен об использовании фабрики интерфейсы и grokcore.component.

3 голосов
/ 26 сентября 2010

С помощью бумаги и карандаша запишите конкретные классы, которые фактически создаются (например, User и BookStore). Перечислите все методы, которые вы хотите, чтобы эти классы выполняли. Только увидев этот список, вы сможете рационально решить, какая иерархия классов лучше всего подходит для вашей ситуации. Медлительность написания от руки может заставить вас задуматься об отношениях между вашими объектами по-новому. Попробуйте подробно объяснить свои занятия воображаемому другу (или нам!), Который умен, но ничего не знает о вашей проблеме. Медлительность артикуляции деталей может привести к пониманию.

Миксины могут дать вам много общего, чтобы позволить вашему проекту расти, но вы часто вынуждены идти на компромисс между общностью (которая сложна) и практичностью (которая часто проще). Четыре миксина допускают 2 ** 4 возможных конкретных класса. Если на практике у вас гораздо меньше конкретных классов, то миксины могут быть не подходящим инструментом для работы.

Если вы чувствуете, что общность ошеломляет вас, я думаю, было бы разумно отказаться от общности, заморозить функции и код наиболее простым способом, который приспособил бы эти функции. Затем, когда у вас есть работающий продукт, вы можете подумать о добавлении новых функций и рефакторинг, если это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...