Я читаю книжку Фаулера. Я не использую в своей работе .NET, и поэтому плохо чувствую такую фичу как DataSet; между тем, все объяснения паттерна "Модуль таблицы" основаны на нем. Я приведу конкретную, весьмя простую задачу, и хотел бы обсудить, какие могут быть решения этой задачи использующие модуль таблицы.
Пусть имеется база данных с несколькими таблиццами. Есть SQL запрос, соединяющий эти таблицы и возвращающий некую таблицу T. Есть стандартный способ представления табличных данных (RecordSet) и есть технология отображения представленных таким образом данных.
В одной из таблиц имеется поле F (попадающее в T) которое при отображении следует форматировать каким-то определенным образом.
Наша система должна уметь выводить таблицы базы данных, а также отчет, получаемый из T путем каких-то сложных вычислений C, которые (для простоты) не затрагивают поле F.
Можно завести для каждой таблицы базы модуль, но кто в таком случае будет проводить вычисления C?
Можно завести модуль и для таблицы T. Но в таком случае форматированием поля F будет заниматься как модуль T, так и модуль таблицы которая содержит F. Необходимость исключить дублирование кода приведет к появлению каких-то дополнительных классов (модуль поля F, грубо говоря), что явно не укладывается в простую схему, предлагаемую Фаулером.
Пример простой, и понятно что в этом случае ничего страшного не случится, все это можно так или иначе сделать.
Однако Фаулер назвает это типовым решением, а я как мне кажется привел очень простую и очень типовую задачу.
Так что либо я чего то-туплю/недопонял (что вероятно), либо модуль таблицы — не типовое решение.
Прошу прощения за длинный нудный пост.
Здравствуйте, mife, Вы писали:
M>Я читаю книжку Фаулера. Я не использую в своей работе .NET, и поэтому плохо чувствую такую фичу как DataSet; между тем, все объяснения паттерна "Модуль таблицы" основаны на нем. Я приведу конкретную, весьмя простую задачу, и хотел бы обсудить, какие могут быть решения этой задачи использующие модуль таблицы.
Модуль таблицы в простейшем случае — просто массив данных, к которому можно обращаться через какие-либо итераторы, где каждая итерация возвращает строку (а строка уже может собой представлять либо объект наподобие активной записи, либо просто набор значений в виде еще одного массива).
M>Можно завести для каждой таблицы базы модуль, но кто в таком случае будет проводить вычисления C?
За это отвечает модуль бизнес-логики — он может быть промежуточным между модулем таблицы и представлением (паттерн Преобразователь данных).
M>Пример простой, и понятно что в этом случае ничего страшного не случится, все это можно так или иначе сделать. M>Однако Фаулер назвает это типовым решением, а я как мне кажется привел очень простую и очень типовую задачу. M>Так что либо я чего то-туплю/недопонял (что вероятно), либо модуль таблицы — не типовое решение. M>
Модуль таблицы — лишь часть системы. Рассмотрите систему в контексте MVC:
1) Model — модуль таблицы + преобразователь данных;
2) View — осуществляет представление данных, отвечает за все форматирование;
3) Controller — осуществляет взаимодействие между моделью и представлением.
Здравствуйте, Nuald, Вы писали:
N>Модуль таблицы в простейшем случае — просто массив данных, к которому можно обращаться через какие-либо итераторы, где каждая итерация возвращает строку (а строка уже может собой представлять либо объект наподобие активной записи, либо просто набор значений в виде еще одного массива).
То что Вы написали — это RecordSet (в терминологии Фаулера), а не модуль таблицы
M>>Можно завести для каждой таблицы базы модуль, но кто в таком случае будет проводить вычисления C?
N>За это отвечает модуль бизнес-логики — он может быть промежуточным между модулем таблицы и представлением (паттерн Преобразователь данных).
Нет уж, извините, опять же, по Фаулеру, модуль таблицы как раз и реализует бизнес-логику.
По моему Вы путаете то что Фаулер называет шлюзом таблицы и модулем таблицы. Это (в идеале) разные вещи. Т.к. пример простой, можно считать что у нас — идеальный случай.
N>Модуль таблицы — лишь часть системы. Рассмотрите систему в контексте MVC: N>1) Model — модуль таблицы + преобразователь данных; N>2) View — осуществляет представление данных, отвечает за все форматирование; N>3) Controller — осуществляет взаимодействие между моделью и представлением.
Один из критериев (опять же, приводимих Фаулером) того, относить что-то к уровню представления или нет, состоит в том, что при замене уровня представления с GUI/web на простой консольный вывод, вам не придется дублировать код. Если отнести форматирование к View, вам придется продублировать его в новом консольном слое представления.
Врочем, мне самому кажется этот момент несколько натянутым.
Предположим поэтому, что то что я назвал форматированием — в действительности сложная обработка, относящаяся к бизнес-логике.
Здравствуйте, mife, Вы писали:
N>>Модуль таблицы в простейшем случае — просто массив данных, к которому можно обращаться через какие-либо итераторы, где каждая итерация возвращает строку (а строка уже может собой представлять либо объект наподобие активной записи, либо просто набор значений в виде еще одного массива). M>То что Вы написали — это RecordSet (в терминологии Фаулера), а не модуль таблицы
Почитайте внимательно Фаулера (если у вас русский вариант, см. стр. 149, Принцип действия, второй абзац) — он там и говорит, что в частном случае модуль таблицы содержит RecordSet, и при отсутствии сложной бизнес-логики их можно приравнять (тем более, что я написал "в простейшем случае"). И хотя в последующих примерах он отделил это с помощью Data Table Gateway, никто не мешает вам использовать их вместе — два в одном.
M>>>Можно завести для каждой таблицы базы модуль, но кто в таком случае будет проводить вычисления C? N>>За это отвечает модуль бизнес-логики — он может быть промежуточным между модулем таблицы и представлением (паттерн Преобразователь данных). M>Нет уж, извините, опять же, по Фаулеру, модуль таблицы как раз и реализует бизнес-логику. M>По моему Вы путаете то что Фаулер называет шлюзом таблицы и модулем таблицы. Это (в идеале) разные вещи. Т.к. пример простой, можно считать что у нас — идеальный случай.
Это уже зависит от того, какую архитектуру вы построете. Если C работает с независимыми сущностями, не завязанные ни на какие данные, то логично их вынести в отдельный слой. Модуль таблицы отвечает в основном за такие вещи которые завязаны на данные, например, валидация. Единственное, я неправильно выразился — это просто паттерн Преобразователь.
M>Предположим поэтому, что то что я назвал форматированием — в действительности сложная обработка, относящаяся к бизнес-логике.
Нет уж, называйте вещи своими именами. Форматирование относится именно к GUI, и к бизнес-логики это отношения не имеет. Это может быть просто сложная логика, требующая интенсивной работы с данными, и тогда можно создать дополнительный уровень косвенности, но все-равно это будет относится к View.
Спасибо за Ваше внимание к моему вопросу, Nuald.
N>Почитайте внимательно Фаулера (если у вас русский вариант, см. стр. 149, Принцип действия, второй абзац) — он там и говорит, что в частном случае модуль таблицы содержит RecordSet, и при отсутствии сложной бизнес-логики их можно приравнять (тем более, что я написал "в простейшем случае"). И хотя в последующих примерах он отделил это с помощью Data Table Gateway, никто не мешает вам использовать их вместе — два в одном.
Эх, позвольте я проясню цели своего вопроса. Я хочу разобраться в понятниях, используемых Фаулером. Для этого я прошу на примере продемонстрировать как они работают. Из ответа должна быть видна разница между понятиями. А Вы мне предлагаете все смешать. Мне от этого понятней не станет.
Грубо говоря, я спрашиваю, чем водка отличается от пива, а мне предлагают смешать их. Это несомненно более действенное решение, если нужно забыться, но я не ищу решения — я хочу понять разницу.
M>>>>Можно завести для каждой таблицы базы модуль, но кто в таком случае будет проводить вычисления C? N>>>За это отвечает модуль бизнес-логики — он может быть промежуточным между модулем таблицы и представлением (паттерн Преобразователь данных). M>>Нет уж, извините, опять же, по Фаулеру, модуль таблицы как раз и реализует бизнес-логику. M>>По моему Вы путаете то что Фаулер называет шлюзом таблицы и модулем таблицы. Это (в идеале) разные вещи. Т.к. пример простой, можно считать что у нас — идеальный случай.
N>Это уже зависит от того, какую архитектуру вы построете. Если C работает с независимыми сущностями, не завязанные ни на какие данные, то логично их вынести в отдельный слой. Модуль таблицы отвечает в основном за такие вещи которые завязаны на данные, например, валидация. Единственное, я неправильно выразился — это просто паттерн Преобразователь.
Опять же, можно вводить дополнительные слои и т.п., это решает задачу. Но не имеет отношения к целям моего вопроса. В одном из примеров Фаулера модуль таблицы занимается определением зачтенного дохода. Это самая настоящая бизнес-логика, а не простая валидация.
Мой вопрос сводится на самом деле вот к чему: неужели паттерн Модуль Таблицы так плох, что даже в простых задачах требует введения дополнительных слоев?
M>>Предположим поэтому, что то что я назвал форматированием — в действительности сложная обработка, относящаяся к бизнес-логике.
Поясню — я немного изменил условия задачи. Забыли слово "форматирование" — над полем F выполняется операция, по сути относящаяся к бизнес-логике (ну какой-нибудь расчет сложного процента, например)
Здравствуйте, mife, Вы писали: M>Опять же, можно вводить дополнительные слои и т.п., это решает задачу. Но не имеет отношения к целям моего вопроса. В одном из примеров Фаулера модуль таблицы занимается определением зачтенного дохода. Это самая настоящая бизнес-логика, а не простая валидация. M>Мой вопрос сводится на самом деле вот к чему: неужели паттерн Модуль Таблицы так плох, что даже в простых задачах требует введения дополнительных слоев? M>Поясню — я немного изменил условия задачи. Забыли слово "форматирование" — над полем F выполняется операция, по сути относящаяся к бизнес-логике (ну какой-нибудь расчет сложного процента, например)
Модуль таблицы — замечательный подход, который имеет свои плюсы и минусы. А искать у Фаулера ответы на все вопросы — занятие неблагодарное, о чем он сам пишет в предисловии.
Возможные варианты решения вашей проблемы:
1. Вынести всю бизнес-логику в отдельный слой.
2. Вынести всю бизнес-логику касательно этих таблиц в отдельный класс не создавая отдельного слоя.
3. Реализовать этот метод в каждом классе.
4. Создать базовый класс и реализовать там этот метод и от него наследоваться.
5. Сделать по схеме primary-slave. В primary будут реализованы бизнес операции, а slave будет хранить указатель на них.
6. Сделать все через делегаты
7. ... etc.
Просто получается, что если сесть и хорошо подумать, то скорее всего ты придешь к решению описанному в одном из паттернов, что, впрочем, неудивительно.
P.S. Не надо бояться писать дополнительные классы, гораздо хуже если всю функциональность пытаться запихать в один.
Мне почему-то кажется, что все это не то, что хотел услышать mife...
идея такова:
таблица — список сущностей, запись — одна сущность.
вот над это сущностью выстраивается вся бизнес-логика.
далее так
нужно вам предоставить пользователя для просмотра какой-то список — это ваш селект (не вдаемся в вопросы реализации)
нужно вам что-то изменить —
person := Persons.GetById(index);
address := person.Address();
address.street := 'something';
Здравствуйте, mife, Вы писали:
M>Эх, позвольте я проясню цели своего вопроса. Я хочу разобраться в понятниях, используемых Фаулером. Для этого я прошу на примере продемонстрировать как они работают. Из ответа должна быть видна разница между понятиями. А Вы мне предлагаете все смешать. Мне от этого понятней не станет.
У себя я использую модуль таблицы как слой между представлением и шлюзом таблицы данных. Схема, нарисованная Фаулером на стр. 151 русского издания (рис. 9.5) немного некорректная — мы у себя в отделе долго ее разбирали и пришли к выводу, что загрузка данных представлением, а потом обработка их модулем таблицы чревата — лучше загрузку производить в модуле таблицы, тогда можно применять такие вещи как отложенную загрузку, и можно не беспокоиться о том, что программист забудет, что после загрузки данных их необходимо еще прошерстить бизнес-логикой.
M>Мой вопрос сводится на самом деле вот к чему: неужели паттерн Модуль Таблицы так плох, что даже в простых задачах требует введения дополнительных слоев?
Он не плох, но Фаулером описан криво, возможно это связано с тем, что он новичок в .NET и не совсем смог представить, как можно корректно реализовать данный паттерн.
Ага. У меня в голове кажется начинает просветляться.
Правильно ли я Вас понял, Oleg A. Bachin: модуль таблицы — это фактически суррогат обычной модели предметной области, используемый в том случае, когда нам не хочется тратить труд программистов/циклы процессора/нервные клетки на преобразование RecordSet'а (возвращаемого слоем данных) в настоящие объекты модели предметной области?
Ну то есть у модуля таблицы могут быть какие-то плюсы и минусы по ср. с моделью предметной области, но основной мотив, по которому этот паттерн появился, именно этот?
Здравствуйте, Nuald, Вы писали:
N>У себя я использую модуль таблицы как слой между представлением и шлюзом таблицы данных. Схема, нарисованная Фаулером на стр. 151 русского издания (рис. 9.5) немного некорректная — мы у себя в отделе долго ее разбирали и пришли к выводу, что загрузка данных представлением, а потом обработка их модулем таблицы чревата — лучше загрузку производить в модуле таблицы, тогда можно применять такие вещи как отложенную загрузку, и можно не беспокоиться о том, что программист забудет, что после загрузки данных их необходимо еще прошерстить бизнес-логикой.
Вот я после ответа Oleg A. Bachin пришел в выводу, что методы бизнес-логики в модуле таблицы относятся к отдельному экземпляру сущности (по крайней мере это наиболее типично).
Я согласен что отдавать загрузку данных слою представления опасно, но вызов метода, относящегося к отдельной сущности, должен как-то определить, какие именно данные загружать.
Как вы решаете эту проблему?
В общем-то это проблема обеспечения постоянства, и она относится не только к модулю таблицы; я пытаюсь понять, дает ли модуль таблицы (и шлюз таблицы) какие-то преимущества при ее решении. Я вообще все еще пытаюсь понять какие могут быть от него преимущества.
Здравствуйте, Nuald, Вы писали:
N>Он не плох, но Фаулером описан криво, возможно это связано с тем, что он новичок в .NET и не совсем смог представить, как можно корректно реализовать данный паттерн.
Это заслуга переводчика. Я, лично, хотел бы получше качество перевода за 720 р.
... << RSDN@Home 1.1.3 stable >>
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Здравствуйте, Igor Trofimov, Вы писали:
S>>Это заслуга переводчика. Я, лично, хотел бы получше качество перевода за 720 р.
iT>Это где ж такие цены?
В Москве, в Библио-Глобусе было 600 р., я же купил в каком-то магазине за 700.
... << RSDN@Home 1.1.3 stable >>
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re[9]: Фаулер: модуль таблицы
От:
Аноним
Дата:
15.10.04 09:47
Оценка:
Здравствуйте, Shady, Вы писали:
S>Здравствуйте, Igor Trofimov, Вы писали:
S>>>Это заслуга переводчика. Я, лично, хотел бы получше качество перевода за 720 р.
iT>>Это где ж такие цены? S>В Москве, в Библио-Глобусе было 600 р., я же купил в каком-то магазине за 700.
Эта книжка на Олимпийском мне обошлась в 450 рублей.
Здравствуйте, mife, Вы писали:
M>Ага. У меня в голове кажется начинает просветляться.
M>Правильно ли я Вас понял, Oleg A. Bachin: модуль таблицы — это фактически суррогат обычной модели предметной области, используемый в том случае, когда нам не хочется тратить труд программистов/циклы процессора/нервные клетки на преобразование RecordSet'а (возвращаемого слоем данных) в настоящие объекты модели предметной области?
M>Ну то есть у модуля таблицы могут быть какие-то плюсы и минусы по ср. с моделью предметной области, но основной мотив, по которому этот паттерн появился, именно этот?
В принципе да. Причем область довольно таки упрощена до того уровня, что мы в состоянии хранить сущной в одной таблице.
т.е. мы напрочь забываем про базы данных и оперируем PERSISTENTными объектами, а вот проблемы с сохранением и вычиткой на себя берет этот слой.
Это довольно таки удобно, но при сложной бизнес-логике и больших объемах начинаю проявляться вопросы с производительностью...
а вообще то довольно таки трудно сказать, что дешевле, проапгрейдить комп или при каких-то средних изменениях менять сиквэл запросы к базе с transaction script модели...