Pull to refresh
6
0
Алексей @posledam

Руководитель разработки ПО

Send message

Если мы говорим про бизнес-логику, то это сложные объекты со сложными сценариями бизнес-консистетности данных. Речь не про простейшие констрейты, которые мы можем обеспечить в БД, а гораздо более сложные. Соответственно, нужно работать с объектами. БД в данном случае выступает хранилищем данных, из которых эти объекты состоят. Единственная альтернатива ORM, это доставать плоские данные и вручную распихивать их в объекты, что не что иное, как "ручной ORM", а зачем в наш век делать что-то вручную, если это довольно легко автоматизируется? Я нахожу только два ответа: старая привычка или религия.

В моей практике я не сталкивался с ситуацией, когда ORM мне мешала, всегда только помогала. Всегда. Это вовсе не отменяет требования знать SQL, как устроены СУБД, индексы, транзакции и прочее прочее.

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

Если же за холиворы считать "бросание какашками", так это не холиворы, это банальный школьный срач, который к холиворам отношения не имеет.

Последние 3 крупных легаси-проекта в моей практике имеют самые большие проблемы именно из-за логики в БД. Близость данных к логике не даёт в реальности никаких преимуществ кроме значительных проблем. В процессе рефакторинга легаси-систем логика с матами-перематами из БД извлекается и переносится в код, где ему и место. Единственные люди, кто по этому поводу недоумевают, это ДБА. Но оно и понятно, с ними даже никто не спорит и спорить никогда не будет. А за триггеры в логике в аду приготовлен отдельный котёл.

ORM не может быть злом. Это отражение плоских данных в структуру объектов ЯП. Либо это делать руками, что по сути ни что иное, как обезьяний труд. Либо всё таки положиться на компилятор/ЯП. Проблемы начинаются в отказе от SQL для написания запросов. Простые запросы и правда нет смысла фигачить руками, а что по-сложнее уже нет смысла генерировать, так как SQL самодостаточен.

А ещё на уровне синтаксиса я не могу отличить локальную переменную от типа, свойства или поля, также не могу однозначно сказать какого типа переменная.

В C# не "всё есть объект". Есть вполне себе значимые типы (структуры) и ссылочные типы (классы). Значимые типы передаются по значению, ссылочные по ссылке (указателю). При этом можно иметь ссылку на значение или указатель. И всё это разнообразие доступно, понятно и работает без звёздочек, амперсандов и стрелочек типа ->.

Какой смысл возвращаться к специальному ссылочно-значимому синтаксису, совершенно непонятно.

Т.е. sql-файлы в нужном порядке можно выполнить и без всякого GO? Выглядит, как изобретение колеса, простите :)

Получается, у разработчиков локально одна архитектура, а на серваках совсем другая, если конечно там тоже не ARM. Мне кажется такое решение контрпродуктивно по своей сути.

Написать плагин, кстати, совсем не сложно. Давным-давно, помню, писал плагины даже на паскале.

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

Почитал комментарии, как странно, что не упомянули одну из основных киллер-фич FAR-а: это мощнейшая интеграция с командной строкой. Это причина, почему Total Commander мне не нравится - это просто файловый менеджер, консольный запуск выполняется отдельно. А FAR это менеджер, интегрированный с консолью.

Многие удивляются, а зачем FAR? Если среди этих людей есть консольщики, для которых консоль -- рабочий инструмент, то собственно для удобной работы с консолью.

Я не люблю обезьяньи команды для вывода содержимого каталога, файлов, перехода по каталогам. Это дорого по времени, даже если команды сидят в подкорке, даже с автокомплитом. FAR быстрее.

Отключение панелей для отображения чистой консоли Ctrl-O, или ESC (после добавления хоткеев из стандартного комплекта).

Можно весь stdout направить прям в редактор, без промежуточного файла, вот так:

edit:<some command

Можно моментально перейти к файлу или папке, с включением переменных окружения:

goto:file/or/directory/path

Все консольные команды запоминаются в истории FAR. Консольные команды можно шаблонизировать с учётом что сейчас на левой панели и на правой, там целый космос что с этим можно делать.

Например, можно по-файлово применить команду к выделенным файлам, выполнить сложнейший поиск с рекурсией, посмотреть результаты поиска в панели, выполнить для найденных файлов/папок любую команду из консоли, или сделать выборку из результатов поиска, сохранить её в файл, или в буфер. Мощная функция сравнения двух каталогов с различными стратегиями.

Если использовать FAR для работы с консолью, он может существенно улучшить комфорт и производительность. Его возможности до сих пор впечатляют.

