Re[21]: хихи
От: Sinclair Россия https://github.com/evilguest/
Дата: 01.08.12 15:23
Оценка: 16 (1)
Здравствуйте, SV., Вы писали:
SV.>Это счет-то не соответствует результату операций по проводкам?
Бухгалтер не мыслит о счёте, как о самостоятельной сущности с жизенным циклом, которой можно посылать сообщения и получать результат.

SV.>У нее есть одно большое преимущество — она интуитивно-понятна. Поэтому так строят реальные системы типа ShP OM. А других преимуществ — да, нет.

Интуитивно понятна она ровно до тех пор, пока не начинаются реальные вопросы типа тех, что я задал.

SV.>Есть и недостаток — ОМ чувствительна к дизайну. Кривые руки ее погубят. Поэтому, ШП ОМ — редкая гадость (когда я последний раз смотрел на их CAML, плакал горючими слезами — пакетные запросы адекватно представлены не были, пришлось плюнуть и переписать все на SQL).

Отож.

S>>Смотрите, в чём затык: для вывода баланса на экран придётся построить новый счёт и попросить данные у него:

S>>
S>>BalanceLabel.Text = (new Account("03")).CalcCurrentBalance().ToString();
S>>


SV.>Нет, поскольку где ж вы возьмете идентификатор? Вообще, идентификатор сугубо служебен и снаружи вам не виден.

Как это "не виден"? Да он в плане счетов написан крупным шрифтом. То, что вы дали счёту какой-то внутренний служебный идентификатор — ваше личное решение; нужды в нём никакой нет.

SV.>Искать вы будете по внешним атрибутам счета, может быть, даже, в соответствии с правами доступа. Создаваться экземпляр будет фабрикой, внешний вид которой зависит от архитектуры. Разумеется, этот поисковый объект не будет исключительно фабрикой, и я никогда не соглашусь, что это нарушение SRP.

А придётся.
S>>А что такое "Current"? Наверное, есть операция CalcBalanceForDate(Date targetDate), и есть важный инвариант CalcCurrentBalance() == CalcBalanceForDate(new Date()).

SV.>Да, хотел дописать почти теми же словами, но решил, что и так понятно. Это некий шорткат, который можно реализовать по-разному (хоть бы и дефолтным значением параметра).

Это — плохой способ. Вы прячете ту функциональность, которая должна быть на виду.
SV.>Зрение бывает у дизайнера, а не у дизайна. Как и точка, откуда дизайнер зрит. Это так, к слову.
Ну давайте не будем
SV.>С какой точки зрите вы, я не знаю. Мой поинт в том, чтобы сложность разложить по полочкам. Поставьте себя на место гуёвого программиста, которому дела нет до идентификаторов и базы. Зато у него на входе есть счет, который сводит дебит с кредитом по запросу. И полученный таким образом результат можно запихать в форму и отдать операционисту.
Я не понимаю вашу терминологию. Вы придумали какое-то решение и хотите общаться только в рамках него?
Ну, а я вижу это совершенно по-другому. Конечно же у гуёвого программиста на входе есть исключительно идентификатор. Потому, что ему приехал запрос .../ShowAccountTransactionHistory.aspx?Acc=78.01
И теперь ему из этого номера счёта нужно получить всю нужную по ТЗ информацию. Либо ему надо заниматься порождением нафиг ненужной объектной модели, либо можно скормить этот параметр в метод хелперного объекта AccountingService и получить всё, что нужно.

SV.>Это зависит от точки зрения дизайнера на responsibility. Если у вас есть дополнительные требования к работе с БД (допустим, поддержка в качестве БД чего угодно, в том числе NoSQL) — ну, введем посредника, который будет делать выборки и другие реляционные операции по чему ему скажут (а Account ему скажет — по проводкам). Если нет — ради бога, прячьте сиквел в реализацию, получите быстрособранную систему, которая жестко завяжется на структуру таблиц. И то, и другое будет понятной объектной моделью, но с разными достоинствами и недостатками в других областях.

Это будет нарушением SRP.

S>>Если оставить в нём работу с базой, тогда непонятно, почему в нём — почему нам не иметь класс DbManager с методами GetTransfers(Predicate where), кроме которого, в общем-то, ничего и не нужно?

S>>Если оставить в нём работу с расчётом баланса, а проводки отдавать снаружи, то получается, что мы завели целый отдельный класс для примитивов типа
S>>
S>>Decimal static CalcBalanceForDate(Date date, allTransfers) 
S>> return (from t in allTransfers where t.Date <= date select t.Amount).Sum();
S>>

S>>Зачем всё это делать, совершенно непонятно.

SV.>Как же это непонятно? Допустим, мы завязались на структуру таблиц. Тогда, во-первых, а где это хранить? В каком месте? "Там, где архитектурно правильно" — это общие слова. Где конкретно? Помните про гуёвого программиста, которому нужно состояние счета, атрибуты, балансы и больше ничего? Его вы озаботите знанием этого запроса, в том или ином виде?

Как где? Внутри сервиса, который знает, как доставать проводки. Делов-то. У нас будет сервис, умеющий из проводок собирать различные отчёты, и будет сервис, умеющий доставать проводки из базы.
Если меняются правила построения отчётов — меняем ровно в одном месте ровно один сервис, и только его нужно тестировать. Если меняется структура таблиц — обратно меняем ровно один сервис и только его нужно тестировать.

SV.>Заглавное сообщение прочитайте еще раз. Всё, что нужно, прекрасно получается безо всяких объектов. Хоть на ассемблере. А вот если подумать о людях, которым с этим кодом работать...

То получится так называемая Anemic Model, в которой логика написана так, что её легко понять и отладить, без попыток сделать "чёрными ящиками" сущности, лишённые тонкостей внутренней структуры.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.