Здравствуйте, 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>Померяемся опытом? Что-то мне говорит, что я победю
Давайте, только разработайте формулу для подсчета опыта с учетом разных технологий, часов за ними проведенных, рейтингов и кармах на профильных форумах, всяких статусов там ... А если серьезно, я еще в пузомерки не играл. Считайте что вы победили в ней за неявкой соперника.