Вы говорите про экземпляр чего-то, что реализует IQueryable. Провайдер. Ну так одно другому не мешает. Вы можете сделать так: Array.Empty().AsQueryable(), затем наполнить полученный экземпляр предикатами, затем можно извлечь Expression и поместить в необходимую реализацию IQueryable.

Обычно, реализации спецификаций хранят в себе Expression. Так IQueryable тоже хранит :) Т.е. он перекрывает спецификацию и Query Object. Ну и плюс, можно делать не только предикаты, но и больше.

Но возможности LINQ просто даже близко не дотягивают до возможностей SQL. Поэтому многие разработчики даже не пользуются LINQ.

Если очень хочется, из IQueryable можно извлекать выражения и встраивать их в "подзапросы", чтобы можно было делать даже так:

public static IQueryable<Contract> ByDealer(this IQueryable<Contract> linq, int dealerId)
{
   return linq.Where(p => p.Dealer.Id == dealerId);
}

public static IQueryable<Contract> ByFilifal(this IQueryable<Contract> linq, int filialId)
{
   return linq.Where(p => p.Filial.Id == filialId);
}

// затем, вуаля:

var query = dbContext.Contracts.ByDealer(123).Or().ByFilial(filialId);

Такие финты можно делать, и сильно сложнее. Другое дело, что в реальности игры с LINQ, спецификациями и прочими игрушками приносят в основном вред, и совсем не приносят пользы.

Возможностей LINQ достаточно, чтобы делать простые выборки и получить до 90% типизированных запросов. Но если выйти за рамки совсем примитивных приложений, окажется, что очень нужны и часто, оконные функции, кубы, предварительные промежуточные выборки, в общем для многих задач нужен SQL. Без плясок, приколов, попытками это запихать в LINQ. И нужно оба этих мира, чтоб программист не тратил время на проектирование спецификаций, которые как окажется потом весьма слабо и плохо комбинируются, но нужны конкретные запросы и возможность без плясок использовать SQL.

Это если конечно говорить о боевых приложениях с какой-никакой нагрузкой и хоть с какой-то сложностью в логике.

Чего это не решаются? Очень даже решаются.

public static IQueryable<Contract> ByDealer(this IQueryable<Contract> linq, int dealerId)
{
   return linq.Where(p => p.Dealer.Id == dealerId);
}

Блин, IQueyrable это спецификация. Это чистая абстракция, об этом даже говорит тот факт, что это интерфейс. DbContext это репозиторий + unit of work. В чистом виде. Когда я вижу проекты, где творят какие-то generic IRepository, мне хочется плакать. Зачем нужны эти "разные репозитории"? Это для чего?

IQueryable уже сам по себе является ни чем иным, как спецификацией. Но людям нравится городить ещё 25 абстракций поверх. Никак не угомонятся :)

Проблема в том, Rich Domain Model это бутафория. Возьмём какой-нибудь классический пример, интернет-магазин. Объект "Заказ". По DDD, мы должны определить класс Order и всё, что можно с ним сделать, находится в этом классе. Вся бизнес-логика. Типа. Почему "типа"? Да потому что класс Order это никакой не "Заказ" и никакой не бизнес-объект, это по сути одна маленькая грань настоящего заказа, это набор полей в одной конкретной системе. В реальном же мире заказ это далеко не только запись в БД, и логикой одной приложухи дело совсем не ограничивается. Заказ может иметь даже не сотню, а тысячи сложнейших правил, некоторые вообще существуют не больше недели.

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

А если перестать фантазировать, и осознать, что мы управляем не Заказом, а всего лишь записью о заказе в БД, т.е. набором полей и связанных записей, то оказывается, что в основном мы работаем с состоянием. А не рулим и не описываем "правила бизнеса". Мы читаем из БД объект, показываем срез данных юзеру, принимаем ввод от юзера, проверяем что он ввёл, сравниваем с данными в БД и сохраняем новое состояние. Вот что мы делаем. А не пишем манускрипты с "правилами бизнеса" :)

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

Как по мне, стало ещё на порядок сложнее. Либо лично мне не нравятся примеры в стиле "это Алиса, она местная дурочка, а это Боб, местный эксперт-душнила", теперь думаешь о бедной Алисе, а не о задаче, и не покидает ощущения, что со мной пытаются общаться как с идиотом. Конечно сложные вещи стоит упрощать, или подбирать удачные аллегории, но без фанатизма :)

Чем статические функции не угодили? Класс там это просто синтаксический контейнер, модуль. Разницы никакой нет.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity

Specialization

Backend Developer, Руководитель отдела разработки
Lead
From 450,000 ₽
C#
.NET
Software development
Database
High-loaded systems
Designing application architecture
Creating project architecture
Design information systems
Monitoring