Дизайн класса Python - Разделение больших классов на несколько для группирования функций - PullRequest
15 голосов
/ 24 марта 2010

ОК. У меня есть 2 действительно больших класса> 1 тыс. Строк, которые я сейчас разделил на несколько. Затем они объединяются с использованием множественного наследования. Теперь мне интересно, есть ли какой-нибудь более чистый / лучший, более питонский способ сделать это. Полное их выделение приведет к бесконечному количеству self.otherself.do_something вызовов, что, я не думаю, так и должно быть.

Чтобы прояснить ситуацию, вот как это выглядит в настоящее время:

from gui_events import GUIEvents # event handlers
from gui_helpers import GUIHelpers # helper methods that don't directly modify the GUI

# GUI.py
class GUI(gtk.Window, GUIEvents, GUIHelpers):
    # general stuff here stuff here

Одной из проблем, которая является следствием этого, является жалоба Pylint, дающая мне триллионы предупреждений "init not named" / "undefined attribute" / ", доступный до определения".

EDIT:
Возможно, вы захотите взглянуть на код, чтобы составить представление о том, что на самом деле представляет собой все это.
http://github.com/BonsaiDen/Atarashii/tree/next/atarashii/usr/share/pyshared/atarashii/

Обратите внимание, я действительно пытаюсь сделать все, чтобы эта вещь была максимально СУХОЙ, я использую Pylint для обнаружения дублирования кода, единственное, на что он жалуется, это импорт.

Ответы [ 5 ]

7 голосов
/ 24 марта 2010

Если вы хотите использовать множественное наследование, чтобы объединить все в один большой класс (это может иметь смысл), то вы можете реорганизовать каждый из родительских классов, чтобы каждый метод и свойство были либо приватными (начинаются с '__ ') или имеет короткий префикс из 2-3 символов, уникальный для этого класса. Например, все методы и свойства в вашем классе GUIEvents могут начинаться с ge_, все в GUIHelpers может начинаться с gh_. Делая это, вы добьетесь некоторой ясности использования отдельных экземпляров подкласса (self.ge.doSomething() против self.ge_doSomething()) и избежите конфликтующих имен членов, что является основным риском при объединении таких больших классов в один .

5 голосов
/ 24 марта 2010

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

Старайтесь избегать множественного наследования в максимально возможной степени; это редко полезно и всегда несколько сбивает с толку. Вместо этого обратите внимание на использование функциональной композиции (отношения "HAS-A") для придания богатых атрибутов вашим объектам из других объектов.

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

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

1 голос
/ 24 марта 2010

Я думаю, что это более общая проблема OO-проектирования, чем проблема Python. Python в значительной степени дает вам все классические инструменты ООП, удобно упакованные. Вам придется описать проблему более подробно (например, что содержат классы GUIEvents и GUIHelpers?)

Один аспект, специфичный для Python, является следующим: Python поддерживает несколько парадигм программирования, и зачастую лучшим решением является не ООП. Это может иметь место здесь. Но опять же, вам придется добавить более подробную информацию, чтобы получить значимый ответ.

0 голосов
/ 06 февраля 2018

Одна возможность - назначить импортированные функции атрибутам класса:

В файле a_part_1.py:

def add(self, n):
    self.n += n
def __init__(self, n):
    self.n = n

И в файле основного класса:

import a_part_1 

class A:
    __init__ = a_part_1.__init__
    add = a_part_1.add

Или, если вы не хотите обновлять основной файл при добавлении новых методов:

class A: pass

import a_part_1 
for k, v in a_part_1.__dict__.items():
    if callable(v):
        setattr(A,k,v)
0 голосов
/ 24 марта 2010

Ваш код может быть существенно улучшен за счет реализации модели Model-View-Controller. В зависимости от того, как настроены ваш графический интерфейс и инструмент, вы также можете извлечь выгоду из «виджирования» частей вашего графического интерфейса, так что вместо одного гигантского Model-View-Controller у вас есть основной Model-View-Controller, который управляет группой меньшие Model-View-Controllers, каждый для отдельных частей вашего GUI. Это позволит вам разбить ваш инструмент и графический интерфейс на множество классов, и вы сможете повторно использовать его части, сократив общий объем кода, который вам нужно поддерживать.

Хотя python поддерживает несколько парадигм программирования, для инструментов с графическим интерфейсом лучшим решением почти всегда будет объектно-ориентированный дизайн.

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