Вот тут возник интересный вопрос по QueryObject — это все же область BLL или DAL.
По сути, сам QueryObject это выражение некоего требования BLL к DAL ("дай мне объекты X по условию Y").
Вот предположим у нас в проекте все BLL Models мапятся в БД как есть. В этом случае QueryObject содержит linq запрос в терминах решаемой задачи. Вроде получается QueryObject принадлежит к BLL.
Теперь прдставим, что DAL (по каким-то причинам) вводит свои DTO и мапит в них BLL Models перед сохранением. Выходит, что в QueryObject должны уже быть linq запросы, где требования бизнес-логики выражены в объектах DAL DTO. Тогда это DAL или BLL?
PS: Что-то мне подсказывает что это будет Infrastructure, т.к. по сути посредник между БД и приложением. В общем, что-то путаться начинаю. Подскажите как правильно.
PPS: Размышляя далее начинаю приходить к выводу что все же паттерн Repository более универсален, по сравнению с QueryObject. Главное правильно его (Repository) готовить.
Здравствуйте, Doc, Вы писали:
IT>>DAL и BL при использовании Linq — это анахронизм, пережитки прошлого, от которых нужно избавлятся. Doc>Про DAL можно спорить, но почему BL анахронизм??? Где тогда бизнес логика?
А что такое бизнес логика? По-моему, бизнес логика — это отъём данных у формы ввода, валидация этих данных, первичная обработка, вторичная обработка, третичная валидация, сохранение в БД. Либо же отбор параметров у запроса, валидация параметров, запрос данных из БД, часто включающий в зависимости от бизнес логики различные фильтрации, группировки и сортировки на уровне SQL, рендеринг полученных данных в HTML или отображение на UI. В большинстве такой бизнес логике BL участвует лишь своими path through методами для переброски данных от БД к потребителю. И таких методов в BL 80%. Ну и нафига такую логику выделять в отдельный слой? Кроме как для внесения дополнительных проблем в понимание такого кода и его поддержку лично я никаких других преимуществ в нём больше не вижу.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Doc, Вы писали:
Doc>Про DAL можно спорить, но почему BL анахронизм??? Где тогда бизнес логика?
Игорь имеет в виду, что бизнес-логика конечно выносится в отдельные классы и методы, просто он не называет это слоем, а называет набор этих классов модулями или сервисами.
Здравствуйте, MozgC, Вы писали:
MC>Игорь имеет в виду, что бизнес-логика конечно выносится в отдельные классы и методы, просто он не называет это слоем, а называет набор этих классов модулями или сервисами.
Да я даже не знаю что ответить на его сообщение. Поскольку там сказано что BL занимается сохранением данных в БД и рендерингом HTML.
По-моему, бизнес логика — это отъём данных у формы ввода, валидация этих данных, первичная обработка, вторичная обработка, третичная валидация, сохранение в БД. Либо же отбор параметров у запроса, валидация параметров, запрос данных из БД, часто включающий в зависимости от бизнес логики различные фильтрации, группировки и сортировки на уровне SQL, рендеринг полученных данных в HTML или отображение на UI.
Но даже если все как вы сказали, то получается демагогия. Ну называйте это модулем — ключевой смысл то от этого не изменится. Главное, что это особобленная часть кода, служащая определенной цели.
А спорить про tier, layer, модуль итд можно бесконечно. Например, лично я не вижу проблем, чтобы в некоторых проектах в одной сборке лежали несколько слоев (layers).
Здравствуйте, Doc, Вы писали:
Doc>Вот тут возник интересный вопрос по QueryObject — это все же область BLL или DAL.
Doc>По сути, сам QueryObject это выражение некоего требования BLL к DAL ("дай мне объекты X по условию Y").
Doc>Вот предположим у нас в проекте все BLL Models мапятся в БД как есть. В этом случае QueryObject содержит linq запрос в терминах решаемой задачи. Вроде получается QueryObject принадлежит к BLL.
Doc>Теперь прдставим, что DAL (по каким-то причинам) вводит свои DTO и мапит в них BLL Models перед сохранением. Выходит, что в QueryObject должны уже быть linq запросы, где требования бизнес-логики выражены в объектах DAL DTO. Тогда это DAL или BLL?
Doc>PS: Что-то мне подсказывает что это будет Infrastructure, т.к. по сути посредник между БД и приложением. В общем, что-то путаться начинаю. Подскажите как правильно.
Doc>PPS: Размышляя далее начинаю приходить к выводу что все же паттерн Repository более универсален, по сравнению с QueryObject. Главное правильно его (Repository) готовить.
У вас фаулеризм головного мозга. Надо срочно сжечь книги по архитектуре и DDD и читать SICP.
Здравствуйте, Doc, Вы писали:
Doc>Здравствуйте, gandjustas, Вы писали:
G>>У вас фаулеризм головного мозга. Надо срочно сжечь книги по архитектуре и DDD
Doc>Ага, так я и кинулся планшет жечь
С планшета можно просто удалить.
G>>и читать SICP.
Doc>И тогда какая болезнь будет?
Скобочный рак, но эта болезнь протекает легче и не ведет к повреждению мозга.
А если серьезно, то стоит внимательнее почитать фаулера. У него черным по-английскому написано, что Repository это объекты, который отдает DTO в обмен на QueryObject. Это все уже давно реализовано в ORM и IQueryable интерфейсе. И нет смысла прятать что-то куда-то. PL и BL формируют QueryObject (который IQueryable) для своих нужд и вызывают DAL (который repository, который ORM) чтобы получить конкретные объекты или внести изменения.
Это уже получается функциональная декомпозиция, о которой очень подробно написано в SICP.
Здравствуйте, gandjustas, Вы писали:
G> Это все уже давно реализовано в ORM и IQueryable интерфейсе.
В принципе согласен.
Но вот на практике не все так гладко. Например, есть проблема в том, что в сами запросы иногда норовят влезть (причины разыные) детали реализации ORM/СУБД. Таким образом QO становится связанным с ними. И тогда вся эта пляска с абстракциями/ORM/Repository итд выглядит бессмысленно. Все равно прикручены к (например) MSSQL/EF.
Пример — на "стандартном" linq не выйдет написать запрос c поиском по шаблону. Или у меня были запросы, которые работали на MSSQL но падали на MySQL (а надо было общаться и с той и с той БД). Да, баг mySQL, да поправят, но сроки то идут и в своем коде делаешь костыль для запроса.
Далее — ограничения ORM. Тот же EF не умеет делать update/delete пачками. А грузить даже 1000 сущностей только ради их удаления еще то удовольствие (по времени). А индексы создать для CodeFirst (холиварить не надо )? Поэтому у меня в итоге остается DAL, который является декоратором для ORM.
Здравствуйте, Doc, Вы писали:
Z>>А когда QueryObject захочется спрятать, что делать будешь?
Doc>А когда перестанишь другим свои мысли присваивать, что писать на форуме будешь?
Намек, очевидно, не понят. LINQ и есть замечательная реализация паттерна QueryObject.
Здравствуйте, IT, Вы писали:
IT>А что такое бизнес логика? По-моему, бизнес логика — это отъём данных у формы ввода .... И таких методов в BL 80%.
Не, это нифига не бизнес-логика, это инфраструктурный код смешанный с логикой поведения приложения. Первое должно быть спрятано за хелперами и переезжать из проекта в проект, второе — писаться по сценариям для UI (если они есть конечно).
Бизнес-логика — это то, что имеет непосредственное отношение к описанию деятельности заказчика. Например, логика принятия заказов для разных категорий клиентов (если она есть конечно), выдача оборотки, анализ затрат-запасов, мониторинг индикаторов и т.д. и т.п.
IT> Ну и нафига такую логику выделять в отдельный слой? Кроме как для внесения дополнительных проблем в понимание такого кода и его поддержку лично я никаких других преимуществ в нём больше не вижу.
+1
Здравствуйте, Doc, Вы писали:
Doc>Здравствуйте, gandjustas, Вы писали:
G>> Это все уже давно реализовано в ORM и IQueryable интерфейсе.
Doc>В принципе согласен.
Doc>Но вот на практике не все так гладко. Например, есть проблема в том, что в сами запросы иногда норовят влезть (причины разыные) детали реализации ORM/СУБД. Таким образом QO становится связанным с ними. И тогда вся эта пляска с абстракциями/ORM/Repository итд выглядит бессмысленно. Все равно прикручены к (например) MSSQL/EF.
А оно и есть бессмысленно, этим не надо заниматься.
Doc>Пример — на "стандартном" linq не выйдет написать запрос c поиском по шаблону. Или у меня были запросы, которые работали на MSSQL но падали на MySQL (а надо было общаться и с той и с той БД). Да, баг mySQL, да поправят, но сроки то идут и в своем коде делаешь костыль для запроса.
Костыли инкапсулируешь в классы, создаешь реализации для разных баз и используешь IoC.
В итоге будет что-то вроде:
Doc>Далее — ограничения ORM. Тот же EF не умеет делать update/delete пачками.
Если очень надо и критично, то используй BLToolkit, если нет, то можно и загрузить\обновить.
Doc>А грузить даже 1000 сущностей только ради их удаления еще то удовольствие (по времени).
Их грузить не обязательно, достаточно ключи иметь.
На крайняк можно просто sql запрос в хранилище отдать. Не напрямую, а примерно как в коде выше.
Doc>А индексы создать для CodeFirst (холиварить не надо )? Здесь нету того что нужно?
Здравствуйте, gandjustas, Вы писали:
G>Костыли инкапсулируешь в классы, создаешь реализации для разных баз и используешь IoC.
Ну собственно вот и вынос QO (части их) в отдельную сборку. G>Их грузить не обязательно, достаточно ключи иметь.
Часто встречали ситуацию, когда 1000 ключей известно. Как правило нужен аналог delete from t where ...
Doc>>А индексы создать для CodeFirst (холиварить не надо )? G>Здесь нету того что нужно?
Есть. Но хоть migration, хоть велосипед — вопрос в том, что IMHO самый что не наесть DAL.
Но мы сейчас скатились к разговору нужен DAL или нет. Это не суть исходного вопроса. Давайте вернемся к тому, с чего я начинал. Мы не можем (по какой-то не важной тут причине) замапить наши Models напрямую в БД. Появляются DTO объекты, в которые сохраняются Models. Где расположим эти объекты. И самое главное, что тогда linq запросы должны оперировать и Models и DTO. Выходит они должны быть в с BLL.
И даже если исключить DAL, то получается что OQ должны располагаться в Infrastructure (то что у меня вышло, походит на описание Hexagon и Onion Architecture).
Здравствуйте, Doc, Вы писали:
Doc>Да я даже не знаю что ответить на его сообщение. Поскольку там сказано что BL занимается сохранением данных в БД и рендерингом HTML.
Видимо ты под BL понимаешь исключительно слой бизнес логики. Я же говорил просто о логике работы приложения.
Doc>Но даже если все как вы сказали, то получается демагогия. Ну называйте это модулем — ключевой смысл то от этого не изменится. Главное, что это особобленная часть кода, служащая определенной цели.
Ну тогда почитай определение abstraction layer, хотя бы здесь.
Doc>А спорить про tier, layer, модуль итд можно бесконечно. Например, лично я не вижу проблем, чтобы в некоторых проектах в одной сборке лежали несколько слоев (layers).
Сборка — это дело десятое. Предназначение слоя — это изоляция и скрытие деталей имплементации. Это хорошо работало в случае DAL, т.к. его основное предназначение — изоляция приложения от работы с прямым SQL. Linq эту проблему устраняет на корню, поэтому в DAL надобность отпадает. BLL в подавляющем большинстве случаев используется просто за компанию и в своей основе состоит из тупой переброски вызовов от потребителя к DAL. Смысла в этих методах ровно 0, только вред. А всё что остаётся от BLL без них можно оформить ввиде небольших сервисных модулей.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Doc, Вы писали:
Doc>Часто встречали ситуацию, когда 1000 ключей известно. Как правило нужен аналог delete from t where ...
Пример? Удалять прямо так не глядя что удаляется? Что за бизнес-задача?
Doc>>>А индексы создать для CodeFirst (холиварить не надо )? G>>Здесь нету того что нужно?
Doc>Есть. Но хоть migration, хоть велосипед — вопрос в том, что IMHO самый что не наесть DAL.
Migration уже не велосипед, а часть EF. Можно его DAL обозвать, но это выглядит как попытка скрыть суть за базвордами.
Doc>Мы не можем (по какой-то не важной тут причине) замапить наши Models напрямую в БД.
Тогда выкиньте модели, зачем они вам нужны.
Doc>Появляются DTO объекты, в которые сохраняются Models. Где расположим эти объекты. И самое главное, что тогда linq запросы должны оперировать и Models и DTO.
Не лечите симптомы, лечите то что их вызывает.
Doc>Выходит они должны быть в с BLL.
Linq запросы? Они и в PL должны быть, кто будет сортировку\группировку результатов задавать.
Вообще суть QueryObject в том что его можно по кускам собирать в разных слоях.
Doc>И даже если исключить DAL, то получается что OQ должны располагаться в Infrastructure (то что у меня вышло, походит на описание Hexagon и Onion Architecture).
Советую курить SICP, а не описание архитектуры.
Здравствуйте, IT, Вы писали:
IT>Видимо ты под BL понимаешь исключительно слой бизнес логики. Я же говорил просто о логике работы приложения.
Там было точно написано
По-моему, бизнес логика — это отъём ...
Но если в ответ про BL ты зачем-то переключился на работу приложения, то ... может проще сказать прямо что запутался сам в ответе?
IT>Linq эту проблему устраняет на корню, поэтому в DAL надобность отпадает.
Не буду повторяться про проблемы с linq и ORM. Куда "костыли" и расширения для них складывать?
IT>Смысла в этих методах ровно 0, только вред.
Если у вас в проектах так, то не стоит обобщать на всех.
Здравствуйте, gandjustas, Вы писали:
G>Пример? Удалять прямо так не глядя что удаляется? Что за бизнес-задача?
Да хоть:
delete from logs where date < [value]
или
delete from actions where tdate = 53 (с таким tdate может быть сколько угодно записей)
так же есть обновления полей по схожим условиям (данные события обновляются в зависимости от параметров события)
G>Migration уже не велосипед, а часть EF.
Я говорил что Migration — велосипед?
G>Можно его DAL обозвать, но это выглядит как попытка скрыть суть за базвордами.
Ничего подобного. Суть и область ответственности EF и Migration как раз подходит под DAL.
G>Тогда выкиньте модели, зачем они вам нужны.
Очень смело. Но вы не учитывает что BLL и Models отражают бизнес-процесс заказчика, а DTO для DAL это просто необходимость.
G>Они и в PL должны быть
OQ в UI? Сильно сомневаюсь.
G>Советую курить SICP, а не описание архитектуры.
Здравствуйте, Doc, Вы писали:
Doc>Здравствуйте, gandjustas, Вы писали:
G>>Пример? Удалять прямо так не глядя что удаляется? Что за бизнес-задача?
Doc>Да хоть: Doc>delete from logs where date < [value] Doc>или Doc>delete from actions where tdate = 53 (с таким tdate может быть сколько угодно записей) Doc>так же есть обновления полей по схожим условиям (данные события обновляются в зависимости от параметров события)
Можно прямо такую команду в storage отправить. Для этого queryobject не нужен.
G>>Тогда выкиньте модели, зачем они вам нужны. Doc>Очень смело. Но вы не учитывает что BLL и Models отражают бизнес-процесс заказчика, а DTO для DAL это просто необходимость.
Зачем какая-то часть кода должна отражать процессы заказчика? Заказчик будет код читать? Процессы заказчика в первую очередь должен отражать UI, в последнюю тоже.
Остальное надо делать так чтобы пришлось меньше код трогать при необходимости внесения изменений.
А то получается что добавление поля приведет к изменению 3 классов с данными и нескольких методов в разных слоях. Это очень хрупкая (Fragile) архитектура.
G>>Они и в PL должны быть Doc>OQ в UI? Сильно сомневаюсь.
PL и UI немного разные вещи.
Здравствуйте, Doc, Вы писали:
IT>>Видимо ты под BL понимаешь исключительно слой бизнес логики. Я же говорил просто о логике работы приложения.
Doc>Там было точно написано Doc>
По-моему, бизнес логика — это отъём ...
И где здесь написано слой?
Doc>Но если в ответ про BL ты зачем-то переключился на работу приложения, то ... может проще сказать прямо что запутался сам в ответе?
Давай ты оставишь свои домыслы при себе. Тогда можно будет конструктивно поговорить.
Логика работы приложения — это логика работы приложения, которая включает в себя в том числе и бизнес логику. Отождествлять бизнес логику только с BLL глупо, т.к. часть этой самой бизнес логики может находится, и как правило находится, в том же DAL, т.к. фильтрации, группировки и сортировки эффективнее делать средствами SQL.
IT>>Linq эту проблему устраняет на корню, поэтому в DAL надобность отпадает. Doc>Не буду повторяться про проблемы с linq и ORM. Куда "костыли" и расширения для них складывать?
Куда удобнее туда и складывай. Или ты считаешь, что из-за одного костыля стоит городить огород из множества слоёв?
IT>>Смысла в этих методах ровно 0, только вред. Doc>Если у вас в проектах так, то не стоит обобщать на всех.
Ну почему же. Это как раз прямое следствие грамотно спроектированного приложения. Если у вас не так, то могу сказать с полной уверенностью, что ваш BLL занимается в основном переливанием из пустого в порожнее, тратит электричество на перекладывание модели данных в какую-нибудь свою модель приложения. С этим, кстати, тоже очень хорошо справляется Linq. Нет надобности получать данные сначала в виде модели данных, а потом их перекладывать в модель приложения. Можно сразу получать данные в нужном виде. Но для этого для начала хорошо бы избавиться от застарелых догм.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Doc, Вы писали:
IT>>Ну что, будем развенчивать мифы от повторном использовании бизнес логики или ну его? Doc>Или у вас все запросы (QueryObject) используются только один раз и в одном месте кода?
Не могу уловить смысл этого вопроса. Можешь пояснить?
Doc>Про повторное использование BLL ты сам придумал.
Здравствуйте, gandjustas, Вы писали:
G>Можно прямо такую команду в storage отправить. Для этого queryobject не нужен.
Т.е. вы предлагаете чтобы BL ставила SQL запрос и отправила его в сразу (через контекст) в БД? Это получается как "немножко беременна".
G>Зачем какая-то часть кода должна отражать процессы заказчика? Заказчик будет код читать? Процессы заказчика в первую очередь должен отражать UI, в последнюю тоже.
Не передёргивайте. Заказчик код читать не будет. Но если его бизнес-процесс сложнее чем "прочитать из блога/записать в блог/сложить 2 и 2", то переписывать его бизнес-процессы в терминах DTO-объектов задача очень мягко говоря не благодарная.
И потом, давайте в первую очередь смотреть что для чего нужно? Классы Models предназначены чтобы отразить некие данные процесса заказчика в приложении. И они максимально близки к реальным документам. А DTO — представить данные удобной для хранения форме. Эти DTO "личная собственность DAL" и его пределы не покидают. В итоге (и у меня такое было) те операции, которые можно применить к Models просто нельзя применить к DTO. Поэтому замена в принципе не возможна.
G>Остальное надо делать так чтобы пришлось меньше код трогать при необходимости внесения изменений.
Согласен. И это согласуется с тем что я написал.
G>А то получается что добавление поля приведет к изменению 3 классов с данными и нескольких методов в разных слоях. Это очень хрупкая (Fragile) архитектура.
Добавление поля в Модель в большинстве случаев затронет все слои.
* БД (т.е. DAL) изменится, т.к. даже для прямого сохранения (типа EF Code First) придется мигрировать БД. А для случая DTO — создать соответствующее свойство и сохранять в него данные.
* BLL меняется по определению (само поле и логика работы с ним)
* И скорее всего поменяется PL. Вы же как-то это поле отображать или даже вводить в него значения будете.
G>PL и UI немного разные вещи.
Здравствуйте, Doc, Вы писали:
Doc>Здравствуйте, gandjustas, Вы писали:
G>>Можно прямо такую команду в storage отправить. Для этого queryobject не нужен.
Doc>Т.е. вы предлагаете чтобы BL ставила SQL запрос и отправила его в сразу (через контекст) в БД? Это получается как "немножко беременна".
Чтобы не вдаваться в терминологический спор о том что такое BL, давайте сделаем конкретный контекст.
Представим что у нас есть ASP.NET MVC приложение, в котором есть собственно MVC часть, есть набор классов, которые содержат всю логику работы, не касающуюся UI (выборки, изменения данных, расчеты), и ORM.
Можно считать что это PL, BL, DAL.
Так что плохого вы видите в том что контроллер будет вызывать метод класса BL, который в свою очередь вызовет метод ExecuteSQL в классе контекста ORM?
Естественно считаем что зависимости подсовываются через IoC.
G>>Зачем какая-то часть кода должна отражать процессы заказчика? Заказчик будет код читать? Процессы заказчика в первую очередь должен отражать UI, в последнюю тоже.
Doc>Не передёргивайте. Заказчик код читать не будет. Но если его бизнес-процесс сложнее чем "прочитать из блога/записать в блог/сложить 2 и 2", то переписывать его бизнес-процессы в терминах DTO-объектов задача очень мягко говоря не благодарная.
Не понял что с чем сравнивается честно говоря. Если бизнес-процесс сложен, то его в явном виде в коде все равно не удастся выразить. А если удастся, то связность кода будет такая, что замучаешься поддерживать.
Надо его побить на элементарные действия, которые требуют одного действия от пользователя (одной транзакции), а потом связать из workflow движком или сделать явный переход по статусам в БД.
Doc>И потом, давайте в первую очередь смотреть что для чего нужно?
Дейтсвительно.
Doc>Классы Models предназначены чтобы отразить некие данные процесса заказчика в приложении. И они максимально близки к реальным документам. А DTO — представить данные удобной для хранения форме.
То есть данные в Model находятся в "неудбной" форме. Это плохо.
А вот то что они максимально близки к реальным документам — еще непонятно хорошо это или нет. Мой опыт подсказывает, что скорее нет.
И зачем оно нужно?
Doc>Эти DTO "личная собственность DAL" и его пределы не покидают.
Не понимаю этого. Зачем такое разделение?
Doc>В итоге (и у меня такое было) те операции, которые можно применить к Models просто нельзя применить к DTO. Поэтому замена в принципе не возможна.
Правильно, я и говорю что Models вам не нужны. Используйте везде DTO.
G>>Остальное надо делать так чтобы пришлось меньше код трогать при необходимости внесения изменений. Doc>Согласен. И это согласуется с тем что я написал.
Ни калпи не согласуется. У вас несколько классов, с неявным связями: Models и DTO, надо синхронно вносить изменения.
G>>А то получается что добавление поля приведет к изменению 3 классов с данными и нескольких методов в разных слоях. Это очень хрупкая (Fragile) архитектура. Doc>Добавление поля в Модель в большинстве случаев затронет все слои.
Я говорю что надо как минимум будет в 2 места добавить поле и еще дополнить код, который поля туда-сюда перекладывает данные. Это 3 изменения вместо одного, причем никто явно не скажет куда их надо внести, связи неявные получаются, а это плохо.
А если взять кейс посложнее, чем добавление поля, то количество изменений растет лавинообразно из-за таких связей.
Кстати. С одним классом DTO EF может "автомагически" сделать миграцию изменения поля. Ваши дополнительные классы сильно усложняют поддержку.
G>>PL и UI немного разные вещи. Doc>Вы под PL что понимаете — Presentation Layer?
Да
Здравствуйте, gandjustas, Вы писали:
G>Так что плохого вы видите в том что контроллер будет вызывать метод класса BL, который в свою очередь вызовет метод ExecuteSQL в классе контекста ORM?
Тем, что BL теперь напрямую зависим от СУБД. Особенно, если нас потянет в этом SQL использовать специфику конкретной версии.
Более того, я против вообще проброса контекста в BL. Это привязывает нас к конкретной реализации ORM. Да саму ORM меняют не часто. Но вот для EF есть все же разница в работе с EF CF и EF DF или MF. И её как раз можно скрыть.
Что делаю я — в BL передается IRepository с поддержкой QueryObject или Specification. В итоге, я легко меняю EF CF (который люблю использовать на первым этапе) или вообще внутри при необходимости скажем в скорости дергать SQL. Главное — как бы я не изголялся с работой с БД, код BL я не трогаю.
G>Не понял что с чем сравнивается честно говоря.
Еще раз — сущности для сохранения данных в БД могут быть настолько отличными от бизнес-сущностей, что написать бизнес-логику для них практически не возможно (ну или с большими издержками). Да и вообще, подстраивать BL под особенности хранилища данных IMHO не правильно.
G>То есть данные в Model находятся в "неудбной" форме. Это плохо.
В неудобной для выбранного хранилища форме.
G>А вот то что они максимально близки к реальным документам — еще непонятно хорошо это или нет. Мой опыт подсказывает, что скорее нет. G>И зачем оно нужно?
Как минимум чтобы не изобретать копию бизнес-процесса в своих терминах (вернее терминах БД). Я понимаю, что если все сводится к save/load/find by id то проще и быстрее подстроиться под выбранную БД. Но как только появятся формулы и расчеты — замучаетесь переписывать их в своих терминах.
Давайте дам пример. Есть большой поток данных с датчиков в real-time. Практика показала, что хранить их в формате date/name/value очень накладно по объему и нагрузке. Был взят формат сохраняющий не каждые точки, а только контрольные. Т.е. в БД лежит формат в принципе не похожий на date/value. Как вы предлагаете такие данные встраивать "напрямую" в бизнес-логику (формы расчета среднего, суммы, учета, сопоставления параметров итд). Должны ли они зависеть от формата БД? Или же лучше чтобы repository принимал и отдавал привычный date/name/value, а подробности сохранения были скрыты от BL?
Doc>>Эти DTO "личная собственность DAL" и его пределы не покидают. G>Не понимаю этого. Зачем такое разделение?
Пример выше.
G>Правильно, я и говорю что Models вам не нужны. Используйте везде DTO.
Т.е. надо было в том примере все формулы переписать под формат DTO? Данные из БД невозможно использовать в них напрямую (еще раз, там нет всех точек — есть данные для полного их восстановления). В итоге, в BL появился был конвертор [DAL DTO] <-> [Object вида date/name/value]. А это значит что мы успешно перетащили одну из ответственностей DAL и BL. Шикарно.
G>Ни калпи не согласуется. У вас несколько классов, с неявным связями: Models и DTO, надо синхронно вносить изменения.
То что EF CF сам при первом запуске подгоняет "внутренности" еще не значит что нет изменений. При добавлении класса надо прописать его в контекст и мигрировать БД, а при добавлении свойства — просто мигрировать БД. Про EF DF/MF вообще думаю спорить нет смысла.
G>Я говорю что надо как минимум будет в 2 места добавить поле и еще дополнить код, который поля туда-сюда перекладывает данные. Это 3 изменения вместо одного, причем никто явно не скажет куда их надо внести, связи неявные получаются, а это плохо.
А связь — контекст/модель явная? А compiler поругает что поле нет в UI? В общем такой крайний случай, как изменение Модели это всяко большая задача.
И опять же — тогда сразу отметайте использование EF DF/MF — там по сути создаются свои DTO и надо будет каждый подкручивать или модель БД или модель классов.
G>Кстати. С одним классом DTO EF может "автомагически" сделать миграцию изменения поля. Ваши дополнительные классы сильно усложняют поддержку.
Может, но не всегда. Иногда может заставить писать код миграции.
Главное вы не учитываете что использование DTO для хранения не прихоть. Пока возможно (и для многих задач это так) я буду сохранять Модель, но при необходимости введу DTO внутри DAL.
Главный поинт — я за то, чтобы особенности ORM и хранилища данных не проникали в BLL. Поэтому — можно хоть SQL но только внутри DAL.
Здравствуйте, Doc, Вы писали:
Doc>Здравствуйте, gandjustas, Вы писали:
G>>Так что плохого вы видите в том что контроллер будет вызывать метод класса BL, который в свою очередь вызовет метод ExecuteSQL в классе контекста ORM?
Doc>Тем, что BL теперь напрямую зависим от СУБД. Особенно, если нас потянет в этом SQL использовать специфику конкретной версии.
Это разве проблема? В подавляющем большинстве случаев ты точно знаешь в каком окружении и с какой версией базы будет работать приложение. Версии MS SQL обратно совместимы, то что работало на 2005 заработает на 2012.
Для отдельных случаев где это нетак — можно написать несколько реализаций под разные БД. Вызывающий код не заметит, ибо IoC.
Или просто сделать ХП на сервере для таких случаев.
Doc>Более того, я против вообще проброса контекста в BL. Это привязывает нас к конкретной реализации ORM. Да саму ORM меняют не часто.
ORM не меняют никогда.
Doc>Но вот для EF есть все же разница в работе с EF CF и EF DF или MF. И её как раз можно скрыть.
Разницы на уровне клиентского кода нет, разница только в инициализации, она разруливается вне BL.
Клиентский код работает с DbContext и DbSet, в остальные часть EF лезть не должен.
G>>Не понял что с чем сравнивается честно говоря.
Doc>Еще раз — сущности для сохранения данных в БД могут быть настолько отличными от бизнес-сущностей, что написать бизнес-логику для них практически не возможно (ну или с большими издержками).
Приведи пример, не могу понять о чем ты. В чем проблема достать из БД ровно то что нужно? Ты же можешь результаты запроса замапить в произвольный DTO.
Doc>Да и вообще, подстраивать BL под особенности хранилища данных IMHO не правильно.
Если снижает затраты на разработку и поддержку, то очень даже правильно.
G>>А вот то что они максимально близки к реальным документам — еще непонятно хорошо это или нет. Мой опыт подсказывает, что скорее нет. G>>И зачем оно нужно?
Doc>Как минимум чтобы не изобретать копию бизнес-процесса в своих терминах (вернее терминах БД). Я понимаю, что если все сводится к save/load/find by id то проще и быстрее подстроиться под выбранную БД. Но как только появятся формулы и расчеты — замучаетесь переписывать их в своих терминах.
Приведи пример, пока выглядит как война с ветряными мельницами.
Doc>Давайте дам пример. Есть большой поток данных с датчиков в real-time. Практика показала, что хранить их в формате date/name/value очень накладно по объему и нагрузке. Был взят формат сохраняющий не каждые точки, а только контрольные. Т.е. в БД лежит формат в принципе не похожий на date/value. Как вы предлагаете такие данные встраивать "напрямую" в бизнес-логику (формы расчета среднего, суммы, учета, сопоставления параметров итд). Должны ли они зависеть от формата БД? Или же лучше чтобы repository принимал и отдавал привычный date/name/value, а подробности сохранения были скрыты от BL?
Типовой способ решения таких проблем:
1) Первый процесс пишет поток данных в файл (csv)
2) Второй процесс периодически считывает файлы, выполняет агрегацию и расчеты, кладет результат в базу.
БЛ обычно работает на втором этапе, она на вход принимает DTO, построенные на CSV, а выдает DTO для записи в базу.
Каждый DTO повторяет именно структуру хранения.
А если надежность не требуется, то можно прямо внутри приложения на IObservable все сделать, c теми же DTO.
G>>Правильно, я и говорю что Models вам не нужны. Используйте везде DTO.
Doc>Т.е. надо было в том примере все формулы переписать под формат DTO? Данные из БД невозможно использовать в них напрямую (еще раз, там нет всех точек — есть данные для полного их восстановления). В итоге, в BL появился был конвертор [DAL DTO] <-> [Object вида date/name/value]. А это значит что мы успешно перетащили одну из ответственностей DAL и BL. Шикарно.
Да, перетащили. Коме от этого хуже стало? Вместо вызова метода конвертации в DAL, он будет вызываться в БЛ.
Даже лучше станет. DAL сведется до банального ORM, будет поддерживать автомагические миграции. Тестировать станет проще. Банально кода будет меньше.
G>>Ни калпи не согласуется. У вас несколько классов, с неявным связями: Models и DTO, надо синхронно вносить изменения.
Doc>То что EF CF сам при первом запуске подгоняет "внутренности" еще не значит что нет изменений. При добавлении класса надо прописать его в контекст и мигрировать БД, а при добавлении свойства — просто мигрировать БД. Про EF DF/MF вообще думаю спорить нет смысла.
Тем не менее, вам придется еще несколько сущностей править.
G>>Я говорю что надо как минимум будет в 2 места добавить поле и еще дополнить код, который поля туда-сюда перекладывает данные. Это 3 изменения вместо одного, причем никто явно не скажет куда их надо внести, связи неявные получаются, а это плохо.
Doc>А связь — контекст/модель явная? А compiler поругает что поле нет в UI? В общем такой крайний случай, как изменение Модели это всяко большая задача.
А поле может быть не нужно в UI.
Doc>И опять же — тогда сразу отметайте использование EF DF/MF — там по сути создаются свои DTO и надо будет каждый подкручивать или модель БД или модель классов.
Дык классы генерятся при изменении модели.
Doc>Главный поинт — я за то, чтобы особенности ORM и хранилища данных не проникали в BLL. Поэтому — можно хоть SQL но только внутри DAL.
Еще раз. Зачем это? Ты продолжаешь повторять утверждение, даже не пытаясь сказать зачем оно нужно.
Здравствуйте, gandjustas, Вы писали:
G>Это разве проблема?
Для вас видимо нет. Я считаю что да.
G>Для отдельных случаев где это нетак — можно написать несколько реализаций под разные БД.
Я удивляюсь. Вы легко вносите обязанности DAL в BL причем даже в виде готовых классов. Но логически выделить это вместе с ORM и назвать DAL вам видимо религия мешает.
G>ORM не меняют никогда.
Т.е. вы готовы утверждать что ни одна команда в мире ни на одном проекте не меняла ORM?
Doc>>Но вот для EF есть все же разница в работе с EF CF и EF DF или MF. И её как раз можно скрыть. G>Разницы на уровне клиентского кода нет, разница только в инициализации, она разруливается вне BL.
Точно нет? А что там автоматические созданные entities, а тут у вас "ручные" POCO ничего не меняет?
G>Клиентский код работает с DbContext и DbSet, в остальные часть EF лезть не должен.
А где лежит этот остальной код? У вас DAL то нет В BL?
G>Приведи пример, не могу понять о чем ты. В чем проблема достать из БД ровно то что нужно? Ты же можешь результаты запроса замапить в произвольный DTO.
+ G>Приведи пример, пока выглядит как война с ветряными мельницами.
Приводил в том же сообщении.
Doc>>Давайте дам пример. Есть большой поток данных с датчиков в real-time. Практика показала, что хранить их в формате date/name/value очень накладно по объему и нагрузке. Был взят формат сохраняющий не каждые точки, а только контрольные. Т.е. в БД лежит формат в принципе не похожий на date/value. Как вы предлагаете такие данные встраивать "напрямую" в бизнес-логику (формы расчета среднего, суммы, учета, сопоставления параметров итд). Должны ли они зависеть от формата БД? Или же лучше чтобы repository принимал и отдавал привычный date/name/value, а подробности сохранения были скрыты от BL?
G>Типовой способ решения таких проблем: G>1) Первый процесс пишет поток данных в файл (csv)
И комп опухает от дисковых операций (пробовали). Еще раз "есть большой поток данных". Кол-во принимаемых параметров меряется в тысячах и десятках тысяч.
G>2) Второй процесс периодически считывает файлы, выполняет агрегацию и расчеты, кладет результат в базу.
1) Приемлемую производительность на доступном железе дает только анализ на лету и запись в БД частное облако там не подходит по цене и по постановке задачи заказчиком).
2) Даже если поставить супербыстрый raid на SSD и решить проблему скорости I/O, то вопрос в том, что данные в BL нужны не только за последний час, а вообще за любой промежуток истории.
Doc>>Т.е. надо было в том примере все формулы переписать под формат DTO? Данные из БД невозможно использовать в них напрямую (еще раз, там нет всех точек — есть данные для полного их восстановления). В итоге, в BL появился был конвертор [DAL DTO] <-> [Object вида date/name/value]. А это значит что мы успешно перетащили одну из ответственностей DAL и BL. Шикарно. G>Да, перетащили. Коме от этого хуже стало? Вместо вызова метода конвертации в DAL, он будет вызываться в БЛ.
И чем это лучше, чем та же конвертация, скрытая от BL в DAL. Только вам придется все формулы расчета переделывать, а я их как есть из ТЗ возьму. И код понятнее в поддержке, т.к. четко видно соответствие формул ТЗ и кода в BL.
G>Тем не менее, вам придется еще несколько сущностей править.
Только для случая с EF:CF. Для DF и MF у вас так же будут правки.
G>>>Я говорю что надо как минимум будет в 2 места добавить поле и еще дополнить код, который поля туда-сюда перекладывает данные. Это 3 изменения вместо одного, причем никто явно не скажет куда их надо внести, связи неявные получаются, а это плохо.
Давайте считать:
1) Добавляю поле в Модель
2) Добавляю после в DTO
3) Если между ними соответствие 1 в 1 то пишу логику. Иначе можно вообще на object маппер положиться.
G>А поле может быть не нужно в UI.
Т.е. вы считаете что добавление свойства в модель это простая операция?
G>Дык классы генерятся при изменении модели.
А я говорил что не так?
G>Еще раз. Зачем это? Ты продолжаешь повторять утверждение, даже не пытаясь сказать зачем оно нужно.
Повторяю последний раз
1) Независимость от хранилища (сознательно не пишу БД, т.к. есть масса других вариантов и есть задачи где можно выбирать или поддерживать разные)
2) Независимость от ORM и возможность на уровне DAL. Специально подчеркиваю — DAL тут является декоратором для ORM + дополнительные функции + код настройки.
3) Возможность писать BL не оглядываясь на то, как сделан DAL (равно как и PL).
PS: Цели убедить вас делать такой вариант архитектуры у меня нет. Да и вообще мы ушли от исходного вопроса очень сильно в сторону. Хотя я для себя ответ нашел.
Здравствуйте, Doc, Вы писали:
Doc>Здравствуйте, gandjustas, Вы писали:
G>>Это разве проблема? Doc>Для вас видимо нет. Я считаю что да.
Проблема существует, когда она существует объективно. Если это исключительно ваше мнение, которое вы не готовы подкрепить массовым опытом или формальным выкладками, то это и останется только вашем мнением. Но тогда вам нет смысла спрашивать на форуме мнение других людей
G>>Для отдельных случаев где это нетак — можно написать несколько реализаций под разные БД. Doc>Я удивляюсь. Вы легко вносите обязанности DAL в BL причем даже в виде готовых классов. Но логически выделить это вместе с ORM и назвать DAL вам видимо религия мешает.
Я обычно не разделяю DAL\BL, все что межу интерфейсом и ORM для меня все BL. Не вижу смысла в словоблудии типа что к чему относить. Вообще проектировать на основе умозрительного отнесения функционала к тому или иному слою неэффективно.
Это как раз религия требует формального разделения на слои и сокрытия функционала, реальный опыт показывает что это только увеличивает объем кода без улучшения функциональности.
G>>ORM не меняют никогда. Doc>Т.е. вы готовы утверждать что ни одна команда в мире ни на одном проекте не меняла ORM?
Нет, я готов утверждать что 99% команд не меняли ОРМ на своих проектах. А если меняли, то это была масштабная переделка, которая не могла быть сведена к замене DAL.
Doc>>>Но вот для EF есть все же разница в работе с EF CF и EF DF или MF. И её как раз можно скрыть. G>>Разницы на уровне клиентского кода нет, разница только в инициализации, она разруливается вне BL. Doc>Точно нет? А что там автоматические созданные entities, а тут у вас "ручные" POCO ничего не меняет?
Я уже давно пользуюсь t4 генератором для Model First, который дает такие же DTO, как и при написании руками.
G>>Клиентский код работает с DbContext и DbSet, в остальные часть EF лезть не должен. Doc>А где лежит этот остальной код? У вас DAL то нет В BL?
Да, все что между интерфейсом и ORM — BL. Так меньше придется спорить о терминах.
Doc>>>Давайте дам пример. Есть большой поток данных с датчиков в real-time. Практика показала, что хранить их в формате date/name/value очень накладно по объему и нагрузке. Был взят формат сохраняющий не каждые точки, а только контрольные. Т.е. в БД лежит формат в принципе не похожий на date/value. Как вы предлагаете такие данные встраивать "напрямую" в бизнес-логику (формы расчета среднего, суммы, учета, сопоставления параметров итд). Должны ли они зависеть от формата БД? Или же лучше чтобы repository принимал и отдавал привычный date/name/value, а подробности сохранения были скрыты от BL?
G>>Типовой способ решения таких проблем: G>>1) Первый процесс пишет поток данных в файл (csv)
Doc>И комп опухает от дисковых операций (пробовали). Еще раз "есть большой поток данных". Кол-во принимаемых параметров меряется в тысячах и десятках тысяч.
Оо что у вас за компы? Можно мегабайт в секнуду писать на диск линейно, комп от этого не страдает вообще никак. Если у вас приходит больше данных (что маловероятно), то тогда inmemory обработка и агрегация. А потом уже запись.
G>>2) Второй процесс периодически считывает файлы, выполняет агрегацию и расчеты, кладет результат в базу.
Doc>1) Приемлемую производительность на доступном железе дает только анализ на лету и запись в БД частное облако там не подходит по цене и по постановке задачи заказчиком).
Как тут поможет модель, отличая от DTO?
Doc>2) Даже если поставить супербыстрый raid на SSD и решить проблему скорости I/O, то вопрос в том, что данные в BL нужны не только за последний час, а вообще за любой промежуток истории.
Мы все еще о записи потока данных в хранилище? Есть подозрение что БЛ, которой нужны данные "вообще за любой промежуток истории" не относится к записи в хранилище, и, скорее всего, будет другими средствами делаться.
Doc>>>Т.е. надо было в том примере все формулы переписать под формат DTO? Данные из БД невозможно использовать в них напрямую (еще раз, там нет всех точек — есть данные для полного их восстановления). В итоге, в BL появился был конвертор [DAL DTO] <-> [Object вида date/name/value]. А это значит что мы успешно перетащили одну из ответственностей DAL и BL. Шикарно. G>>Да, перетащили. Коме от этого хуже стало? Вместо вызова метода конвертации в DAL, он будет вызываться в БЛ.
Doc>И чем это лучше, чем та же конвертация, скрытая от BL в DAL. Только вам придется все формулы расчета переделывать, а я их как есть из ТЗ возьму. И код понятнее в поддержке, т.к. четко видно соответствие формул ТЗ и кода в BL.
Тем что DAL проще и не требует поддержки (вообще). Для соответствия формул можешь просто локальные переменные использовать.
G>>Тем не менее, вам придется еще несколько сущностей править. Doc>Только для случая с EF:CF. Для DF и MF у вас так же будут правки.
Нет, потому что все давно генерируется на t4.
G>>А поле может быть не нужно в UI. Doc>Т.е. вы считаете что добавление свойства в модель это простая операция?
Нет, я лишь говорю что лишние модели в коде делают его более хрупким.
Doc>Повторяю последний раз Doc>1) Независимость от хранилища (сознательно не пишу БД, т.к. есть масса других вариантов и есть задачи где можно выбирать или поддерживать разные)
Мимо кассы, в твоем случае, из-за bottleneck в IO и все приложение начинает зависеть от хранилища. А в среднем случае хранилище заранее известно и его изменение связано с расширением функционала.
Doc>2) Независимость от ORM и возможность на уровне DAL. Специально подчеркиваю — DAL тут является декоратором для ORM + дополнительные функции + код настройки.
Еще дальше от цели, так как в подавляющем большинстве случаев ORM не меняется, а лишний код вокруг его только бесцельно усложняет приложение.
Doc>3) Возможность писать BL не оглядываясь на то, как сделан DAL (равно как и PL).
Тоже самое дает ORM и IQueryable.
Цели крайне эфемерны, большинство достигается без отдельного слоя DAL, а прямым использованием ORM.
Вообще религиозная попытка разделить слой DAL и BL при наличии мощных ORM не имеет никакого смысла, так же как попытки прятать функционал.
Все это только усложняет приложение, не давая преимуществ в среднем случае.
Здравствуйте, gandjustas, Вы писали:
G>Проблема существует, когда она существует объективно.
Кто там бы против словоблудия?
G>Но тогда вам нет смысла спрашивать на форуме мнение других людей
Ну это уже мне решать.
G>Нет, я готов утверждать что 99% команд не меняли ОРМ на своих проектах. А если меняли, то это была масштабная переделка, которая не могла быть сведена к замене DAL.
Если ORM полностью изолирована от BL в DAL, то назовите причину менять BL?
G>Я уже давно пользуюсь t4 генератором для Model First, который дает такие же DTO, как и при написании руками.
Вы упорно уходите в сторону — суть в том, что руками меняем, миграцией, генератором ... это все изменения. И причем не явные (надо не забыть вписать, запустить, сгенерить).
G>Оо что у вас за компы?
Опять уходите в сторону. Какая разница что за компы и что ее там делает в это время комп? Главное — данные в любой момент могут потребоваться за любой интервал. Вопрос как доставать? Я уже понял что вы бы или хранили 1 в 1 или в BL везде в формулах учитывали формат данных.
Doc>>1) Приемлемую производительность на доступном железе дает только анализ на лету и запись в БД частное облако там не подходит по цене и по постановке задачи заказчиком). G>Как тут поможет модель, отличая от DTO?
Вы вообще помните что я писал? В БД вместо точек пишутся упакованные данные (по сути линейная апроксимация). Это позволило еще и урезать объем данных в БД.
G>Мы все еще о записи потока данных в хранилище? Есть подозрение что БЛ, которой нужны данные "вообще за любой промежуток истории" не относится к записи в хранилище, и, скорее всего, будет другими средствами делаться.
G>Тем что DAL проще и не требует поддержки (вообще). Для соответствия формул можешь просто локальные переменные использовать.
Ага DAL проще, зато BL сложнее. Где профит?
G>Нет, я лишь говорю что лишние модели в коде делают его более хрупким.
То что вы их автоматически генерите через t4 не значит что их нет.
Doc>>2) Независимость от ORM и возможность на уровне DAL. Специально подчеркиваю — DAL тут является декоратором для ORM + дополнительные функции + код настройки. G>Еще дальше от цели, так как в подавляющем большинстве случаев ORM не меняется, а лишний код вокруг его только бесцельно усложняет приложение.
1) Главное проигнорировать часть на которую нет ответа (я про
2) Самое забавное что вы делаете почти тоже самое (особенно если сами запросы для повторого использования содержите в классах). Только вот приставка в namespace DAL вас почему-то бесит
Doc>>3) Возможность писать BL не оглядываясь на то, как сделан DAL (равно как и PL). G>Тоже самое дает ORM и IQueryable.
Тут главное верить что везде IQueryable поддерживается одинаково.
G>Цели крайне эфемерны, большинство достигается без отдельного слоя DAL, а прямым использованием ORM.
Дальше обсуждать смысла не вижу. Свои точки зрения мы высказали, убеждать вас задачи у меня не было в принципе, а спор ради спора не интересен.
Здравствуйте, Doc, Вы писали:
Doc>Здравствуйте, gandjustas, Вы писали:
G>>Проблема существует, когда она существует объективно. Doc>Кто там бы против словоблудия?
Переход на личности случает от того что сказать по теме нечего. Лучше не начинать
Doc>Если ORM полностью изолирована от BL в DAL, то назовите причину менять BL?
Изменение требований. Перевод на другую БД скорее всего случается не личному по желанию разработчиков, а потому что существующая не удовлетворяет характеристикам или потому что хочется использовать новые возможности. В обоих случаях одной заменой DAL не обойдешься.
Doc>Вы упорно уходите в сторону — суть в том, что руками меняем, миграцией, генератором ... это все изменения. И причем не явные (надо не забыть вписать, запустить, сгенерить).
Нет, автоматические изменения никогда не принимаются в расчеты, потому что в них ошибиться невозможно.
Вон например переименование свойства в классе при наличии VS это одно изменение, а не столько, сколько обращений к этому свойству. А вот в JS как раз наоборот.
Doc>Опять уходите в сторону. Какая разница что за компы и что ее там делает в это время комп? Главное — данные в любой момент могут потребоваться за любой интервал. Вопрос как доставать? Я уже понял что вы бы или хранили 1 в 1 или в BL везде в формулах учитывали формат данных.
Сначала быр разговор о записи, теперь о доставании данных. Я не могу угадывать какое следующее требование вы придумаете, поэтому предлагаю свернуть разговор. Тем более дополнительные классы моделей не помогут в любом случае.
Doc>>>1) Приемлемую производительность на доступном железе дает только анализ на лету и запись в БД частное облако там не подходит по цене и по постановке задачи заказчиком). G>>Как тут поможет модель, отличая от DTO?
Doc>Вы вообще помните что я писал? В БД вместо точек пишутся упакованные данные (по сути линейная апроксимация). Это позволило еще и урезать объем данных в БД.
Это я понимаю. Также понимаю что структурно выглядит это как IObservable<InputDTO> -> IObservable<OutputDTO>. Так вот эта стрелка и есть BL.
Другой аспект BL: IEnumerable<OutputDTO> -> отчет. Это разные стрелки, реализация одной не обязана зависеть от другой.
Ты же пытаешься насильно выделить в них общие части, прибить это к DAL, а потом героически борешься с возникающими проблемами.
Только вот причина создания такого DAL исключительно религиозная.
Doc>Ага DAL проще, зато BL сложнее. Где профит?
DAL вообще не потребует поддержки, а в БЛ не будет проблем из-за сокрытия функционала.
G>>Нет, я лишь говорю что лишние модели в коде делают его более хрупким. Doc>То что вы их автоматически генерите через t4 не значит что их нет.
Это значит что их не надо поддерживать.
Doc>2) Самое забавное что вы делаете почти тоже самое (особенно если сами запросы для повторого использования содержите в классах). Только вот приставка в namespace DAL вас почему-то бесит
Вообще-то тред начался с проблема о том кому отдавать тот или иной кусок функционала. Я же говорю что не надо отдавать, надо разделение пересмотреть. Делать отдельный DAL слой не имеет смысла при наличии ORM. Причем получение "единого пространства" логики работы приложения позволит выбросить кучу ненужных DTO и преобразований.
Doc>>>3) Возможность писать BL не оглядываясь на то, как сделан DAL (равно как и PL). G>>Тоже самое дает ORM и IQueryable. Doc>Тут главное верить что везде IQueryable поддерживается одинаково.
А причем тут "везде"? Ведь никто не будет просто так меня одну реализацию IQueryable на другую.
Здравствуйте, gandjustas, Вы писали:
Doc>>Если ORM полностью изолирована от BL в DAL, то назовите причину менять BL? G>Изменение требований. Перевод на другую БД скорее всего случается не личному по желанию разработчиков, а потому что существующая не удовлетворяет характеристикам или потому что хочется использовать новые возможности. В обоих случаях одной заменой DAL не обойдешься.
Не вижу явных причин менять BL. Ведь хоть заоптимизируйтесь в DAL под новые возможности нового хранилища. BL просто говорит "сохрани" или "дай" данные, а как там внутри его не волнует. Например, уходим в Azure. Там, те же большие файлы выгоднее хранить не в SQL, а в Azure blob storage. Вот DAL и будет разруливать — запись в sql, а файл в blob (вместо FileSteam как на старом выделенном сервере).
G>Вон например переименование свойства в классе при наличии VS это одно изменение, а не столько, сколько обращений к этому свойству. А вот в JS как раз наоборот.
Т.е. вопрос в автоматизации. Ну тогда и мапить Model на DTO в общем случае можно автоматически. В расчет тоже не берем тогда
G>Сначала быр разговор о записи, теперь о доставании данных. Я не могу угадывать какое следующее требование вы придумаете, поэтому предлагаю свернуть разговор. Тем более дополнительные классы моделей не помогут в любом случае.
Разговор был о решаемой задаче. Вы мне упорно доказываете что не помогут, а у меня после введения этих сущностей ушли проблемы со скоростью и сама база уменьшилась в размерах в разы и как следствие — упала нагрузка на сеть (эти данные еще и по сети ходят).
Doc>>Ага DAL проще, зато BL сложнее. Где профит? G>DAL вообще не потребует поддержки, а в БЛ не будет проблем из-за сокрытия функционала.
Сокрытия какого функционала?
Doc>>2) Самое забавное что вы делаете почти тоже самое (особенно если сами запросы для повторого использования содержите в классах). Только вот приставка в namespace DAL вас почему-то бесит G>Вообще-то тред начался с проблема о том кому отдавать тот или иной кусок функционала. Я же говорю что не надо отдавать, надо разделение пересмотреть. Делать отдельный DAL слой не имеет смысла при наличии ORM. Причем получение "единого пространства" логики работы приложения позволит выбросить кучу ненужных DTO и преобразований.
На этом и остановимся. У нас разные подходы к архитектуре.
Здравствуйте, Doc, Вы писали:
Doc>Здравствуйте, gandjustas, Вы писали:
Doc>>>Если ORM полностью изолирована от BL в DAL, то назовите причину менять BL? G>>Изменение требований. Перевод на другую БД скорее всего случается не личному по желанию разработчиков, а потому что существующая не удовлетворяет характеристикам или потому что хочется использовать новые возможности. В обоих случаях одной заменой DAL не обойдешься.
Doc>Не вижу явных причин менять BL. Ведь хоть заоптимизируйтесь в DAL под новые возможности нового хранилища. BL просто говорит "сохрани" или "дай" данные, а как там внутри его не волнует. Например, уходим в Azure. Там, те же большие файлы выгоднее хранить не в SQL, а в Azure blob storage. Вот DAL и будет разруливать — запись в sql, а файл в blob (вместо FileSteam как на старом выделенном сервере).
В этом случае у тебя уже нет одного ORM, а есть несколько систем, так что наличие DAL может быть оправдано. Только ты уже начинаешь выдумывать кейсы, которых раньше не было.
G>>Вон например переименование свойства в классе при наличии VS это одно изменение, а не столько, сколько обращений к этому свойству. А вот в JS как раз наоборот. Doc>Т.е. вопрос в автоматизации. Ну тогда и мапить Model на DTO в общем случае можно автоматически. В расчет тоже не берем тогда
Если автоматически можно мапить модель на DTO, тогла модль по структуре совпадает с DTO и в ней по сути нет смысла. Иначе надо настраивать маппинг, а это тоже ручные изменения, которые надо делать параллельно с изменением схемы.
G>>Сначала быр разговор о записи, теперь о доставании данных. Я не могу угадывать какое следующее требование вы придумаете, поэтому предлагаю свернуть разговор. Тем более дополнительные классы моделей не помогут в любом случае.
Doc>Разговор был о решаемой задаче.
Она как-то меняется со временем. Я рассматриваю средний случай, ты все время выдумываешь corner cases.
Doc>>>Ага DAL проще, зато BL сложнее. Где профит? G>>DAL вообще не потребует поддержки, а в БЛ не будет проблем из-за сокрытия функционала. Doc>Сокрытия какого функционала?
Который ты скрываешь на основании религиозного убеждения о принадлежности того или иного функционала к конкретному слою.
Doc>Вы мне упорно доказываете что не помогут, а у меня после введения этих сущностей ушли проблемы со скоростью и сама база уменьшилась в размерах в разы и как следствие — упала нагрузка на сеть (эти данные еще и по сети ходят).
Значит ты изначально что-то не так делал.
Попробую угадать. Изначально был код, который мапил некоторый объект (Модель) напрямую в базу.
Но в этом коде было некоторое большое поле, типа файла или большого куска текста. Вокруг такого класса Модели была выстроена логика.
Естественно все запросы были упрятаны в классы Repository и отдавали сразу список Моделей.
Оказалось что оно банально тормозит при выводе списка Моделей на экране, потому что на каждый элемент тянется еще и огромный файл.
Причем просто FileStream не помог бы, потому что Модель тянется полностью.
Появилась идея — вынести файлы в отдельную таблицу в БД, но тогда пришлось бы переписывать \ перемещать методы БЛ, поэтому сделали так что внутри Repository на методах чтения объекты, получаемые EF, мапятся на Модель.
Выделенное курсивом — изначальная проблема. Надо было прямо в UI отдавать IQueryable, а UI делал бы проекцию ровно тех полей, которые нужны для вывода и проблема бы и не появилась.
Здравствуйте, Doc, Вы писали:
IT>>А какое за этим поинтом логическое обоснование? Кроме "IMHO не правильно". Doc>Вот тут в конце сообщения. Doc>http://www.rsdn.ru/forum/design/5052475
Там нет логического обоснования. Там есть примерно такое — хочу абстракцию и фсё. Какие проблемы она решает не указано, кроме не очень большой проблемы совместимости разны SQL, которая решается либо выбором правильного инструмента, либо небольшими хелперами.
Можно я приведу пример логического боснования против разбиения логики приложения на слои? Спасибо.
Разбиение логики приложения на слои приводит к разбиению цельного алгоритма на части и размазыванию его по слоям. Что в свою очередь приводит к значительному увеличению объёма кода, ужудшению восприятия и дополнительному усложнению при его модификации. Как привило, в размазанном по слоям коде BL соостоит более чем наполовину их мусора типа path-through методов. Дополнительные проблемы сюда вносит попытка повторного использования бизнес логики. Здесь ситуация получается с точностью до наоборот. В один и тот же метод вносятся части слабо связанных друг с другом алгоритмов, внутренняя логика метода строится на флажках параметрах или в зависимости от вторичных половых признаков передаваемых в метод объектов. В результате чего очень скоро в процессе модификаций в коде появляются сначала фантомные параметры методов, а затем и сами фантомные методы. Модифицировать такие методы на порядок сложнее по причине их повышенной хрупкости, приходится изучать логику работы всего что их вызывает.
Вот это всё реальные проблемы, которые возникают при разбиении цельного алгоритма на слои. Это было всегда и так и останется навсегда просто потому что за всё надо платить. Но в случае изпользования DAL, как изолятора приложения от работы с прямым SQL, это с лихвой компенсировалось преимуществами такой изоляции. Если же это преимущество у DAL убрать, то от слоёности останутся практически одни недостатки.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, gandjustas, Вы писали:
G>В этом случае у тебя уже нет одного ORM, а есть несколько систем, так что наличие DAL может быть оправдано. Только ты уже начинаешь выдумывать кейсы, которых раньше не было.
Т.е. этот кейс тоже не подходит? А ничего что я с самого начала утверждал, что одна из причин это независимость от ORM и хранилища, и это как раз прямая иллюстрация.
G>Если автоматически можно мапить модель на DTO, тогла модль по структуре совпадает с DTO и в ней по сути нет смысла. Иначе надо настраивать маппинг, а это тоже ручные изменения, которые надо делать параллельно с изменением схемы.
Это от задачи зависит.
Doc>>Разговор был о решаемой задаче. G>Она как-то меняется со временем. Я рассматриваю средний случай, ты все время выдумываешь corner cases.
Шикарно Ну если это выдуманная задача — смысла продолжать нет. Показывать сорцы я точно не буду. Выдуманная так выдуманная.
Doc>>Сокрытия какого функционала? G>Который ты скрываешь на основании религиозного убеждения о принадлежности того или иного функционала к конкретному слою.
И в чем проблема ситуации, когда тонкости ORM и БД скрыты от DAL. Ходим по кругу
G>Значит ты изначально что-то не так делал. G>Попробую угадать.
100% мимо. Более того, ты показал что "чучка не читатель, чукча писатель". Нет там файлов, блобов итд Все работа идет с кучей записей вида date/name/value. Кстати, вынос файлов бы никак не сэкономил бы дисковое пространство (уменьшение размеров БД в этом случае фикция, т.к. ничего не дает, а модель и без этого можно тянуть только с нужными полями).
Извините, но дальше не вижу смысла вести разговор, т.е. надоело повторять одно и тоже и видеть игнор написанного.
Здравствуйте, IT, Вы писали:
IT>Можно я приведу пример логического боснования против разбиения логики приложения на слои? Спасибо.
Сам спросил, сам ответил. Ну ясно дело, ведь приятно поговорить с умным человеком
IT>Разбиение логики приложения на слои приводит к разбиению цельного алгоритма на части и размазыванию его по слоям.
Ух ты, это интересно, что за бизнес-процесс вклчает в себя описание как сохранять документы в БД?
IT> Что в свою очередь приводит к значительному увеличению объёма кода
Ну это как писать. Все что есть в моем DAL было бы в вашем BL (или как угодно назовите). От того, что я перестану использоваться EF в своем классе, у него не появится batch update/delete. Это кусок кода все равно будет в виде extension или просто класса в приложении. OQ так же будут в виде классов — ради из повтороного использования в том же BL.
IT> Дополнительные проблемы сюда вносит попытка повторного использования бизнес логики.
А вот это вообще ваши фантазии. Я нигде не утверждал что BL можно повторно использовать. А вот ту же обретку для EF — легко.
IT> Как привило, в размазанном по слоям коде BL соостоит более чем наполовину их мусора типа path-through методов
Опять неправда ваша.
IT> В один и тот же метод вносятся части слабо связанных друг с другом алгоритмов
"И тут Остапа понесло" "Умение" нарушать SRP вообще никак не связана с разделением по слоям. Ну и все эти ошибочные высказывания приводят вас к странным выводам. Хотя даже не выводам, а просто попытке "навешать всех собак" чтобы выглядело все это страшно.
Здравствуйте, Doc, Вы писали:
IT>>Можно я приведу пример логического боснования против разбиения логики приложения на слои? Спасибо. Doc>Сам спросил, сам ответил. Ну ясно дело, ведь приятно поговорить с умным человеком
Дык. Учись пока я жив.
IT>>Разбиение логики приложения на слои приводит к разбиению цельного алгоритма на части и размазыванию его по слоям. Doc>Ух ты, это интересно, что за бизнес-процесс вклчает в себя описание как сохранять документы в БД?
А почему бы его не включать? Сохранение документа — это часть бизнес процесса. Можно, конечно, эти вещи искусственно разделить и гордится никому не нужными абстракциями, но вообще-то это называется over-architecture.
IT>> Что в свою очередь приводит к значительному увеличению объёма кода Doc>Ну это как писать. Все что есть в моем DAL было бы в вашем BL (или как угодно назовите). От того, что я перестану использоваться EF в своем классе, у него не появится batch update/delete. Это кусок кода все равно будет в виде extension или просто класса в приложении. OQ так же будут в виде классов — ради из повтороного использования в том же BL.
Ты не понял. К увеличению кода приводит размазывание одного алгоритма по слоям. Как минимум тебе понядобится два дополнительных метода (по одному в DAL и BL) и возможно, хотя в твоём случае абсолютно точно, дополнительные сущности типа DTO, выполняющие функции переливания из пустого в порожнее.
IT>> Дополнительные проблемы сюда вносит попытка повторного использования бизнес логики. Doc>А вот это вообще ваши фантазии. Я нигде не утверждал что BL можно повторно использовать. А вот ту же обретку для EF — легко.
Утверждал выше по ветке как аргумент в пользу необходимости DAL. А то, о чём ты говоришь не имеет никакого отношения к слоям. Просто повторно используемые модули пиши хоть обпишись.
IT>> Как привило, в размазанном по слоям коде BL соостоит более чем наполовину их мусора типа path-through методов Doc>Опять неправда ваша.
Правда-правда. Наличие path-through методов говорит о непереусложнённом и эффективном дизайне. Это часть вынужденной платы за слоёность. Если у тебя в BL каждый метод выполняет ещё что-то кроме переброски вызова в DAL, то с гарантией 90% можно утверждать, что этот код не имеет никакого отношения к самой бизнес логики. Естественно, бывает, что в BL инкапсулируется определённая логика. Но таких методов в BL не более 20%. Остальное мусор.
IT>> В один и тот же метод вносятся части слабо связанных друг с другом алгоритмов Doc>"И тут Остапа понесло" "Умение" нарушать SRP вообще никак не связана с разделением по слоям. Ну и все эти ошибочные высказывания приводят вас к странным выводам. Хотя даже не выводам, а просто попытке "навешать всех собак" чтобы выглядело все это страшно.
Уверяю тебя, всё так и есть. Так может не быть только либо в микроскопических проектах для показухи, либо в теории, а мы знаем чем теория отличается от практики.
Doc>Но все равно спасибо, т.к. улыбнуло
Давай сюда код своего проекта, вместе поржём. Уверен, найдётся там и нарушение SRP, и фантомная и хрупкая бизне логика, и переусложнённый дизайн. Хотя о последнем можно сделать вывод и без исходников, просто на основании твоих рассуждений, в которых ты почему-то очень старательно умалчиваешь какие конкретные проблемы решают те или иные твои решения.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Doc, Вы писали:
Doc>Здравствуйте, gandjustas, Вы писали:
G>>В этом случае у тебя уже нет одного ORM, а есть несколько систем, так что наличие DAL может быть оправдано. Только ты уже начинаешь выдумывать кейсы, которых раньше не было.
Doc>Т.е. этот кейс тоже не подходит? А ничего что я с самого начала утверждал, что одна из причин это независимость от ORM и хранилища, и это как раз прямая иллюстрация.
Независимость от ORM не нужна, ORM сам достаточно хорошо абстрагирует от РСУБД и современные ORMы очень мощны. Независимость от какого-то произвольного хранилища — надо смотреть по ситуации.
G>>Если автоматически можно мапить модель на DTO, тогла модль по структуре совпадает с DTO и в ней по сути нет смысла. Иначе надо настраивать маппинг, а это тоже ручные изменения, которые надо делать параллельно с изменением схемы.
Doc>Это от задачи зависит.
Да ну? А как обеспечить автомаппинг двух сущностей если они по структуре достаточно сильно отличаются? А если не отличаются, то зачем две сущности?
Doc>>>Разговор был о решаемой задаче. G>>Она как-то меняется со временем. Я рассматриваю средний случай, ты все время выдумываешь corner cases.
Doc>Шикарно Ну если это выдуманная задача — смысла продолжать нет. Показывать сорцы я точно не буду. Выдуманная так выдуманная.
Разницы нет. Если есть конкретные условия — опиши, если нет — не выдумывай на ходу.
Doc>>>Сокрытия какого функционала? G>>Который ты скрываешь на основании религиозного убеждения о принадлежности того или иного функционала к конкретному слою.
Doc>И в чем проблема ситуации, когда тонкости ORM и БД скрыты от DAL. Ходим по кругу
ORM очень мощен, ни один самописный DAL не покроет и 10% его мощностей. То есть ты сознательно не используешь все возможности инструментов в программе. А что получаешь в замен? Легкость смены DAL? Так это подавляющему большинству не нужно.
G>>Значит ты изначально что-то не так делал. G>>Попробую угадать.
Doc>100% мимо. Более того, ты показал что "чучка не читатель, чукча писатель". Нет там файлов, блобов итд Все работа идет с кучей записей вида date/name/value. Кстати, вынос файлов бы никак не сэкономил бы дисковое пространство (уменьшение размеров БД в этом случае фикция, т.к. ничего не дает, а модель и без этого можно тянуть только с нужными полями).
Ну и что ты с этими date\name\value делаешь? С ними можно сильно по-разному работать. Хранилище у тебя где? SQL? Azure Tables? Какой-нить NoSQL движок?
Doc>Извините, но дальше не вижу смысла вести разговор, т.е. надоело повторять одно и тоже и видеть игнор написанного.
По-моему ты сам начал с абстрактного вопроса, получив ответ, противоречащий твоей религии, начал спорить.
Деталей задачи ты не описал. Так что я все еще нахожусь в той же абстракции, как в начале. Похоливарить на форуме мне не сложно.
Здравствуйте, IT, Вы писали:
IT>А почему бы его не включать? Сохранение документа — это часть бизнес процесса. Можно, конечно, эти вещи искусственно разделить и гордится никому не нужными абстракциями, но вообще-то это называется over-architecture.
А PL тоже включите в бизнес-логику?
IT>Ты не понял. К увеличению кода приводит размазывание одного алгоритма по слоям.
А зачем его размазывать? Я прекрасно обхожусь без этого.
IT>Как минимум тебе понядобится два дополнительных метода (по одному в DAL и BL)
Для чего? Можно пример (псевдокод)?
IT>и возможно, хотя в твоём случае абсолютно точно, дополнительные сущности типа DTO, выполняющие функции переливания из пустого в порожнее.
Обожаю экстрасенсов, как они рассказывают что и как есть "в твоём случае абсолютно точно" DTO в DAL мне далеко не всегда нужны.
IT>Утверждал выше по ветке как аргумент в пользу необходимости DAL.
Можно цитату, не вырванную из контекста, где я говорил о повторном использовании BL.
IT>А то, о чём ты говоришь не имеет никакого отношения к слоям. Просто повторно используемые модули пиши хоть обпишись.
Можно цитату, не вырванную из контекста, где я говорил о что повторное использование это особенность только слоев?
IT>Правда-правда. Наличие path-through методов говорит о непереусложнённом и эффективном дизайне.
Хм... написать что ли в каком-нибудь проекте пару path-through методов? А то у меня их нет, и вы опять мимо. Все обманываетесь и обманываетесь.
IT>Уверяю тебя, всё так и есть. Так может не быть только либо в микроскопических проектах для показухи, либо в теории, а мы знаем чем теория отличается от практики.
IT>Давай сюда код своего проекта, вместе поржём. Уверен, найдётся там и нарушение SRP, и фантомная и хрупкая бизне логика, и переусложнённый дизайн. Хотя о последнем можно сделать вывод и без исходников, просто на основании твоих рассуждений, в которых ты почему-то очень старательно умалчиваешь какие конкретные проблемы решают те или иные твои решения.
Столько выводов не видя кода А вы по фотографии не лечите?
Doc>Повторяю последний раз Doc>1) Независимость от хранилища (сознательно не пишу БД, т.к. есть масса других вариантов и есть задачи где можно выбирать или поддерживать разные) Doc>2) Независимость от ORM и возможность на уровне DAL. Специально подчеркиваю — DAL тут является декоратором для ORM + дополнительные функции + код настройки. Doc>3) Возможность писать BL не оглядываясь на то, как сделан DAL (равно как и PL).
Doc>PS: Цели убедить вас делать такой вариант архитектуры у меня нет. Да и вообще мы ушли от исходного вопроса очень сильно в сторону. Хотя я для себя ответ нашел.
И какой правильный ответ?
К какой области относится QueryObject — к BLL или DAL?
IT>Разбиение логики приложения на слои приводит к разбиению цельного алгоритма на части и размазыванию его по слоям.
Это исходное неверное рассуждение.
Разбиение на слои подразумевает не разбиение алгоритма на части — алгоритм при этом вообще не изменяется.
Разбиение на слои подразумевает абстрагирование от деталей реализации алгоритма, когда реализация осуществляется на более низких уровнях.
Таким образом, разбиение на слои приводит к лучшему выражению и пониманию цельного алгоритма, путем скрытия его реализации.
Здравствуйте, es3000, Вы писали:
E>И какой правильный ответ? E>К какой области относится QueryObject — к BLL или DAL?
Если смотреть на классическую трехзвенку, то в общем случае это DAL (я вот тут всеже прихожу к мысли что Repository+Specification тут правильнее выглядят, а QO уж слишком много хочет знать).
А если со стороны Onion — однозначно Infrastructure.DataAccess
Здравствуйте, Doc, Вы писали:
E>>И какой правильный ответ? E>>К какой области относится QueryObject — к BLL или DAL? Doc>Если смотреть на классическую трехзвенку, то в общем случае это DAL (я вот тут всеже прихожу к мысли что Repository+Specification тут правильнее выглядят, а QO уж слишком много хочет знать). Doc>А если со стороны Onion — однозначно Infrastructure.DataAccess
А к чему относится GetFavouriteCustomersQuery, FindDelayedOrdersQuery, GetTopPriorityOrders?
Здравствуйте, es3000, Вы писали:
IT>>Разбиение логики приложения на слои приводит к разбиению цельного алгоритма на части и размазыванию его по слоям.
E>Это исходное неверное рассуждение. E>Разбиение на слои подразумевает не разбиение алгоритма на части — алгоритм при этом вообще не изменяется. E>Разбиение на слои подразумевает абстрагирование от деталей реализации алгоритма, когда реализация осуществляется на более низких уровнях. E>Таким образом, разбиение на слои приводит к лучшему выражению и пониманию цельного алгоритма, путем скрытия его реализации.
Согласен, но это теория. На практике, к сожалению, получается именно так как Игорь написал
Пример: обработать все просроченные заказы. На практике просроченные заказы эффективнее искать с помощью sql в базе (настолько эффективнее, что альтернативы даже не рассматриваются). Поэтому логика поиска просроченных заказов уезжает в DAL.
QueryObject пытается решить эту проблему. Он говорит, что вот я весь из себя DAL, я знаю все про SQL, но я не DAL, я BL. Мне приходится знать про SQL потому что мои нструменты не позволяют эффективно получать данные из базы без знания SQL.
С приходом LINQ ситуация существенно изменилась (я обожаю этот инструмент). Теперь запросы к базе можно писать на том же языке (ну почти) что и всю остальную логику. Это позволяет во многих случаях заменить QueryObject на прямой select в бизнесс методе. Потому что скрывать "select o.q, o.w, o.e from orders o where o.user_id = :user" строго рекомендуется (и это простйший пример), а вот from o in Orders where o.UserId = userId уже вполне вписывается в BL.
Но, даже во времена linq QueryObject не умер. У него поменялись обязанности. Он стал тру BL (без вариантов).
Вот серия статей про подход Ayende. Мне этот подход понравился. Я его лично не использовал, но что-то в нем есть.
public override void Execute()
{
var origin = Session.Load<Location>(OriginCode);
var destination = Session.Load<Location>(DestinationCode);
var trackingId = Query(new NextTrackingIdQuery());
var routeSpecification = new RouteSpecification(origin, destination, ArrivalDeadline);
var cargo = new Cargo(trackingId, routeSpecification);
Session.Save(cargo);
Result = trackingId;
}
Этот подход нужно рассматривать в комплексе. Т.е. не вырывать Query из контекста. Весь контекст это Query, Command, Task и, главное, ифраструктура, которая позволяет это все удобно использовать.
Здравствуйте, Aikin, Вы писали:
A>А к чему относится GetFavouriteCustomersQuery, FindDelayedOrdersQuery, GetTopPriorityOrders?
Я так понимаю, что (учитывая что вы процитировали), вы хотите поспорить и сказать что в них лежит бизнес-логика? Они только знаю что и откуда взять и (если форматы БД и объекта не совпадают), то как выдать. Ну и опять же, учитывайте что все эти *Query много чего знают про хранилище, чего BLL в принципе знать не должен.
Здравствуйте, Doc, Вы писали:
A>>А к чему относится GetFavouriteCustomersQuery, FindDelayedOrdersQuery, GetTopPriorityOrders? Doc>Я так понимаю, что (учитывая что вы процитировали), вы хотите поспорить и сказать что в них лежит бизнес-логика? Они только знаю что и откуда взять и (если форматы БД и объекта не совпадают), то как выдать.
Я не хочу навязывать своего мнения. Я хочу чтобы вы задумались о роли QueryObject
Знание о том кто такой фаворитный кастомер это что? Знание о том что такое просроченный заказ? Что такое заказ высшего приоритета?
Не заставляет задуматься?
А так: фаворитный заказ -- это заказ сделанный важныйм заказчиком (+ еще определение) на сумму свыше 1000$ с доставкой в другой конец страны (+ определение)
Doc>Ну и опять же, учитывайте что все эти *Query много чего знают про хранилище, чего BLL в принципе знать не должен.
Аргумент который можно спокойно инвертировать ничего не стоит: Query много чего знают про BLL, чего DAL в принципе знать не должен
Здравствуйте, Aikin, Вы писали:
A>Я не хочу навязывать своего мнения. Я хочу чтобы вы задумались о роли QueryObject
А я уже высказал его. Вы же процирировали мое высказывание, что QueryObject сильно много хочет знать.
Но по моей логике, но больше связан с DAL, т.к. при изменении DAL придется менять
A>Не заставляет задуматься? A>А так: фаворитный заказ -- это заказ сделанный важныйм заказчиком (+ еще определение) на сумму свыше 1000$ с доставкой в другой конец страны (+ определение)
Я видел ваше сообщение, где вы сказали что QO как бы и в DAL и как бы в BLL. Собственно, с этого и начался разговор. Но поскольку в проекте нельзя быть немножко беременным, то надо куда-то его отнести. В данном случае IMHO заявка на DAL сильнее, т.к. QO использует специфику про которую BLL не в курсе вообще (формат хранения данных, спец. методы обращения к ним итд).
Doc>>Ну и опять же, учитывайте что все эти *Query много чего знают про хранилище, чего BLL в принципе знать не должен. A>Аргумент который можно спокойно инвертировать ничего не стоит: Query много чего знают про BLL, чего DAL в принципе знать не должен
Вот поэтому я и обратил внимание на Specification. Т.к. там для конкретного DAL будут определены некоторые базовые операции (искать по дате, искать по мин. цене и т.д.), которые уже BLL объединяет в выражения, представляющие саму BL (грубый пример: лучшее предложение = искать по дате "сегодня" && по мин. цене).
Тот же "фаворитный заказ" прекрасно будет составлен из 3 спецификации, каждая из которых не несет какой-либо BL: что-то вроде IsVIP(user) && PriceMoreThan(order, minPrice) && LongDistanse(source, dest, minDistance)
Здравствуйте, Doc, Вы писали:
Doc>Я видел ваше сообщение, где вы сказали что QO как бы и в DAL и как бы в BLL. Собственно, с этого и начался разговор. Но поскольку в проекте нельзя быть немножко беременным, то надо куда-то его отнести. В данном случае IMHO заявка на DAL сильнее, т.к. QO использует специфику про которую BLL не в курсе вообще (формат хранения данных, спец. методы обращения к ним итд).
Можно. Все можно. На практике можно BL писать в DAL, а sql использовать в PL. GodClass тоже имеет право на существование. Например для однразового приложения.
Doc>Вот поэтому я и обратил внимание на Specification. Т.к. там для конкретного DAL будут определены некоторые базовые операции (искать по дате, искать по мин. цене и т.д.), которые уже BLL объединяет в выражения, представляющие саму BL (грубый пример: лучшее предложение = искать по дате "сегодня" && по мин. цене).
Я не готов обсуждать эту ветку без четкого определения Specification и QueryObject. Насколько я знаю теорию, эти два термина ввели разные авторы для разных классификаций.
Doc>Тот же "фаворитный заказ" прекрасно будет составлен из 3 спецификации, каждая из которых не несет какой-либо BL: что-то вроде IsVIP(user) && PriceMoreThan(order, minPrice) && LongDistanse(source, dest, minDistance)
Размазывание логики по классам. Причем от проблемы мы не избавились. IsVIP -- юзер, который потратил больше 10000$ за летние месяцы прошлого года. Или IsVIP -- юзер которыйв прошлом году привел больше 20 рефералов. LongDistanse тоже не вариант, если критерий -- разные, не соседние области (графства, субъекты федерации).
Да, можно и дальше разбивать спецификации на части, но смысл. Для "чистоты кода"? Извините, но это не аргумент.
Doc>А я уже высказал его. Вы же процирировали мое высказывание, что QueryObject сильно много хочет знать. Doc>Но по моей логике, но больше связан с DAL, т.к. при изменении DAL придется менять
Да, я на ваше мнение и ответил. Ответил "не так все просто".
Не закончил мысль.
A>Да, можно и дальше разбивать спецификации на части, но смысл. Для "чистоты кода"? Извините, но это не аргумент.
А можно сказать,что QueryObject -- "немножко беременный", т.е. относится и к DAL и BL и записать все в одном месте.
Здравствуйте, Doc, Вы писали:
IT>>А почему бы его не включать? Сохранение документа — это часть бизнес процесса. Можно, конечно, эти вещи искусственно разделить и гордится никому не нужными абстракциями, но вообще-то это называется over-architecture. Doc>А PL тоже включите в бизнес-логику?
Для PL придумано семейство паттернов MVC.
IT>>Ты не понял. К увеличению кода приводит размазывание одного алгоритма по слоям. Doc>А зачем его размазывать? Я прекрасно обхожусь без этого.
Это как? Слои есть, функционал есть, а размазывание его по слоям нет? Тогда зачем тебе слои?
IT>>Как минимум тебе понядобится два дополнительных метода (по одному в DAL и BL) Doc>Для чего? Можно пример (псевдокод)?
UI:
...
var customers = MyBusinessLogic.GetCustomers();
...
IT>>и возможно, хотя в твоём случае абсолютно точно, дополнительные сущности типа DTO, выполняющие функции переливания из пустого в порожнее. Doc>Обожаю экстрасенсов, как они рассказывают что и как есть "в твоём случае абсолютно точно" DTO в DAL мне далеко не всегда нужны.
Т.е. мы только чуть-чуть беременны? Понятно.
IT>>Утверждал выше по ветке как аргумент в пользу необходимости DAL. Doc>Можно цитату, не вырванную из контекста, где я говорил о повторном использовании BL. IT>>А то, о чём ты говоришь не имеет никакого отношения к слоям. Просто повторно используемые модули пиши хоть обпишись. Doc>Можно цитату, не вырванную из контекста, где я говорил о что повторное использование это особенность только слоев?
Посмотри выше по ветке.
IT>>Правда-правда. Наличие path-through методов говорит о непереусложнённом и эффективном дизайне. Doc>Хм... написать что ли в каком-нибудь проекте пару path-through методов? А то у меня их нет, и вы опять мимо. Все обманываетесь и обманываетесь.
У тебя их нет, потому что ты напихал в свой код ещё какого-нибудь дополнительного мусора, не имеющего отношения к бизнес логике.
IT>>Давай сюда код своего проекта, вместе поржём. Уверен, найдётся там и нарушение SRP, и фантомная и хрупкая бизне логика, и переусложнённый дизайн. Хотя о последнем можно сделать вывод и без исходников, просто на основании твоих рассуждений, в которых ты почему-то очень старательно умалчиваешь какие конкретные проблемы решают те или иные твои решения. Doc>Столько выводов не видя кода А вы по фотографии не лечите?
Так давай его сюда, не стесняйся.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, es3000, Вы писали:
IT>>Разбиение логики приложения на слои приводит к разбиению цельного алгоритма на части и размазыванию его по слоям. E>Это исходное неверное рассуждение.
Видимо всё же это исходное непонятое рассуждение.
E>Разбиение на слои подразумевает не разбиение алгоритма на части — алгоритм при этом вообще не изменяется.
Может и не меняется, но расслаивается, т.е. разбивается на части.
E>Разбиение на слои подразумевает абстрагирование от деталей реализации алгоритма, когда реализация осуществляется на более низких уровнях.
Зачем мне абстрагироваться от деталей, которых нет?
E>Таким образом, разбиение на слои приводит к лучшему выражению и пониманию цельного алгоритма, путем скрытия его реализации.
Относительно к нашей дискуссии, это справедливо если в DAL используется прямой SQL. Если используется Linq, то расслоение не даёт никаких выгод, я вот все проблемы расслоения мы получаем автоматически.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Aikin, Вы писали:
A>Можно. Все можно. На практике можно BL писать в DAL, а sql использовать в PL. GodClass тоже имеет право на существование. Например для однразового приложения.
... или для проверки какой-нибудь идеи итд Но я о продакшене. А там такое поддерживать как-то не хочется.
A>Я не готов обсуждать эту ветку без четкого определения Specification и QueryObject. Насколько я знаю теорию, эти два термина ввели разные авторы для разных классификаций.
Давайте ваш вариант определения.
A>Да, можно и дальше разбивать спецификации на части, но смысл. Для "чистоты кода"? Извините, но это не аргумент.
На мой взгляд нет тут размазывания логики. Тогда и +-/* то тоже размазывание логики. Под IsVIP я как-то про статус подумал. Согласен, вы говорили про $1000, тогда что-то вроде IsUserSummary(user) > 1000. Но я думаю вы идею поняли.
Насчет размывания, тоже не согласен. Спецификации по сути это небольшие операции, которые знают где взять данные. Незнаю, ясно ли выражусь, но если абстрагироваться, то это своего рода маппинг бизнес-объектов на хранилище. Т.е. BL используя ту или иную спецификацию говорит что "дай юзера", "дай цену не меньше N" и т.д. Т.е. самой BL в отдельном "дай" нет, но спецификация знает откуда взять и их можно логически объединять (вот это уже на BL уровне).
A>Да, я на ваше мнение и ответил. Ответил "не так все просто".
Здравствуйте, Aikin, Вы писали:
A>>Да, можно и дальше разбивать спецификации на части, но смысл. Для "чистоты кода"? Извините, но это не аргумент. A>А можно сказать,что QueryObject -- "немножко беременный", т.е. относится и к DAL и BL и записать все в одном месте.
Здравствуйте, Doc, Вы писали:
A>>Да, я на ваше мнение и ответил. Ответил "не так все просто". Doc>Было бы просто, я бы не спрашивал
A>>Да, можно и дальше разбивать спецификации на части, но смысл. Для "чистоты кода"? Извините, но это не аргумент.
Doc>На мой взгляд нет тут размазывания логики. Тогда и +-/* то тоже размазывание логики. Под IsVIP я как-то про статус подумал. Согласен, вы говорили про $1000, тогда что-то вроде IsUserSummary(user) > 1000. Но я думаю вы идею поняли.
Конечно, я понимаю идею. Думаю вы тоже понимаете, что я специально закручиваю определение Вип заказа
Doc>Насчет размывания, тоже не согласен. Спецификации по сути это небольшие операции, которые знают где взять данные. Незнаю, ясно ли выражусь, но если абстрагироваться, то это своего рода маппинг бизнес-объектов на хранилище. Т.е. BL используя ту или иную спецификацию говорит что "дай юзера", "дай цену не меньше N" и т.д. Т.е. самой BL в отдельном "дай" нет, но спецификация знает откуда взять и их можно логически объединять (вот это уже на BL уровне).
IsVIP -- это не [только] обращение к данным. Вот "дай юзера", "дай цену не меньше N" -- это обращение. Но чтобы такими мелкими спецификациями было удобно удобно пользоватьсяих должно быть очень-очень много. Вот только возникает вопрос зачем тратить на них время если есть linq, который и удобнее и его не нужно руками создавать.
A>>Можно. Все можно. На практике можно BL писать в DAL, а sql использовать в PL. GodClass тоже имеет право на существование. Например для однразового приложения. Doc>... или для проверки какой-нибудь идеи итд Но я о продакшене. А там такое поддерживать как-то не хочется.
У меня в продакшене пару утилит написанных в стиле GodClass. Так же у меня есть страницы диагностики, которые бы я тоже не задумываясь написал бы в виде GodClass, но, блин, архитектура не позволяет (ORM + ASP MVC), глупо от них отказываться. Но если бы их не было, то я бы не задумывась из PL вызвал пару самописных SQL.
Я не могу четко сформулировать когда я придерживаюсь архитектурных принципов, а когда нет. Но одно я знаю точно: любое решение это компромис между простотой и гибкостью. И когда гибкоть не нужна, то я предпочитаю прототу (простота, кстати, термин относительный). Для страниц диагностики, которые используеют только программисты гибкость не нужна.
Здравствуйте, Aikin, Вы писали:
A>IsVIP -- это не [только] обращение к данным. Вот "дай юзера", "дай цену не меньше N" -- это обращение. Но чтобы такими мелкими спецификациями было удобно удобно пользоватьсяих должно быть очень-очень много. Вот только возникает вопрос зачем тратить на них время если есть linq, который и удобнее и его не нужно руками создавать.
Их количество зависит от задачи. Что-то мне подсказывает что будет максимально ~3n (где n число свойств в хранимых моделях BL). Но на практике такое встречается редко. Возвращаясь к VIP, я понимаю что его определение можно развивать и оно даже может изменяться со времением, но на определенном этапе оно конечно. А значит можно реальзовать, оттестировать через UT и добавлять уже потом по мере изменения ТЗ. Но да — теоретически (т.к. не сталкивался) в некоторых задачах число спеков может быть больше и там надо подумать, как делать.
Кстати, ну и такой подход хорош если даже сама BL не знает конкретного запроса (юзер может набрать фильтры для сортировки таблицы или ввести только часть параметров запроса и т.д.).
Здравствуйте, Doc, Вы писали:
Doc>Их количество зависит от задачи. Что-то мне подсказывает что будет максимально ~3n (где n число свойств в хранимых моделях BL). Но на практике такое встречается редко.
На практике, таких спецификаций делают ровно столько сколько нужно сейчас и надеются, что потом добавят нужные. Но вот когда это потом приходит, вместо того, чтобы делать "правильно" пишут бизнесс логику прямо в спецификации.
Вот это практика.
Doc>Возвращаясь к VIP, я понимаю что его определение можно развивать и оно даже может изменяться со времением, но на определенном этапе оно конечно. А значит можно реальзовать, оттестировать через UT и добавлять уже потом по мере изменения ТЗ. Но да — теоретически (т.к. не сталкивался) в некоторых задачах число спеков может быть больше и там надо подумать, как делать.
Это не будет работать в реальной жизни. В реальной жизни либо у тебя есть "конструктор" (спеки на все случаи жизни) и ты из них конструируешь логику, либо ты забиваешь на "правильность" (либо ты пипец какой ответственный)
Кстати, как-то мы от QueryObject ушил к спецификациям, хотя, ИХМО, это один хрен.
Doc>Кстати, ну и такой подход хорош если даже сама BL не знает конкретного запроса (юзер может набрать фильтры для сортировки таблицы или ввести только часть параметров запроса и т.д.).
Это уже совсем другая задача.
Здравствуйте, Doc, Вы писали:
A>>>Да, можно и дальше разбивать спецификации на части, но смысл. Для "чистоты кода"? Извините, но это не аргумент. A>>А можно сказать,что QueryObject -- "немножко беременный", т.е. относится и к DAL и BL и записать все в одном месте.
Doc>В Infrastructure?
Неа, инфраструктура ничего не должна знать ни про модель данныз ни про бизнесс логику, ни про остальный application specific вещи. Теоретически, инфраструктуру можно перенести 1в1 в другой проект с совершенно другой моделью данных.
Здравствуйте, Aikin, Вы писали:
A>На практике, таких спецификаций делают ровно столько сколько нужно сейчас и надеются, что потом добавят нужные. Но вот когда это потом приходит, вместо того, чтобы делать "правильно" пишут бизнесс логику прямо в спецификации.
Я пишу только нужные спеки. Потом же добавляю новые — в спеки. А за запись в BL я бы по рукам стучал.
A>Это не будет работать в реальной жизни. В реальной жизни либо у тебя есть "конструктор" (спеки на все случаи жизни) и ты из них конструируешь логику, либо ты забиваешь на "правильность" (либо ты пипец какой ответственный)
Вот честно, ну не вижу проблемы добавить Spec или QO для запроса новых данных. А что кому-то лень — это их проблема, а не шаблона.
Здравствуйте, Aikin, Вы писали:
A>Неа, инфраструктура ничего не должна знать ни про модель данныз ни про бизнесс логику, ни про остальный application specific вещи. Теоретически, инфраструктуру можно перенести 1в1 в другой проект с совершенно другой моделью данных.
Ну тогда где вы разместите QO? (по теории и реально)
Здравствуйте, Doc, Вы писали:
A>>Неа, инфраструктура ничего не должна знать ни про модель данныз ни про бизнесс логику, ни про остальный application specific вещи. Теоретически, инфраструктуру можно перенести 1в1 в другой проект с совершенно другой моделью данных.
Doc>Ну тогда где вы разместите QO? (по теории и реально)
По теории (моей): это однозначно BL. То что он знает SQL -- это от недостатков инструментов. Если заменить SQL на linq, то у него вообще никаких не BL знаний не останется.
На практике:
за мою практику не написал ни одного QueryObject, как-то не было необходимости. В до-linq времена была DAL с методами GetAllFavouriteOrders().
Если бы писал, то поместил бы рядом с BL.
Здравствуйте, Doc, Вы писали:
A>>Это не будет работать в реальной жизни. В реальной жизни либо у тебя есть "конструктор" (спеки на все случаи жизни) и ты из них конструируешь логику, либо ты забиваешь на "правильность" (либо ты пипец какой ответственный)
Doc>Вот честно, ну не вижу проблемы добавить Spec или QO для запроса новых данных. А что кому-то лень — это их проблема, а не шаблона.
Вот реальная ситуация:
2 недели до релиза, все в запарке, фиксят баги, допиливают функционал.
Заказчик обнаруживает, что фаворитный заказы считаются не так как он ожидал (а так как прочитали программисты).
Есть GetFavouriteQuery одна простая спецификация (OrderTotal>1000).
К заказу "заказ на сумму свыше 1000" нужно добавить "от клиента, который за год заказал на сумму свыше 10000" и еще всякую хрень.
Вопрос не в лени, а в общем видении: "я не знал, что в спеку нельзя добавлять BL"; "блин, да что тогда НЕ бизнесс логика, это же простой запрос", до банальной нехватки времени.
P.S. И я еще не говорю про ифраструктуру, которая берет две спецификации и объединяет в один запрос. У вас такой код есть? Для чистого SQL, для linq все просто. Но для linq сами спецификации (в том виде как их описываете вы) не нужны.
Здравствуйте, Aikin, Вы писали:
Doc>>Ну тогда где вы разместите QO? (по теории и реально) A>По теории (моей): это однозначно BL. То что он знает SQL -- это от недостатков инструментов. Если заменить SQL на linq, то у него вообще никаких не BL знаний не останется.
Хорошо, берем пример: движок сайта блога, который может сохранить статьи или в XML файлы или в одну из доступных СУБД. Как быть с DAL-зависимыми LINQ командами. В частности — поиск текста по маске. Для Linq и СУБД это разный код. Как поступите? Повесите на BLL зависимость от LINQ2SQL?
Здравствуйте, Aikin, Вы писали:
A>P.S. И я еще не говорю про ифраструктуру, которая берет две спецификации и объединяет в один запрос. У вас такой код есть? Для чистого SQL, для linq все просто. Но для linq сами спецификации (в том виде как их описываете вы) не нужны.
Стоп, у вас есть Infra где спеки (что вы отнесли как я понял к BL) объединяются в один запрос. А как же утверждение что Infra должна переноситься из проекта в проект.
Здравствуйте, Doc, Вы писали:
Doc>Как быть с DAL-зависимыми LINQ командами. В частности — поиск текста по маске. Для Linq и СУБД это разный код. Как поступите? Повесите на BLL зависимость от LINQ2SQL?
Пусть linq провайдеры задумываются как это реализовать. Вещи типа where entry.Text.Contains("текст") || entry.Text.StartsWith("Блог") должны быть реализованы у всех провайдеров.
Если какая-то конструкция не реализована, то, например, в BLToolkit можно расширить linq с помощью экстеншен методов. Сделать например: entry.Text.Like("%dffd%fdf%").
Этот код будет кодом инфраструктуры, так как не завязан на логику приложения.
Если ОРМ не позволяет, то приходится искать обходные пути. Вплоть до загрязнения бизнесс логики "лишним" кодом.
Кстати, "поиск текста по маске" это не бизнесс логика. Можно поспорить, но в моем понимании это не BL. Вот поиск сообщения по фразе, это вполне бизнесс логика. Потому как при поиске сообщения мы должны искать и в тексте, и в названии, и в тэгах, и, возможно, в анонсах, не говоря уже о том, что релевантность сообщения у которого образец найден в названии или тегах больше чем у сообщении с образцом в тексте.
Здравствуйте, Doc, Вы писали:
A>>P.S. И я еще не говорю про ифраструктуру, которая берет две спецификации и объединяет в один запрос. У вас такой код есть? Для чистого SQL, для linq все просто. Но для linq сами спецификации (в том виде как их описываете вы) не нужны. Doc>Стоп, у вас есть Infra где спеки (что вы отнесли как я понял к BL) объединяются в один запрос. А как же утверждение что Infra должна переноситься из проекта в проект.
Чтобы было что переносить это что-то нужно сначала написать или найти. У меня такой задачи не стояло, вот и нет такого кода в инфраструктуре.
Здравствуйте, Aikin, Вы писали:
A>Пусть linq провайдеры задумываются как это реализовать.
Они и задумались и реализовали это в разных методах.
A>Если какая-то конструкция не реализована, то, например, в BLToolkit можно расширить linq с помощью экстеншен методов. Сделать например: entry.Text.Like("%dffd%fdf%").
Это даст возможность искать по паттерну и в СУБД и d XML?
A>Если ОРМ не позволяет, то приходится искать обходные пути. Вплоть до загрязнения бизнесс логики "лишним" кодом.
Тогда BL будет жестко подсажен на LINQ2SQL.
A>Кстати, "поиск текста по маске" это не бизнесс логика. Можно поспорить, но в моем понимании это не BL. Вот поиск сообщения по фразе, это вполне бизнесс логика. Потому как при поиске сообщения мы должны искать и в тексте, и в названии, и в тэгах, и, возможно, в анонсах, не говоря уже о том, что релевантность сообщения у которого образец найден в названии или тегах больше чем у сообщении с образцом в тексте.
Мы одинаково понимаем поиск по маске? Например, я хочу найти строку "some user input text — string", но с условием что в БД разделителями вместо пробелов могут быть -_ или [tab] а так же переносы строки.
Здравствуйте, Doc, Вы писали:
Doc>Они и задумались и реализовали это в разных методах. Doc>Это даст возможность искать по паттерну и в СУБД и d XML?
А вон оно что. Я не хочу обсуждать теоретическую возможность смены linq провайдера, а тем более хранилища.
Тем более, что в первом случае компилятор поможет писправить названия, а во втором замена провайдера не самая большая проблема.
Doc>Тогда BL будет жестко подсажен на LINQ2SQL.
А вас не смущает, что BL жестко посажен практически на все кроме PL?
A>>Кстати, "поиск текста по маске" это не бизнесс логика. Можно поспорить, но в моем понимании это не BL. Вот поиск сообщения по фразе, это вполне бизнесс логика. Потому как при поиске сообщения мы должны искать и в тексте, и в названии, и в тэгах, и, возможно, в анонсах, не говоря уже о том, что релевантность сообщения у которого образец найден в названии или тегах больше чем у сообщении с образцом в тексте.
Doc>Мы одинаково понимаем поиск по маске? Например, я хочу найти строку "some user input text — string", но с условием что в БД разделителями вместо пробелов могут быть -_ или [tab] а так же переносы строки.
Возможно я не понимаю что такое "поиск по маске". В моем это like-запросы.
Но это не важно как мы понимаем алгоритм поиска. Важно, что это алгоритм, а не бизнесс логика.
Здравствуйте, Aikin, Вы писали:
A>А вон оно что. Я не хочу обсуждать теоретическую возможность смены linq провайдера, а тем более хранилища. A>Тем более, что в первом случае компилятор поможет писправить названия, а во втором замена провайдера не самая большая проблема.
Тогда есть смысл завершить разговор. Вы просто так откинули проекты, где смена хранилища нормальное явление. В частности те же движки блогов и ряд сайтов, которым не нужны такие фишки SQL как JOIN. Они вполне могут хранить данные в XML, различных SQL, Azure Tables. У меня например блог на таком — BlogEngine.NET. Есть такие бизнес-сайты. Причем это зависит не от нагрузки, а именно от задач.
Хотя если вы десктоп разработчик и не разу с таким не сталкивались, то для вас да — смена хранилища только в теории.
Doc>>Тогда BL будет жестко подсажен на LINQ2SQL. A>А вас не смущает, что BL жестко посажен практически на все кроме PL?
Не на все. Я предпочитаю чтобы BL зависела от интерфейсов, а не от реализаций.
A>Возможно я не понимаю что такое "поиск по маске". В моем это like-запросы. A>Но это не важно как мы понимаем алгоритм поиска. Важно, что это алгоритм, а не бизнесс логика.
Хм.. если это вытекает из требований процесса заказчика, то я все же не соглашусь с вами.
Здравствуйте, Doc, Вы писали:
Doc>В частности те же движки блогов и ряд сайтов, которым не нужны такие фишки SQL как JOIN. Они вполне могут хранить данные в XML, различных SQL, Azure Tables. У меня например блог на таком — BlogEngine.NET.
Кстати, по поводу таких движков. Ковырялся как-то с вот такой викой несколько лет назад. У неё как раз отдельный слой для хранилищ. Запутанность кода невероятная не смотря на относительно примитивные запросы, которые там используются. Переписывание этого кода на тот же Linq от BLToolkit автоматически, ещё раз с большой буквы, АВТОМАТИЧЕСКИ, дало бы возможность поддерживать сразу 12! баз данных, из которых три с половиной embedded. Т.е. надобность ва всяких XML отпадает за ненадобностью.
На тот момент кроме файлового хранилища поддерживалось ещё хранилище для MSSQL. Ради интереса глянул на этот проект опять. Всё как было так и осталось. Количество хранилищ не возросло, что говорит о многом. Например, о том, что развивать проект и одновременно поддерживать множество форматов хранилиш является весьма сложной задачей и выглядит это всё как обыкновенная архитектурная ошибка.
Теперь возьмём тот же BlogEngine.NET. Кроме XML хранилища там поддерживается 4 БД, что в общем-то очень не плохо. Хотя, почти уверен, что это всё далось ребятам с большим трудом. А могло бы быть всё гораздо проще при гораздо большем выборе БД.
Теперь вернёмся к ScrewTurn Wiki. Довольно заметно, что эта штука работает не очень быстро. Да и BlogEngine.NET в твоём блоге тоже заметно подтормаживает на тегах. И тут дело не только в XML. При использовании таких хранилищ разработчик самым естественным образом стремится по минимуму изменять их API. Лучше сделать несколько запросов вместо одного, лучше запросить больше данных, а потом отфильтровать в памяти лишнее, лучше много простых и незамысловатых вызовов, чем один оптимальный запрос в БД. В результате горы непонятно что делающего кода и тормоза приложения как прямое следствие неправильно выбранной архитектуры приложения.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT> Кстати, по поводу таких движков.
Интересно. Тем не менее это не отменяет задачи писать такие (поддерживающие разные хранилища) в веб, и как следует из вашего рассказа, с правильной и понятной архитектурой. В вашем случае если бы код не был запутан, то замена на BLToolkit прошла бы очень просто.
IT> При использовании таких хранилищ разработчик самым естественным образом стремится по минимуму изменять их API. Лучше сделать несколько запросов вместо одного, лучше запросить больше данных, а потом отфильтровать в памяти лишнее, лучше много простых и незамысловатых вызовов, чем один оптимальный запрос в БД
Это отчасти зависит от архитектуры самого приложения. В частности, если правильно созданы QueryObject, то можно сделать их варианты оптимальные под конкретные хранилища и не затрагивать изменениями BL.
Здравствуйте, Doc, Вы писали:
Doc>Это отчасти зависит от архитектуры самого приложения. В частности, если правильно созданы QueryObject, то можно сделать их варианты оптимальные под конкретные хранилища и не затрагивать изменениями BL.
Я боюсь даже представить инфраструктуру, которая такое поддерживает.
Интерфейс IFavouriteOrdersQuery, конкретный экземпляр которого должна создавать некая фабрика.
var favOrdersQuery = factory.Get<IFavouriteOrdersQuery)();
favOrdersQuery.Param1 = 12323;
favOrdersQuery.Param2 = "dsdsd";
var favOrders = db.Execte(favOrdersQuery); // или favOrdersQuery.Execute(), на ваше усмотрение
У вас есть мысли как сделать использование проще? Представьте, что пришел таск изменить эту логику. Например, добавить параметр param3.
А теперь сравните объем работы, если у нас вместо IFavouriteOrdersQuery linq запрос.
Я за все свое время работы поучаствовал в нескольких сменах хранилища и даже в смене типа хранилища.
Меняли DB2 на DB2, но на мэйнфрэйме (проект по распилу бабла жирного заказчика). Затраты никого не интересовали (как и то, что современный сервер порвет мэйнфрэйм).
Меняли MSSQL на Оракл, SQLite на Oracle XE (требование заказчика). Ничего особо страшного не произошло. В рабочем порядке мигрировали.
Замена noSql базы на Оракл (7 лет назад), потому что первая не справлялась с нагрузками. Это было больно, согласен. Но мы сделали это, за две недели. Были интерфейсы для DAL. Но они тоже менялись потому как модель хранения уж очень разная.
Весь мой опыт говорит, что не нужно изначально затачиваться на супер гибкость. Придет время меняться -- поменяем. Даже несмотря на то, что все это было до-linq и миграция проходила намного сложнее.
Doc>Вы просто так откинули проекты, где смена хранилища нормальное явление. В частности те же движки блогов и ряд сайтов, которым не нужны такие фишки SQL как JOIN. Они вполне могут хранить данные в XML, различных SQL, Azure Tables.
Про последствия чрезмерной гибкости отлично написал Игорь (IT). Хотя у меня тоже есть свои примеры.
Я хочу вот что сказать. Проектов для которых "смена хранилища нормальное явление" очень-очень мало. В основном это всевозможные движки. И бизнесс задача тут охватить как можно большую аудиторию. Но, писать провайдера для экзотических случаев никто не будет. Экономически не выгодно. Тем более, что во многих языках уже есть готовые.
Doc>Причем это зависит не от нагрузки, а именно от задач.
Вот про это я хочу послушать.
Doc>Хотя если вы десктоп разработчик и не разу с таким не сталкивались, то для вас да — смена хранилища только в теории.
Померяемся опытом? Что-то мне говорит, что я победю
Здравствуйте, Aikin, Вы писали:
Doc>>Причем это зависит не от нагрузки, а именно от задач. A>Вот про это я хочу послушать.
Ну а я привел примеры.
A>Померяемся опытом? Что-то мне говорит, что я победю
Давайте, только разработайте формулу для подсчета опыта с учетом разных технологий, часов за ними проведенных, рейтингов и кармах на профильных форумах, всяких статусов там ... А если серьезно, я еще в пузомерки не играл. Считайте что вы победили в ней за неявкой соперника.
Здравствуйте, Doc, Вы писали:
Doc>Это отчасти зависит от архитектуры самого приложения. В частности, если правильно созданы QueryObject, то можно сделать их варианты оптимальные под конкретные хранилища и не затрагивать изменениями BL.
К сожалению, только в теории.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Doc, Вы писали:
A>>У вас есть мысли как сделать использование проще?
Doc>Первое что пришло в голову — просто грузить классы из сборки, не? Для реализации под каждый тип хранилища — своя сборка.
Нет, мы о разном говорим.
Реализация фабрики это отдельная задача. Причем не такая уж и сложная. Современные IoC контейнеры отлично справляются с автоматической регистрацией достаточно сборку или нэймспэйс им подсунуть.
Я говорю о количестве мест в приложении, которые придется изменить если изменится логика подсчета фавортиных заказов. Вот это действительно важно.
Чем больше количество мест для изменения, тем больше возможностей и вероятности про что-то забыть и получить трудноуловимый баг.
Почему я сказал, что задача с фабрикой не такай уж и сложная, хотя код в ней будет в разы сложнее чем само Query?
А потому что ошибку в фабрике найдешь ты сам, причем буквально при первом запуске. А вот если ты что-то сделал не так с query, то ошибку в лучшем случае найдет тестер, но что-то мне говорит, что это будет заказчик, да еще и не сразу.
Здравствуйте, Doc, Вы писали:
Doc>>>Причем это зависит не от нагрузки, а именно от задач. A>>Вот про это я хочу послушать. Doc>Ну а я привел примеры.
"А давайте еще и поддержку XML сделаем" -- это не задача.
"Поддержка клиентов, которые не могут/не хотят ставить сервер баз данных" -- вот это задача. Но эту задачу решают embeded базы данных.
Здравствуйте, Aikin, Вы писали:
A>Реализация фабрики это отдельная задача. Причем не такая уж и сложная. Современные IoC контейнеры отлично справляются с автоматической регистрацией достаточно сборку или нэймспэйс им подсунуть.
Собственно это я и предложил.
A>Я говорю о количестве мест в приложении, которые придется изменить если изменится логика подсчета фавортиных заказов. Вот это действительно важно. A>Чем больше количество мест для изменения, тем больше возможностей и вероятности про что-то забыть и получить трудноуловимый баг.
Подождите, мы о чем — о переделке QO и DAL или замене заранее спроектированных для этого OQ? Во втором случае надо будет просто загрузить сборку с оптимизированными под данное хранилище QO.
A>А потому что ошибку в фабрике найдешь ты сам, причем буквально при первом запуске. А вот если ты что-то сделал не так с query, то ошибку в лучшем случае найдет тестер, но что-то мне говорит, что это будет заказчик, да еще и не сразу.
А если такая же ошибка будет в Linq выражении? Её также найдет только или текстер или заказчик.
Здравствуйте, Aikin, Вы писали:
A>Ну так как? Будут реальные примеры?
Т.е. движки вроде BlogEngine выдуманный пример? Или сайты для малого бизнеса, которым по типу данных без разницы где хранилища. Т.е. мне, как разработчику удобно иметь библиотеку DAL, которую можно использовать для любого из этих сайтов. Все это реальные задачи?
Здравствуйте, Doc, Вы писали:
A>>Я говорю о количестве мест в приложении, которые придется изменить если изменится логика подсчета фавортиных заказов. Вот это действительно важно. A>>Чем больше количество мест для изменения, тем больше возможностей и вероятности про что-то забыть и получить трудноуловимый баг.
Doc>Подождите, мы о чем — о переделке QO и DAL или замене заранее спроектированных для этого OQ? Во втором случае надо будет просто загрузить сборку с оптимизированными под данное хранилище QO.
Я говорю о готовности решения к изменениям. Эту характеристуку называют maintainability (за неимением нормального русского эквивалента).
Некоторые люди, только что закончившие ВУЗ, могут решить любую задачу за ночь. Не нужно говорить, что maintainability таких решений обычно стремиться к 0.
Doc>А если такая же ошибка будет в Linq выражении? Её также найдет только или текстер или заказчик.
Такая же не будет. Linq выражение ты можешь охватить взглядом и легко протестить, а вот проследить связи через этерфейсы уже сложнее. Я не говорю, что сложно, но сложнее.
Особенно сложно будет если вы поддерживаете десяток провайдеров. В этом случае, например, можно забыть внести эти изменения в Query для XML. Или сделать ошибку только в query для Postgres.
Doc>Собственно это я и предложил.
Да, именно это вы и предложили. Но это совсем не то на что я хотел обратить внимание.
Здравствуйте, Doc, Вы писали:
A>>Ну так как? Будут реальные примеры?
Doc>Т.е. движки вроде BlogEngine выдуманный пример? Или сайты для малого бизнеса, которым по типу данных без разницы где хранилища. Т.е. мне, как разработчику удобно иметь библиотеку DAL, которую можно использовать для любого из этих сайтов. Все это реальные задачи?
Я выделил пример чего я хотел увидеть в предыдущем сообщении.
Я хочу увидеть пример задачи, которая бы требовала поддержки всевозможных (экзотических) хранилищ.
Например задача для движка блога:
"Поддержка клиентов, которые не могут/не хотят ставить сервер баз данных" -- эту задачу решают embeded базы данных.
Здравствуйте, Doc, Вы писали:
Doc>Здравствуйте, Aikin, Вы писали:
A>>Ну так как? Будут реальные примеры?
Doc>Т.е. движки вроде BlogEngine выдуманный пример? Или сайты для малого бизнеса, которым по типу данных без разницы где хранилища. Т.е. мне, как разработчику удобно иметь библиотеку DAL, которую можно использовать для любого из этих сайтов. Все это реальные задачи?
Ты немного путаешь. Для BlogEngine и прочих engine, изначально ставится задача поддержки определенных типов хранилищ. Но нет задачи сделать возможность "заменить dal". Во всех этих *engine DAL затачивается под общее подмножество функций хранилищ, а не делается настолько абстрагированным чтобы подставить любое хранилище.
Кстати если рассматривать современные ORM, то они решают задачу смены одной DBMS на другую самостоятельно, не нужно их абстрагировать.
Здравствуйте, Aikin, Вы писали:
A>Я выделил пример чего я хотел увидеть в предыдущем сообщении. A>Я хочу увидеть пример задачи, которая бы требовала поддержки всевозможных (экзотических) хранилищ.
Судя по разговору, я понимаю что дальше будет. Например я скажу, что-то вроде "поддержка оптимальной работы ПО у клиентов, вне зависимости от типа хранилища." Вы затем скажете что это решается и так, без всяких "заморочек" с DAL.
Я замечаю что разговор переходит в плоскость, будто я утверждаю что софт с Linq в BL развалится до запуска. Хотя я такого не говорил.
A>Например задача для движка блога: A>"Поддержка клиентов, которые не могут/не хотят ставить сервер баз данных" -- эту задачу решают embeded базы данных.
Даже если не уходить с SQL, то разные БД имеют свои ограничения и баги. Про mySQL я уже писал, embeded как правило не поддерживают транзакции и т.д. Все равно придется учитывать все это в DAL и OQ.
Здравствуйте, Aikin, Вы писали:
A>Я говорю о готовности решения к изменениям. Эту характеристуку называют maintainability (за неимением нормального русского эквивалента).
Хорошо, как вы можете доказать свое утверждение, что maintainability "Linq в BL" больше, чем "Linq в QO"?
Кроме того, почему если я не трогаю BL и переписываю только сборку с QO, это хуже чем копаться сразу в BL?
Doc>>А если такая же ошибка будет в Linq выражении? Её также найдет только или текстер или заказчик. A>Такая же не будет.
С чего бы это? В реальном QO содержится тоже Linq выражение. Так или иначе мы выйдем или на что-то вроде
var someResult = mydata.where(n => id==n)...[итд]
или на что-то вроде
var someResult = dal.executeQuery(new GetSomeDataByIdQuery(id));
Ну да, во втором слчае на одно нажатие F12 больше Да и что-то подсказывает, что для тестов лучше завернуть mydata.where(n => id==n)...[итд] в отдельный метод в отдельном классе запросов. Поэтому кол-во нажатий F12 сравняется.
Ну и да, с контейнером будет чуть сложнее. Но это только на случай, когда выбор хранилища идет в рантайме.
Doc>>Linq выражение ты можешь охватить взглядом и легко протестить, а вот проследить связи через этерфейсы уже сложнее. Я не говорю, что сложно, но сложнее.
Сложно охватить взглядом класс QO из ~20 строк, да и то, все кроме метода с Linq выражением приячется сворачиванием.
A>Особенно сложно будет если вы поддерживаете десяток провайдеров. В этом случае, например, можно забыть внести эти изменения в Query для XML. Или сделать ошибку только в query для Postgres.
А UnitTest на что? QO очень лего тестятся как против массива, так и (где специфика СУБД) против тестовой базы.
Здравствуйте, Doc, Вы писали:
Doc>С чего бы это? В реальном QO содержится тоже Linq выражение. Так или иначе мы выйдем или на что-то вроде
Начинаем все сначала. Смысл в QO которое содержит только Linq выражение? ИХМО, чтобы QO имело смысл, нужно несколько реализаций под разные хранилища. Поэтому и сложнее.
Doc>Ну и да, с контейнером будет чуть сложнее. Но это только на случай, когда выбор хранилища идет в рантайме.
А какие варианты? Выбор конкретной реализации всегда в рантайме происходит. Если провайдеров больше одного, конечно.
A>>Особенно сложно будет если вы поддерживаете десяток провайдеров. В этом случае, например, можно забыть внести эти изменения в Query для XML. Или сделать ошибку только в query для Postgres. Doc>А UnitTest на что? QO очень лего тестятся как против массива, так и (где специфика СУБД) против тестовой базы.
А, так у вас еще и юнит тесты есть на всю логику. И интэгрэйшен сервер настроен. Так?
Это реально так и есть, или это теоретические рассуждения?
Я говорю за практику. Вы, похоже, о теории.
Здравствуйте, Doc, Вы писали:
Doc>Вы затем скажете что это решается и так, без всяких "заморочек" с DAL.
Нет, мы перешли в плоскость бизнесс задач. Я буду говорить с точки зрения стоимости реализации и экономической эффективности. А еще я буду говорить о том, что очень часто решения проблем преподносятся как требования (задачи) (привет, Гапертон, спасибо за науку).
Doc>Например я скажу, что-то вроде "поддержка оптимальной работы ПО у клиентов, вне зависимости от типа хранилища."
Извините, но это не бизнесс задача. Это маркетинговый лозунг от человека далекого от IT.
Как вы собираетесь решать эту задачу? А главное: как вы сможете понять что решили ее?
Doc>Я замечаю что разговор переходит в плоскость, будто я утверждаю что софт с Linq в BL развалится до запуска. Хотя я такого не говорил.
И близко не переходит. Я просто хочу понять откуда могут появиться требования о поддержке хранилища в виде XML вместе с нормальными БД.
Doc>Про mySQL я уже писал, embeded как правило не поддерживают транзакции и т.д. Все равно придется учитывать все это в DAL и OQ.
XML-файлы, очевидно, поддерживают.
Здравствуйте, IT, Вы писали:
IT>Для PL придумано семейство паттернов MVC.
Я то думал что оно и для BL тоже
IT>Это как? Слои есть, функционал есть, а размазывание его по слоям нет? Тогда зачем тебе слои?
А слои нужны для размазывания функционала? Это что-то новое.
IT>>>Как минимум тебе понядобится два дополнительных метода (по одному в DAL и BL) Doc>>Для чего? Можно пример (псевдокод)?
IT>UI:
IT>
Ну при таком построении DAL не мудрено что вам мерещется размазывание по слоям.
Doc>>Можно цитату, не вырванную из контекста, где я говорил о что повторное использование это особенность только слоев? IT>Посмотри выше по ветке.
Здравствуйте, Doc, Вы писали:
IT>>Для PL придумано семейство паттернов MVC. Doc>Я то думал что оно и для BL тоже
MVC для BL? Что-то я всё больше и больше убеждаюсь, что у кого-то из нас двоих, но не у меня, либо сплошная каша в голове, либо проблемы с терминологией.
IT>>Это как? Слои есть, функционал есть, а размазывание его по слоям нет? Тогда зачем тебе слои? Doc>А слои нужны для размазывания функционала? Это что-то новое.
Путаем причину со следствием.
Doc>Ну при таком построении DAL не мудрено что вам мерещется размазывание по слоям.
Всё остальное вариации на тему. Хотя, конечно, иногда бывает, что за деревьями леса не видно.
Впрочем, мы можем посмотреть на твой код и решить. Но ты видимо очень сильно стесняешься его показать.
IT>>Посмотри выше по ветке. Doc>Не нашел. Укажите.
Нет никакого желания перелапачивать весь топик.
Если нам не помогут, то мы тоже никого не пощадим.
"и для BL тоже"
IT>Что-то я всё больше и больше убеждаюсь, что у кого-то из нас двоих, но не у меня, либо сплошная каша в голове, либо проблемы с терминологией.
MVC отделяет PL и BL (которая по сути тут M) через C. Ваша версия? Хотя вы уже в BL UI включали (и потом неумело отдувались).
IT>Путаем причину со следствием.
Это вы путать начали.
Doc>>Ну при таком построении DAL не мудрено что вам мерещется размазывание по слоям. IT>Всё остальное вариации на тему. Хотя, конечно, иногда бывает, что за деревьями леса не видно.
Вы на название топика поглядите? OQ, ну еще Spec упоминались. А если так (упрощенно)
BL:
// валидация
IEnumerable<int> indexes = this.GetMessageIndex(someUserData);
// тут выбор и создание QueryObject по списку индексов
someMessage = dal.ExecuteQuery(selectedQueryObject);
return someMessage;
DAL:
// тут формируется и выполняется запрос к БД на основании переданного QueryObject
// по сути обертка над ORM с учетом особенностей заданного для данного DAL типа хранилища
return message;
Как видите каждый занят своим делом:
PL — показывает
C — обработка user input и отправка результата обратно пользователю
BL — содержит логику
DAL — просто бегает в базу
Со Spec даже веселее было бы, т.к. для Spec можно использовать логические выражения. По сути BL бы строил запрос, оперируя терминами решаемой задачи.
Кстати, в общем случае (если в DAL нет преобразований) это позволяет запихать DAL в отдельные библиотеки (для разных типов хранилища, но реализующие один и тот же интерфейс) и просто через NuGet подключать к проекту. В самом проекте пишутся и тестируются только QO/Spec.
IT>Впрочем, мы можем посмотреть на твой код и решить. Но ты видимо очень сильно стесняешься его показать.
Не вижу в этом необходимости. Тем более, что при желании можно доколупаться до любого кода. Так что я не сомневаюсь что объем вашего "фи" в отношении его будет ограничен только фантазией и свободным временем. Можете начать c "а почему UI не в BL"? :D (как тут уже было http://www.rsdn.ru/forum/design/5049674.1
Здравствуйте, Doc, Вы писали:
IT>>Что-то я всё больше и больше убеждаюсь, что у кого-то из нас двоих, но не у меня, либо сплошная каша в голове, либо проблемы с терминологией. Doc>MVC отделяет PL и BL (которая по сути тут M) через C.
О как! Теперь никаких сомнений — каша.
Doc>Ваша версия?
Моя версия такая. Разработка GUI имеет одну фундаментальную проблему. В одном месте у нас находится три составляющих GUI: визуальные компоненты, модель отображаемых данных и контроль состояния всего этого барахла. Смешивание всего этого дела даёт нам умножение сложности всех составляющих. В результе линейное наращивание функционала приводит к экспоненциальному увеличению сложности всего решения. Задача семейства (а это не один паттерн, а целое семейство) MVC паттернов развести все три составляющие по углам и по максимуму устранить или хотя бы ослабить между ними связи.
Работу с BL MVC паттерны не определяют, что вности определённую путаницу. Её пихают/вызывают то из модели, то из контроллера. В последнее время такую логику всё чаще прикомандировывают к контроллеру.
Doc>Хотя вы уже в BL UI включали (и потом неумело отдувались).
Что значит отдувался? Я пишу всю логику в контроллерах и ни секунды не сомневаюсь, что это правильно. Если ты под UI понимаешь все состовляющие MVC паттерна, то да, моя логика в UI, кроме, конечно, компонент, которые используются повторно. Но это не суть.
IT>>Всё остальное вариации на тему. Хотя, конечно, иногда бывает, что за деревьями леса не видно. Doc>Вы на название топика поглядите? OQ, ну еще Spec упоминались. А если так (упрощенно)
Я же говорю — вариации на тему.
Doc>Как видите каждый занят своим делом: Doc>PL — показывает Doc>C — обработка user input и отправка результата обратно пользователю Doc>BL — содержит логику Doc>DAL — просто бегает в базу
Тут настоящим делом заняты только PL и C. Остальное архитектурные (или как теперь модно говорить задчиские) излишества. QO выкидываем на йух. BL и DAL объединяем и переносим в C. Код сокращается в пять раз, решение упрощается, все пьют шампанское.
Doc>Со Spec даже веселее было бы...
Это точно.
IT>>Впрочем, мы можем посмотреть на твой код и решить. Но ты видимо очень сильно стесняешься его показать. Doc>Не вижу в этом необходимости.
Кто бы сомневался.
IT>>Нет никакого желания перелапачивать весь топик. Doc>Тогда постарайтесь ваши фантазии держать при себе.
При чём тут фантазии. Такие заявления сложно забыть. Я бы и топик перелопатил, если бы наша беседа имела характер не "имею мнение хрен оспоришь", а "есть мнение давайте обсудим".
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>О как! Теперь никаких сомнений — каша.
После этого вашего сообщения я вот так про вас думаю.
IT>Моя версия такая. Разработка GUI имеет одну фундаментальную проблему. В одном месте у нас находится три составляющих GUI: визуальные компоненты, модель отображаемых данных и контроль состояния всего этого барахла. Смешивание всего этого дела даёт нам умножение сложности всех составляющих. В результе линейное наращивание функционала приводит к экспоненциальному увеличению сложности всего решения. Задача семейства (а это не один паттерн, а целое семейство) MVC паттернов развести все три составляющие по углам и по максимуму устранить или хотя бы ослабить между ними связи.
А если много умных слов заменить на суть... останется разделение BL и PL (здесь L не layer, а Logic).
IT>Работу с BL MVC паттерны не определяют, что вности определённую путаницу. Её пихают/вызывают то из модели, то из контроллера. В последнее время такую логику всё чаще прикомандировывают к контроллеру.
Ага, и при этом даже для "пихают в контроллер" вывели anti-pattern Fat Controllers.
Doc>>Хотя вы уже в BL UI включали (и потом неумело отдувались). IT>Что значит отдувался? Я пишу всю логику в контроллерах и ни секунды не сомневаюсь, что это правильно.
Ну вот дошли до Fat Controllers. И эти люди говорят что я не понимаю MVC
Кстати, Controller это у вас выходит BL?
IT> Если ты под UI понимаешь все состовляющие MVC паттерна, то да, моя логика в UI, кроме, конечно, компонент, которые используются повторно. Но это не суть.
Под UI я понимаю V+C (т.к. С имеет прямое отношение к user input).
А вот BL тут в M.
У вас же C получается "и ваши и нашим", он и от юзера данные получает и BL тянет.
IT>Тут настоящим делом заняты только PL и C. Остальное архитектурные (или как теперь модно говорить задчиские) излишества. QO выкидываем на йух. BL и DAL объединяем и переносим в C. Код сокращается в пять раз, решение упрощается, все пьют шампанское.
Т.е. по сути сказать нечего? Напоминаю вопрос был не "что можно тут поменять", а "где тут дублирование кода и проброс вызовов". Архитектуру оставьте в стороне.
IT>При чём тут фантазии. Такие заявления сложно забыть.
Т.е. я вам ссылкой показал где у вас UI в бизнес-логике. А вы не можете показать якобы мое утверждение. Вывод — у вас развитое воображение.
IT> Я бы и топик перелопатил, если бы наша беседа имела характер не "имею мнение хрен оспоришь", а "есть мнение давайте обсудим".
Здравствуйте, Doc, Вы писали:
IT>>Что значит отдувался? Я пишу всю логику в контроллерах и ни секунды не сомневаюсь, что это правильно. Doc>Ну вот дошли до Fat Controllers. И эти люди говорят что я не понимаю MVC Doc>Кстати, Controller это у вас выходит BL?
Не нужно слова собеседника доводить до абсурда, а потом радостно заявлять "Ага!".
Мне сложно говорить за Игоря, но я 100% уверен, что в случае FatController-a, большая часть логики переедет из контроллера в другие классы/методы. И не столько важно в какую часть приложения уедет эта логика. Важно то, что при грамотной архитектуре (тут я имею ввиду "грамотной инфраструктуре" (например вынос валидации из контроллера)) и грамотной организации Юзер Сценариев (каждый "экран" делет необходимый минимум работы), необходимость в вынесении логики из котроллера куда-нить возникает редко.
Вы же, выделяя отдельный слой для BL, изначально обрекаете контроллер на функции "мальчика на побегушках", единственные обязанности которого бегать к BL и спрашивать "пользователь нажал кнопку, что делать?????".
Здравствуйте, Aikin, Вы писали:
A>Здравствуйте, Doc, Вы писали:
A>Мне сложно говорить за Игоря, но я 100% уверен ...
Да почему всё за него говорят то То "UI в BL" и за него начинают утверждать что он совсем не то имел ввиду. Теперь и тут он не то оказывает сказал.
A>Вы же, выделяя отдельный слой для BL, изначально обрекаете контроллер на функции "мальчика на побегушках", единственные обязанности которого бегать к BL и спрашивать "пользователь нажал кнопку, что делать?????".
Так это и есть задача Controller — связать User Input и BL. Команды "думать" ему не было
Вот сейчас, похоже к радости Игоря , скажу что повторно используется BL в рамках одного Solution.
Поэтому у меня например BL как правило отдельная сборка. И её использует не только MyProject.WebUI, но и ряд других проектов (например сборщика данных) в этом же Solution (извините за bold).
Здравствуйте, Aikin, Вы писали:
A>Начинаем все сначала. Смысл в QO которое содержит только Linq выражение? ИХМО, чтобы QO имело смысл, нужно несколько реализаций под разные хранилища. Поэтому и сложнее.
Это при условии что они сразу используются в проекте. Кстати и вашем случае тогда будет куча разных запросов.
В большинстве случаев в текущий момент времени у нас конкретно хранилище. В этом случае QO помогают повторно использовать в BL одни и те же запросы. Я надеюсь что и вы свои linq выражения где-то в методах держите, а не через copy/paste по коду кидаете. Ну и переезд в этом случае на другой тип хранилища не трогает BL.
Отмечу, что сама "обертка для ORM" уже давно живет в своей библиотеке на локальном NuGet и в проектах пишу только сами QO или Spec (от задач проекта).
A>А какие варианты? Выбор конкретной реализации всегда в рантайме происходит. Если провайдеров больше одного, конечно.
См. выше. Для рантайма и с linq будет не меньшая заморочка. А для варианта "1 тип" можно подключить библиотеку с нужными QO и заменить её при необходимости.
A>А, так у вас еще и юнит тесты есть на всю логику. И интэгрэйшен сервер настроен. Так?
На BL да. Не 100% покрыто, но где-то 70% в среднем. Чем это плохо?
A>Я говорю за практику. Вы, похоже, о теории.
Да, да.. я помню о пузомерке... формулы расчета длинны пуза от достижений уже готовы?
Здравствуйте, Doc, Вы писали:
Doc>Я надеюсь что и вы свои linq выражения где-то в методах держите, а не через copy/paste по коду кидаете. Doc>Да, да.. я помню о пузомерке... формулы расчета длинны пуза от достижений уже готовы?
Давайте разойдемся. Как-то я устал от общения.
Здравствуйте, Doc, Вы писали:
IT>>Какие именно? Access, SQLite и SqlCe поддерживают. Embedded Firebird не пробовал, но наверняка тоже поддерживает. Doc>У меня SqlCe падала на попытке использовать транзакции с Exception что не поддерживается.
Что такое транзакции с Exception?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Aikin, Вы писали:
A>Не нужно слова собеседника доводить до абсурда, а потом радостно заявлять "Ага!".
Да ещё и делать это так неумело.
A>Мне сложно говорить за Игоря, но я 100% уверен, что в случае FatController-a, большая часть логики переедет из контроллера в другие классы/методы.
В слове FatController ключевое слово — Fat. И это означает, что у нас просто много функционала в одном месте. Если этот функционал переместить в BL, то мы получим FatBL. Вот и вся разница.
A>Вы же, выделяя отдельный слой для BL, изначально обрекаете контроллер на функции "мальчика на побегушках", единственные обязанности которого бегать к BL и спрашивать "пользователь нажал кнопку, что делать?????".
Не трать патроны. Это бесполезно. Товарищ упёрся в свои догмы и уже давно дискутирует по принциау "имею мнение хрен оспоришь".
Если нам не помогут, то мы тоже никого не пощадим.
Да, я тоже пришел к этому мнению. Самоустраняюсь
IT>В слове FatController ключевое слово — Fat. И это означает, что у нас просто много функционала в одном месте. Если этот функционал переместить в BL, то мы получим FatBL. Вот и вся разница.
Здравствуйте, IT, Вы писали:
IT>В слове FatController ключевое слово — Fat. И это означает, что у нас просто много функционала в одном месте. Если этот функционал переместить в BL, то мы получим FatBL.
Здравствуйте, Doc, Вы писали:
IT>>У меня в BLToolkit около полутора тысяч тестов с SqlCe и почти все с транзакциями. Doc>Хм. А они там через SQL команды заданы?
Через метод BeginTransaction.
Если нам не помогут, то мы тоже никого не пощадим.