Объектно-ориентированный дизайн? - PullRequest
6 голосов
/ 22 октября 2009

Я пытаюсь выучить объектно-ориентированное программирование, но мне трудно преодолевать мой опыт структурированного программирования (в основном C, но многие другие со временем). Я думал, что напишу простую программу проверки регистра в качестве упражнения. Я довольно быстро соединил что-то (python - отличный язык), с моими данными в некоторых глобальных переменных и множеством функций. Я не могу понять, можно ли улучшить этот дизайн, создав ряд классов для инкапсуляции некоторых данных и функций и, если да, то как изменить дизайн.

Мои данные - это в основном список счетов ['проверка', 'сохранение', 'Amex'], список категорий ['еда', 'жилье', 'транспорт'] и списки диктов, которые представляют транзакции [ {'date': xyz, 'cat': xyz, 'amount': xyz, 'description': xzy]. У каждой учетной записи есть связанный список диктовок.

Затем у меня есть функции на уровне аккаунта (create-acct (), display-all-accts () и т. Д.) И на уровне транзакции (display-records-in-account (), enter-a-транзакция ( ), редактировать транзакцию (), отображать записи между датами () и т. д.)

Пользователь видит список учетных записей, затем может выбрать учетную запись и просмотреть базовые транзакции с возможностью добавления, удаления, изменения и т. Д. Учетных записей и транзакций.

В настоящее время я реализую все в одном большом классе, чтобы я мог использовать всюду self.variable, а не явные глобальные переменные.

Короче говоря, я пытаюсь выяснить, была бы полезна реорганизация этого в некоторые классы и, если да, то как спроектировать эти классы. Я прочитал несколько книг о книгах (последний раз - объектно-ориентированный мыслительный процесс). Мне нравится думать, что мой существующий дизайн читается и не повторяется.

Любые предложения будут оценены.

Ответы [ 5 ]

7 голосов
/ 22 октября 2009

Вам не нужно выбрасывать структурированное программирование для объектно-ориентированного программирования. Код все еще структурирован, он просто принадлежит объектам, а не отделен от них.

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

В ОО данные и код неразрывно связаны - объект содержит как данные, так и код для работы с этими данными (хотя технически код (а иногда и некоторые данные) принадлежит классу, а не отдельному объекту). Любой клиентский код, который хочет использовать эти объекты, должен делать это только с помощью кода внутри этого объекта. Это предотвращает проблему несоответствия кода и данных.

Для системы бухгалтерского учета я подхожу к ней следующим образом:

  1. Низкоуровневые объекты - это счета и категории (фактически, в бухгалтерском учете нет разницы между ними, это ложное разделение, только усугубленное Quicken и др. Для отделения статей баланса от прибылей и убытков - я буду называть их счетами только). Объект счета состоит из (например) кода счета, имени и начального баланса, хотя в системах учета, над которыми я работал, начальный баланс всегда равен нулю - я всегда использовал «начальную» транзакцию для первоначальной установки балансов .
  2. Транзакции - это сбалансированный объект, который состоит из группы счетов / категорий со связанными движениями (изменения в долларовом выражении). Под балансом я подразумеваю, что они должны равняться нулю (это суть учета двойной записи). Это означает, что это дата, описание и массив или вектор элементов, каждый из которых содержит код счета и значение.
  3. Общий «объект» учета (бухгалтерская книга) - это просто список всех счетов и транзакций.

Имейте в виду, что это «бэкэнд» системы (модель данных). Мы надеемся, что у вас будут отдельные классы для просмотра данных (представления), которые позволят вам легко изменять их в зависимости от предпочтений пользователя. Например, вам может потребоваться вся бухгалтерская книга, только баланс или только отчет о прибылях и убытках. Или вы можете захотеть разные диапазоны дат.

Я бы хотел подчеркнуть одну вещь, чтобы создать хорошую систему учета. Вы do должны думать как бухгалтер. Под этим я подразумеваю потерю искусственной разницы между «счетами» и «категориями», поскольку это сделает вашу систему намного чище (вам нужно иметь возможность совершать транзакции между двумя счетами класса активов (например, банковским переводом), и это выиграло не работает, если каждая транзакция нуждается в «категории». Модель данных должна отражать данные, а не представление.

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

5 голосов
/ 22 октября 2009

Не прямой ответ на ваш вопрос, но Head-O-Reilly объектно-ориентированного анализа и проектирования - отличное место для старта.

Вслед за Head First Design Patterns

3 голосов
/ 22 октября 2009

«Мои данные - это в основном список учетных записей»

Учетная запись является классом.

"Дикты, представляющие транзакции"

Транзакция представляется классом. Вы случайно решили представить это как диктат.

Это ваш первый проход в ОО-дизайне. Сосредоточьтесь на обязанностях и сотрудниках.

У вас есть как минимум два класса объектов.

1 голос
/ 22 октября 2009

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

Вот несколько вопросов для ответа, которые могут указать вам на принципы проектирования:

  • Собираются ли другие использовать этот API? Они могут сломать это? ( информация скрывается )
  • мне нужно развернуть это на многих машинах? ( управление состоянием, управление жизненным циклом )
  • мне нужно взаимодействовать с другими системами, средами исполнения, языками? ( абстракция и стандарты )
  • каковы мои ограничения производительности? ( управление состоянием, управление жизненным циклом )
  • в какой среде безопасности находится этот компонент? ( абстракция, сокрытие информации, совместимость )
  • как бы я сконструировал свои объекты, если бы я их использовал? ( конфигурация, инверсия управления, развязка объекта, скрытие деталей реализации )

Это не прямые ответы на ваш вопрос, но они могут поставить вас в правильное настроение, чтобы ответить на него самостоятельно. :)

0 голосов
/ 22 октября 2009

Вместо использования dicts для представления ваших транзакций лучшим контейнером будет именованный кортеж из модуля коллекций. Именованный кортеж - это подкласс кортежа, который позволяет ссылаться на его элементы по имени, а также по номеру индекса.

Поскольку в ваших списках журналов могут быть тысячи транзакций, стоит поддерживать эти элементы как можно меньшими и легкими, чтобы обработка, сортировка, поиск и т. Д. Были максимально быстрыми и отзывчивыми. Диктовка - это довольно тяжелый объект по сравнению с именованным кортежем, который занимает не больше памяти, чем обычный кортеж. Именованный кортеж также имеет дополнительное преимущество, заключающееся в том, что он сохраняет свои элементы в порядке, в отличие от dict.

>>> import sys
>>> from collections import namedtuple
>>> sys.getsizeof((1,2,3,4,5,6,7,8))
60
>>> ntc = namedtuple('ntc', 'one two three four five six seven eight')
>>> xnt = ntc(1,2,3,4,5,6,7,8)
>>> sys.getsizeof(xnt)
60
>>> xdic = dict(one=1, two=2, three=3, four=4, five=5, six=6, seven=7, eight=8)
>>> sys.getsizeof(xdic)
524

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

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