У вас есть четко определенные, узконаправленные классы ... как мне сделать что-нибудь в моей программе? - PullRequest
1 голос
/ 21 июля 2010

Я пишу оценщик покерных рук как мой первый программный проект. Я прошел через три класса, каждый из которых хорошо выполняет свою узко определенную задачу:

HandRange = строковый объект (например, "AA"). getHands () возвращает список кортежей для каждой конкретной руки в строке:

[(Ad,Ac),(Ad,Ah),(Ad,As),(Ac,Ah),(Ac,As),(Ah,As)]

Перевод = словарь, который отображает список возврата из getHands в значения, которые полезны для данного оценщика (да, это, вероятно, может быть реорганизовано в другой класс).

{'As':52, 'Ad':51, ...}

Evaluator = берет список из HandRange (в переводе Translator), перечисляет все возможные комбинации рук и предоставляет% выигрыша для каждого.

Мой вопрос: как должен выглядеть мой «доменный» класс для использования всех этих классов, учитывая, что я могу захотеть подключиться к нему через интерфейс оболочки или графический интерфейс? Прямо сейчас это выглядит как процесс сборочной линии:

user_input = HandRange()
x = Translation.translateList(user_input)
y = Evaluator.getEquities(x)

Это пахнет смешно, потому что мне кажется, что это процедурно, когда я должен использовать ОО.

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

Спасибо

Mike

Ответы [ 2 ]

3 голосов
/ 21 июля 2010

Не делайте фетиш объектной ориентации - в конце концов, Python поддерживает несколько парадигм!Думайте о ваших пользовательских типах, классах AKA, как о строительных блоках, которые постепенно дают вам «язык», который ближе к вашему домену, чем к примитивам языка / библиотеки общего назначения.

В какой-то момент вам захочетсякодировать «глаголы» (действия), которые используют ваши строительные блоки, чтобы выполнить что-то (по команде из любого интерфейса, который вы предоставите - командная строка, RPC, веб, GUI, ...) - иэто могут быть функции уровня модуля, а также методы внутри некоторого охватывающего класса.Вам наверняка понадобится класс, если вам нужно несколько экземпляров, и, скорее всего, также, если действия включают обновление «состояния» (переменные экземпляра класса намного лучше глобальных) или если в игру вступают наследование и / или полиморфизм;но нет никакой априорной причины предпочитать классы функциям в противном случае.

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

1 голос
/ 21 июля 2010

Вы можете создать класс покера, который связывает все это вместе и инициализирует все эти вещи методом __init__():

class Poker(object):
    def __init__(self, user_input=HandRange()):
        self.user_input = user_input
        self.translation = Translation.translateList(user_input)
        self.evaluator = Evaluator.getEquities(x)

    # and so on...

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