В недавней статье Domain-Driven Design: Продажа идеи я обращал внимание на удобство работы с ORM и возможность ухода от хранимых процедур в сторону ORM. Мне на почту прислали много писем с вопросами о том, что же сейчас является «трендом» в работе с базой данных.
Я думаю, что выбор зависит от конкретного проекта, тем не менее предлагаю вам в опросе выбрать вариант, который вы в данный момент наиболее часто используете.
Последние мои общения с коллегами показали, что этот вопрос вызывает разногласия. Лично я предпочитаю работу через ORM и уже давно не пишу хранимые процедуры и не формирую запросы в коде. Работа через ORM ускоряет разработку и позволяет сосредоточится на бизнес-логике. ORM строит довольно хорошие запросы, которые не снижают произовдительности. Активно использую кэш для ускорения работы.
Будет интересно увидеть в комментариях причины вашего выбора.
> Дней до окончания голосования: 282 имхо, дней до завершения голосования должно быть 272 ;)
ОтветитьУдалитьORM - по тем же причинам и с той же аргументацией что в этом блоге уже тысячу раз обсуждалась :)
ОтветитьУдалитьФормирование запросов в коде - в тех редких случаях/проектах когда мне видиться выгоднее/быстрее/потенциально безопасно описывать домен в низкоуровневых понятиях аля данные и язык работы с доменом удается привести к SQL.
Если дней должно быть 272, то уже не важно через ORM делать запросы или в коде :)
ОтветитьУдалить> ORM строит довольно хорошие запросы, которые не снижают произовдительности.
ОтветитьУдалитьВот именно поэтому строю запросы вручную чаще всего. Для упрощения есть базовая обертка на стандартные часто используемые запросы, но все что от них отличается строю вручную.
ORM строит "хорошие" запросы, не более того. Эти запросы в основном не снижают производительности, но и не улучшают ее. Невозможно учитывать все автоматизированно.
А я строю максимально подходящие запросы к каждой ситуации, учитывая объем данных, структуру таблиц, возможные варианты оптимизации в БД. Проверяю каждый вариант на производительность на тестовом скопе данных и выбираю лучший. Понятно что такой подход оправдан не всегда, только в некоторых случаях. Но как раз предпочитаю работать с такими случаями.
Александр, спасибо за комментарий. Я хочу иметь список аргументов за каждый подход, чтобы глубже разобраться в теме.
ОтветитьУдалитьПодход с хранимыми процедурами мне не очень нравится, но я не могу его игнорировать и хочу лучше понять в чем преимущества от его использования.
Амаль, какой архитектурные шаблоны вы используете для доступа к данным?
ОтветитьУдалитьhttp://martinfowler.com/eaaCatalog/dataMapper.html
http://martinfowler.com/eaaCatalog/repository.html
За счет чего вы добиваетесь гибкости при построении запросов? Что будет если, например, название сущности и полей поменяется? Как вы боретесь за скорость внесения изменений? Возможно вы пишите интеграционные тесты с участием БД?
В тех случаях, когда мне нужна супер-быстрость разработки, я использую NH + FNH (обязательно автомапинг) в чистом виде - без всяких репозиториев и прочих юнит-оф-ворков.
ОтветитьУдалить>
ОтветитьУдалитьORM строит "хорошие" запросы, не более того. Эти запросы в основном не снижают производительности, но и не улучшают ее.Вы не правы. Не нужно утверждать то, чего вы не знаете.
1. В NH, есть очень мощный инструмент, который все и всегда, почему-то, забывают и игнорируют - second level cahce.
Простой пример - при повторном отображении вебсайта до базы данных не дойдет ни один запрос. NH возьмет всё данные из кэша. Умеет кэшировать отдельные сущности или целые результаты запросов.
2. NH может группировать запросы в пакеты и делать несколько запросов за одно обращение к базе, избавляя вас от необходимости это делать самому (это сложно, скучно и неудобно программировать вручную).
3. И, наконец, в NH можно написать запрос на чистом SQL или вызвать хранимую и получить все прелести этого самого объекто-реляционного отображения (сделать из плоской структуры граф объектов и т.д.).
Вспоминаем базовые преимущества хранимых процедур:
ОтветитьУдалить- процедуры компилируются один раз задолго до вызова, в отличии от запросов генерируемых ORM;- ip-пакеты с вызовом процедуры гораздо меньше чем с вызовом 3-х страничного запроса генерируемого ORM;- возможность "инкапсулировать" некоторую логику внутри процедуры, в отличие от множественных запросов генерируемых ORM;- данные, получаемые в промежуточной логике не передаются на сторону приложения, это может составить гигантские объёмы трафика в случае когда сервер БД и веб-сервер находятся на отдельных машинах;- ну и возможность разграничения доступа, т.е. пользователю можно полностью запретить просмотр/изменение/удаление данных в любой таблице и дать возможность выполнять только процедуры.
ОРМ - как все знают - хороший способ сосредоточиться на бизнес-логике. Это классно, но часто в крупных и сложных проектах бывают проблемы производительности. Приходиться отказываться от нормальных форм в структуре БД и прочее, и прочее.
ОтветитьУдалитьещё хуже, когда структура БД была до меня и её менять нельзя.
Обычно так, там где ОРМ ляжет легко, используется ОРМ.
Там где это проблемно, используется легкая прослойка между JDBC и классами бизнес-логики. Например, spring-jdbc (это для java пример, может для C# есть что похожее). при этом запросы пишутся в ручную, но не в коде, а вытаскиваются в отдельные файлы. Конкретные данные можно сразу мапить в объекты.
Такой подход позволяет:
- не возиться в ручную с коннекшенами (не закрытие их может приводить к утечке ресурсов, а закрытие - к усложнению логики приложения, либо изобретению прослойки-велосипеда)
- постоянно контролировать список всех возможных запросов, которые делаются к БД. (эту информацию можно отдать специалистам по БД, которые оптимизируют саму БД, чтобы заданные запросы работали оптимально)
- поддерживать компактность кода (те или иные запросы могут быть не маленькими, мне довелось делать запросы по 30-40 строк, но я видел и запросы на 120 строк, когда такая портянка висит в коде, она мешает его чтению и пониманию, приходиться прокручивать текст туда-сюда постоянно, это влияет на производительность разработки).
- поддержка постоянно вида запросов (часто легкое изменение запроса при редактировании кода может его сломать - например, пробел не там где надо, и тому подобное... )
Что касается хранимок, логики в хранимках. С точки зрения дизайна приложения - это зло, т.к. часто придется повторять бизнес-логику в хранимках, а значит держать в двух местах ход, который делает одно и тоже. Это плохо, т.к. такой код тяжело поддерживать. Но, иногда без этого вообще никак. Потому как объемы обрабатываемых данных могут быть огромны. В этом случае могу посоветовать только не дублировать логику хранимок в коде проекта.
ИХМО, хранимки тяжело поддерживать, рефакторить, дорабатывать. Должны быть веские причины, чтобы вступить на этот путь. В очень крупных проектах БД может заниматься отдельный человек
Это всё хорошо, только, пожалуйста, перечитайте мой предыдущий комментарий более тщательно.
ОтветитьУдалитьНемного странный опрос
ОтветитьУдалить1. В ASP.NET есть очень мощный инструмент - Output cache. При повторном отображении сайта даже до бизнеслогики ничего не дойдет. ;)
ОтветитьУдалитьВ целом я за ORM, но иногда можно использовать и небольших хранимые процедуры. Например, проверить логин и пароль пользхователя, а в приложение вернуть просто "true/false".
ОтветитьУдалитьФормирую запросы в коде, т.к. имею дело с унаследованным кодом и структура таблиц отличается от модели и структуру таблиц проблематично править так как на неё завязаны другие программы. Считаю, что и без ORM можно обойтись с помощью Data Mapper + Repository. ORM лишнее усложнение. С помощью Data Mapper + Repository можно менять хранилище SQL /NoSQL / ещё что-то, возможно даже композиция из хранилищь.
ОтветитьУдалитьRepository - это паттерн группы Object-Relational Metadata Mapping. Если вы используете репозиторий - значит вы работаете через ORM.
ОтветитьУдалитьЯ смотрю тут все слишком умные собрались. Не сравнивайте жопу с пальцем. В кэше NHibernate, при условии, что никто не лезет своими кривыми руками в базу, ВСЕГДА актуальные и свежие данные. В кэше ASP.NET - нет.
ОтветитьУдалитьНе успел пока прочитать все комментарии, так что извините, если это уже кто-то написал. Предполагаю, что в вашем вопросе нужно бы еще добавить "какие именно приложения вы пишите". От этого очень сильно зависит подход. Если у вас приложение отображающее графики по каким-то статистическим данным, которых собирается миллион за день, то как вы не крутите - кеш в NH не сможет загрузить все объекты, а .NET не обеспечит такую же скорость работы с коллекциями, которую покажет SQL сервер, и учитывайте, что запросы обычно ну прям совсем не пересекаются. Смысла использовать ORM в этом случае совсем нет.
ОтветитьУдалитьХватает перфоманса - ОРМ
ОтветитьУдалитьНе хватает - начинаем лезть ближе данным, соответсвенно ручные запросы, хп и т.д.
К сожалению, не все проблемы перфоманса можно решить кэшем:)
Почему иногда нужны хп?
ОтветитьУдалитьДопустим, вам надо обработать сто тыщ записей из 15 таблиц, чтобы получить результат из 10 записей. Причем логика обработки довольно сложная, и ее не выразить в запросе.
Так вот, есть вариант тащить все эти сто тыщ записей в слой бизнес логики, и обрабатывать там. Соотвественно сетевые задержки, память, то се.
Либо написать хп, которая все это прокрутит внутри бд, и вернет результат. Тем более что rdbms десятилетиями затачивались под подобные задачи.
Второй вариант может быть оочень предпочтительней в качестве перфоманса, и никакие плюсы ОРМ подхода тут не перевесят.
Триггеры используете для производительности? Простите, но вы бредите. Триггеры во всех реляционных базах данных работают синхронно, т.е. тормозят вставку значений.
ОтветитьУдалить>Например, рекурсивные выборки и работу с иерархическими данными большинство ORM-ов как-то не слишком хорошо поддерживают.
Это у большинства людей мозг не поддерживает иерархические данные, а ORM, при наличие мозга деревья поддерживает на уAlexander Steshenko
а. И это будет работать в РАЗЫ быстрее, чем средствами базы данных. Уже три года работаем со всякими сущностями, которые образуют деревья через ОРМ и НИ РАЗУ не писали рекурсивный запрос к базе, после того, как три года назад уволили нашего DBA за ненадобностью.
http://nhibernate.hibernatingrhinos.com/16/how-to-map-a-tree-in-nhibernate курить раздел "an alternative approach"
Зашибись у вас стиль общения. Вежливось аж прет из всех отверстий.
ОтветитьУдалитьСами же ответили "есть кэш" в ответ на утверждение, что орм не всегда генерирует оптимальные запросы. Неважно, насколько кэш крут, если приложение часто мимо него промахивается, и если на конкретных данных запрос, сгенеренный orm-ом, работает на пару секунд дольше, чем написанный DBA 40-го уровня.
Если всегда хватало сгенеренных запросов + кэша второго уровня, никогда не приходилось кэшить уже готовый html - значит повезло. Или наоборот, не повезло.
Для asp.net есть CacheDependency/SqlCacheDependency. Если захотеть - то можно удержать его в актуальном состоянии для тех кусков, для которых это действительно надо.
В этом случае нет смысла использовать БД вообще.
ОтветитьУдалитьhttp://martinfowler.com/articles/lmax.html
Т.е. есть какой-то сервис, в который все ваши миллион событий поступают и он это анализирует в РЕАЛЬНОМ времени. В базу это сохраняет кто-то другой.
>Для asp.net есть CacheDependency/SqlCacheDependency.
ОтветитьУдалитьNH его поддерживает, для случая с кривыми руками, постоянно пытающимися что-то изменить в базе данных.
>Неважно, насколько кэш крут, если приложение часто мимо него промахивается.
NH не промахивается. Кэшируются запросы и их результаты.
>Если всегда хватало сгенеренных запросов + кэша второго уровня, никогда не приходилось кэшить уже готовый html - значит повезло. Или наоборот, не повезло.
Один из наших бывших программистов разрабатывает онлайн игру для одноклассников. Одновременный онлайн 10-20к пользователей. 2-3к запросов в минуту. По его словам при онлайне 4к MS SQL просто лёг. Спас кэш второго уровня NH.
>никогда не приходилось кэшить уже готовый html
Расскажите мне вкратце, как вы будете кэшировать странице в динамическом приложении, в котором нужен свежий-при-свежий контент?
>>NH его поддерживает, для случая с кривыми руками, постоянно пытающимися что-то изменить в базе данных.
ОтветитьУдалитьне всегда можно сказать заказчику, которых хочет прямой доступ в базу для своего сервиса ZZZ "у вас руки кривые".
>>NH не промахивается. Кэшируются запросы и их результаты.
Промах мимо кэша - это не когда по тому же запросу ORM полез в базу, а когда запросы идут в основном разные (или со слишком разными параметрами), и кэш не срабатывает. Кэш хорош при большом количестве одинаковых/похожих запросах, а такое не во всех приложениях встречается.
>> Один из наших бывших программистов
всегда можно привести контрпример. один из моих знакомых как-то пытался (вместе со всей командой, и руки у них ровные) включить кэш 2-го уровня в приложении, работающем с пачкой одинаковых баз (для разных аккаунтов, исторически так сложилось, перейти на одну базу займет N человеко-лет). в результате аккаунты в некоторых случаях начали видеть данные друг-друга, кэш отключили. И исправить такое поведение для их проекта займет еще N человеко-лет.
>> Расскажите мне вкратце, как вы будете кэшировать странице в динамическом приложении, в котором нужен свежий-при-свежий контент?
Если у меня будет много времени, то вот так :)
http://37signals.com/svn/posts/3112-how-basecamp-next-got-to-be-so-damn-fast-without-using-much-client-side-ui
Если мало - то проще подправить отдельные тормознутые запросы и кэшировать только редкоизменяемые куски. Например, результаты рендеринга отдельных Actions, через ActionFilters.
Я же не пытаюсь доказать что кэш в NH плохой. Он хороший. Но его надо использовать вместе, а не вместо полноценного кэширования и ручных запросов в нужных местах.
Черт, вы открыли мне глаза на подлую сущность триггеров!!! Они не нужны, срочно пишите в Microsoft чтобы поддержку триггеров убрали из SQL Server!
ОтветитьУдалитьЕсли серьезно, то триггеры + сервис брокер. Для некоторых действительно специфических кусков.
>> Это у большинства людей мозг не поддерживает иерархические данные, а ORM, при наличие мозга деревья поддерживает
При наличии мозга достаточно очевидно, что ORM не обязательно означает именно NH. Я даже вроде не заявлял в своем посте что пишу на C#. Александр, насколько я вижу, тоже никаких ограничений в опросе не поставил. Если бы вы еще и прочитали мой ответ внимательно, то заметили бы что я специально упомянул ORM во множественном числе "большинство ORM-ов".
Интересно, через какую магию запрос за иерархическими данными через NH будет работать быстрее запроса средствами базы. Вы же знаете что NH работает через обычный SQL (на всякий случай спрашиваю)?
Рекурсивные запросы к базе используются не только для выборки иерархий. Обычно это именно хитрые выборки, в которых результат прямо зависит от первой итерации На конкретном куске в моем текущем проекте перенос одной из выборок из хранимки в .NET - рассчета resource allocation для кучи задач/людей/проектов - дает больше 100 заходов даже на мелких объемах данных. Можно я оставлю этот кусок в хранимке?
3 года - да, огромный срок :)
>не всегда можно сказать заказчику, которых хочет прямой доступ в базу для своего сервиса ZZZ "у вас руки кривые".
ОтветитьУдалитьС заказчиком всегда можно договориться и прописать в договоре, что за сломанное таким способом приложение он несет ответственность.
Либо хорошо ему разъяснить принцип работы: "полез в базу - сбрось кэш. сбрасыват кэш так-то и так-то"
>в результате аккаунты в некоторых случаях начали видеть данные друг-друга
Видимо руки всё-таки кривые. Эта проблема решаема, и насколько я ее понял, достаточно легко.
Да, я не спорю, что с кэшем второго уровня нужно уметь работать и закладывать возможное его использование в приложение с самого начала (придерживаться пары простых правил). Но это как с любым другим инструментом - нужно уметь пользоваться.
>И исправить такое поведение для их проекта займет еще N человеко-лет.
Прочитайте предыдущий пост в этом блоге. Там про то как 2 человека за 2 месяца переписали ядро системы, которое писалось большой командой несколько лет (по моим данным 10 чеовек х 5 лет).
>Но его надо использовать вместе.
Вот вот и я о том же. А о чем? О том, что ORM (конкретно NH) умеет всё то, что можно делать без нее:запросы в коде, хранимки, etc. Но при этом для этих случаев предоставляет дополнительные возможность - строгую типизацию и прочие скучные нудные штуки.
Применительно к NH: не хватает каких-то параметров linq - используйте QueryOver или CriteriaAPI; Не хватает - используйте hql; Не хватает - используйте SQL; опять не хватает - используйте хранимки. Но при этом ко всем этому у вас доступны ВСЕ преимущества ORM.
Это как VS и ReSharper. Они дополняют друг-друга.
>> Прочитайте предыдущий пост в этом блоге. Там про то как 2 человека за 2
ОтветитьУдалитьмесяца переписали ядро системы, которое писалось большой командой
несколько лет (по моим данным 10 чеовек х 5 лет).
Я участвовал в 2-х переписываниях одного проекта.
Первое - 6 лет назад. Переписывание ядра заняло месяц. на полтора человека Доведение до релиза - год.
Второе - 3 года назад. Переписываение ядра - месяц-полтора. Доведение до релиза - 2 с половиной года, с сохранением примерно 1/3-ти функционала.
Может быть тем ребятам действительно повезло. Но обычно все заканчивается не так оптимистично.
>>Видимо руки всё-таки кривые
100% ровные. Эти ребята делают одну из самых классных систем для agile project management. Вы наверняка видели или пользовались :) Просто когда возникает подобная проблема, чинить ее уже слишком дорого.
>
ОтветитьУдалитьИнтересно, через какую магию запрос за иерархическими данными через NH будет работать быстрее запроса средствами базы. Вы же знаете что NH работает через обычный SQL
Подход описан в статье,. там много букав, но не поленитесь прочитать.
>При наличии мозга достаточно очевидно, что ORM не обязательно означает именно NH.
В мире .NET это, IMO, безусловный лидер. Никой linq2sql, EnityFramework (да он даже enum не поддерживает http://bit.ly/yqjQdm ) и прочие недо-ORM рядом не валялись.
В мире java его старший брат де-факто является стандартом. В своей сути они идентичны, но есть штуки которые NHibernate ЕЩЕ не поддерживает, а Hibernate уже не сможет поддерживать (linq и компания).
Других платформ в корпоративном секторе нет - ими можно пренебречь. Я не говорю тут про всякие специализированные штуки типа SAP/1c прочей лабудой.
Следовательно ORM => (N)Hibernate.
И еще, если читали Фаулеровскую PoEAA, то не могли не заметить, что 80% книжки про то как написать ORM. А 80% того что там написано применено в (N)Hibernate.
>Можно я оставлю этот кусок в хранимке?
Можно, но вызывайте ее через ORM, и, по-возможности пересмотрите логику работы, возможно вы что-то делаете не так.
>3 года - да, огромный срок :)
Ну... до этого 7 лет в этой компании всё писали на хранимках. Я застал только смерть этого подхода в этой компании: скорость разработки была близка к нулю, при несметном количестве багов, при интеграционном ужасе: починили одно - сломалось другое. Да, ВОЗМОЖНО, это должно было работать быстрее. Но это не работало... никак.
Слава богу, что Саша всё исправил;) : скорость разработки скакнула до астрономических высот (приходишь из недельного отпуска, а это уже "другой проект"). Количество багов снизилось практически до нуля.
Помню 3 года назад мы втроем за 2 недели переписали с нуля продукт, который до этого разрабатывался 3 года, но при этом он не работал: в день в логах IIS было до 20к эксепшенов, пул приложений IIS *принудительно* перезапускался каждые 15 минут. И это всё только для того, чтобы продукт хоть как-то ворочался. Он был написан на хранимках и запросах в коде. Хранимки были самым большим источником *трудноуловимых*, но частых багов.
После перерождения проекта и одного месяца *стабильной* работы, в логах было найдено около десяти (не тысяч, просто десяти) ошибок. И те были вызваны какими-то нестандартными поведениями пользователей пришедших по старым ссылкам из поисковиков.
>
ОтветитьУдалитьЯ участвовал в 2-х переписываниях одного проекта.
"проще это переписать, чем поддерживать" - наверное самая распространенная фраза программиста, когда его просят "вот тут изменить".
>с сохранением примерно 1/3-ти функционала.
В моих 2х случаях удалось сохранить 80% функциональности (остальные 20 отбросили за ненадобностью, но при необходимости портировали бы и их). + Добавили 200% нового.
>Доведение до релиза - год.
>Доведение до релиза - 2 с половиной года
Вы по-любому умалчиваете тот факт, что в релиз была заложена *новая* функциональность, которой не было в старой инкарнации. Иначе зачем переписывать то что работает и не требует изменений: в крупных старых банках есть старые системы, которые работают безотказно уже на протяжении 20-30-40 лет. Работают стабильно и никто не собирается их переписывать (от части потому, что это не нужно и от части потому, что никто УЖЕ не знает как они работают.)
>одну из самых классных систем для agile project management. Вы наверняка видели или пользовались
1. Трудно угадать. 2. Тот факт, что система классная и работает еще не говорит о том, что она написана 100% прямыми руками. Я знаю кучу примеров, когда система классная, а программисты, которым она досталась в наследство вешаются от ее кривого кода.
>3 года - да, огромный срок :)
ОтветитьУдалитьПомериемся письками. За 3 года мы сделали: 3 крупных проекта (10-20 человеко-лет). Несколько средних (1-2 человекогода). И дюжину мелких.
3 года - да, это огромный срок.
Для тех, кому лень читать комментарии повторюсь:
ОтветитьУдалитьПочти любая ORM позволяет писать запросы в коде и использовать хранимые процедуры. ORM это удобное дополнение, выполняющее ЗА ВАС всю рутинную работу. Это как ReSharper и Visual Studio.
Все попытки защиты хранимок напомнили вот эту картинку http://www.practicalecommerce.com/uploads/images/0001/0133/png_vs_jpg.png
ОтветитьУдалить>> Можно, но вызывайте ее через ORM, и, по-возможности пересмотрите логику работы, возможно вы что-то делаете не так.Я не настолько суров, чтобы работать с SQL не через ORM :)
ОтветитьУдалить>> Хранимки были самым большим источником *трудноуловимых*, но частых багов.
Да, но причиной творившегося в этой компании были не хранимки, а принятое решение "все на хранимках, любой ценой". Решение "все на NH, любой ценой" в некоторых случаях приводит к таким же последствиям.
Да, за 3 года можно много чего написать :). Но для не "корпоративного" проекта это слишком короткий срок. Если проект - это основной продукт компании - то его нельзя "сделать и забыть". Проблемы уровня "не угадали через что выбирать данные" вылазят лет через 5 (или через 7, в вашем случае). Нет никакой гарантии, что еще лет через 7 NH не выйдет из моды ;)
Например, на одном из моих текущих проектов решение о выборе ORM принималось в 2006-ом году. Тогда NH был маленький, не поддерживал хранимки, генерики и nullable. И не тянул 2-й дотнет. И не умел очень многое из того, что умеет сейчас. Тогда в моде еще был .netTiers.
Сейчас в этом проекте используется сразу 3 подхода для вытягивания данных, с постепенным переползанием на OMR(не NH). И основные проблемы в проекте сейчас - не работа "не через NH", как ни странно. "Правильный" способ выборки данных - это примерно 0.1% успеха проекта. Вне зависимости от кривизны рук.
>> "проще это переписать, чем поддерживать" - наверное самая распространенная фраза программиста, когда его просят "вот тут изменить".
ОтветитьУдалитьПереписывания шли со сменой бранда, и основная цель была - откушать соседнюю нишу. Т.е. старый проект (продукт) все так же развивается и продается после релиза нового.
>> Вы по-любому умалчиваете тот факт, что в релиз была заложена *новая* функциональность, которой не было в старой инкарнации. В релиз был заложен другой стек технологий. И в последнем случае - очень сильно урезана функциональность (раз в 5), и изменен UI.
Люди в банках не выбирают с чем работать. Люди в интернете, к сожалению, выбирают. Перестанешь бежать вдвое быстрее, переписывать и дописывать то, что и так работает - конкуренты сожрут.
>
ОтветитьУдалитьДа, но причиной творившегося в этой компании были не хранимки, а принятое решение "все на хранимках, любой ценой".
Нет, конкретно в этой компании, не из-за этого, т.к. запросы были и в коде, и использовалась какая-то ORM (не помню какая). Хранимки там использовались по тем же выдуманным причинам, которые привели вы - "не тащить кучу данных", "это быстрее, т.к. компилируется" и т.д.
>Решение "все на NH, любой ценой" в некоторых случаях приводит к таким же последствиям.
"любо ценой", это да. Но нужно понимать, что любым инструментом нужно уметь пользоваться.
>"не угадали через что выбирать данные" вылазят лет через 5 (или через 7, в вашем случае).
Да они там сразу вылезли.
>Нет никакой гарантии, что еще лет через 7 NH не выйдет из моды ;)
Возможно и выйдет из моды, но от этого ничего не изменится для уже написанных приложений.
>"Правильный" способ выборки данных - это примерно 0.1% успеха проекта.
Это смотря с какой колокольни плевать. Во-первых, программирование проекта не больше 10-20% за успех. Во-вторых "успех" это субъективное понятие: проект может быть успешным в коммерческом плане, но полностью провальным в плане разработки и дальнейшей поддержки. Реальный пример - 1С. Для России это стандарт, но от него вешаются бухгалтера, которые вынужденны его использовать, вешаются администраторы, которые вынужденны его поддерживать, вешаются программисты, которые вынужденны разрабатывать кастомные конфигурации. И вряд-ли кто-то сможет занять место 1С в ближайшие 10 лет.
Так что в этом блоге мы говорим об "успехе" проекта с точки зрения его разработки и дальнейшей поддержки. Поддержка хранимок - тот еще ад: мне нужно постоянно помнить какая хранимка какие таблицы, вьюхи и колонки использует.
Мне "легче" вообще не менять схему базы, чтобы ни дай бог ничего не сломать. От этого у меня возникает постоянная проблема: как решить задачу, не изменяя базу данных.
В этих случаях нужно говорить о НОВЫХ продуктах, которые *похожи* на старый.
ОтветитьУдалитьЯ же говорю про переписывание продукта с целью решения проблем в старом и на его замену.
Это абсолютно разные вещи: в вашем случае можно отказаться от старой функциональности, в моем случае - нужно СОХРАНИТЬ всю старую функциональность.
>Перестанешь бежать вдвое быстрее, переписывать и дописывать то, что и так работает - конкуренты сожрут.
Это не всегда верно: есть куча софта, который даже не обновляется и продолжает быть популярным. К примеру WinDjView (последнее обновление в 2009 году)
У хранимых роцедур есть существенный недостаток: как правило они не переносимы и не портабельны между различными базами. Поэтому если ваша система должна работать на нескольких платформах (включая различные БД), то хранимые процедуры точно не ваш путь.
ОтветитьУдалить>>
ОтветитьУдалитьПричем логика обработки довольно сложная, и ее не выразить в запросе
Что это за логика такая, которую не выразить в запросе или в коде на ООП?
>> Так вот, есть вариант тащить все эти сто тыщ записей в слой бизнес логики, и обрабатывать там.
Не надо ничего никуда тащить, ORM может просто отправить нужный запрос в базу.
>> Второй вариант может быть оочень предпочтительней в качестве перфоманса, и никакие плюсы ОРМ подхода тут не перевесят.
SQL Server 2008 Умеет кешировать планы запросов
http://msdn.microsoft.com/en-us/library/ee343986(v=sql.100).aspx
Думаю, что разница в производительности по сравнению с процедурами будет не такой значительной.
Я бы не сказал, что этот недостаток самый существенный. Есть множество других более существенных и более опасных. К примеру, если ваша хранимая процедура сломалась вы узнаете об этом только когда ваше приложение упадёт: обычно RDBMS ничего не говорят о том, что процедура сломалась при манипуляции с базой, они ее просто отключают. Т.е. вам нужно постоянно держать в голове информацию о зависимостях в базе данных, а так же как можно быстрее эту информацию передавать между членами команды.
ОтветитьУдалитьСовсем забыл. Хочу ещё добавить. Иногда приходилось использовать следующий подход для работы с SQL
ОтветитьУдалитьВесь SQL запрос и его обработка прячется в класс. В БД есть такое понятие VIEW (виртуальные таблицы).
Получается что-то такое же, для всего внешнего мира это объект с полями и методами, а для БД - это лишь запрос.
Такую штуку можно реализовать и средствами ОРМ. Для этого придется создать реальную VIEW в БД и честно использовать ОРМ для этой таблицы.
Использую ORM для работы с ХП. А на самом деле все зависит от того какие требования к проекту.
ОтветитьУдалитьНаписал тут блогопост со своим мнением на этот счет.
ОтветитьУдалитьhttp://blog.hazzik.ru/post/19463059043
В очередной раз не дочитал срач развернувшийся в комментариях к статье Александра. А все почему? Потому что народ у нас очень любит бросаться из крайности в крайность и тупо следовать "мейн стриму". Ну не было раньше ни IoC, ни DDD ни явно вырожденных серверов приложений, и что? Системы написанные без всей этой тягомотины не работают? Работают, поверьте уж, и работают прекрасно, и что самое страшное, до сих пор сопровождаются и развиваются!
ОтветитьУдалитьВот заметил очень много комментариев про крутизну NH L2-кеша, а вы сравните средства оптимизации запросов и кешей Oracle и Nh, только потом не напивайтесь с расстройства. Дублирование логики в процедурах? Я вас умоляю, только не говорите что основная проблема это что в PL/SQL пакет нельзя инжектировать зависимости :)Я все это к чему, я никогда не считал и не считаю что тот-же ORM это всегда плохо, но он должен быть уместен! Если у меня стык с 3-мя организациями на уровне БД-БД и системе всего-то надо показать 3 формочки с графиками-отчетами, то под страхом смертной казни там не будет ORM-а, а если же это те же три формочки но система уже по, например, продаже товара для пивного ларька, то там, возможно, и будет ORM. Еще раз, всему свое место и каждой разработке, каждому куску проекта так же должны быть подобраны свои, наиболее оптимальные и подходящие средства. Паттерны это бесспорно хорошо, но применение всего должно быть много раз обдумано и обосновано, а не потому что про мы уже стопиццот проектов так сделали. Если у вас есть феррари, вы на нем и по бабам, и на треке и в тундру за грибами поедете? Что-то мне подсказывает что нет. Ну и еще раз на последок. It depends, и хватит устраивать холивары анемик-DDD, хранимка-ORM при этом не вдаваясь в подробности в какой системе, в какой среде это используется и какие требования к срокам и проекту в целом.
Вы серьезно? Отделите плз мух от котлет.
ОтветитьУдалитьRepository - Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects
ORM is a programming technique for converting data between incompatible type systems in object-oriented programming languages
Саша, только не надо забывать, что клиентом для БД может быть и тонкий клиент в виде Microsoft Excel с его Pivot Table. Не всегда enterprise пирложение имеет удобную форму представления и анализа информации о продажах, например. Работа с Pivot Table доступна для создания пользователями аналитического отдела, т.е. есть возможность делегирования из отдела разработки в аналитический... В этом случае хранимые процедуры спасают.
ОтветитьУдалитьПонятно, что в этом случае нет смысла использовать ORM.
ОтветитьУдалить>> Хранимки там использовались по тем же выдуманным причинам, которые
ОтветитьУдалитьпривели вы - "не тащить кучу данных", "это быстрее, т.к. компилируется" и
т.д.
Во первых я вообще ровно про одно место упоминал (и один проект), где лично я использовал хранимки. И не вам решать, по выдуманной причине, или нет. Лично для меня важно что то место работает в 100-200 раз быстрее, чем аналогичное с "тащить все в память", и за год там не найдено ни одного бага.
По поводу "это быстрее, т.к. компилируется" - не могли бы вы процитировать мое сообщение, где я такое заявил? У меня сложилось впечатление, что вы считаете меня фанатом хранимок, и пытаетесь мне что-то доказать. Если это так - то не тратьте силы зря - я как фанат ОРМ и ООП уже лет так 7-8. Просто для меня хранимки - это один из инструментов, а не средоточение мирового зла.
Я вполне серьезно. Если вы знаете как использовать Repository поверх реляционной базы, не используя при этом Object-relational mapping - расскажите. А не цитируйте википедию.
ОтветитьУдалитьSimpliestDomainObjectRepository : IEntityRepository {
ОтветитьУдалитьpublic DomainObject Get(long id) {
var reader = Database.OpenReader("select * from table where id = :id");
var res = new DomainObject();
res.Id = reader["Id"];
return res;
}
}
Сейчас придут фанаты SRP и начнут кричать что он нарушен.
ОтветитьУдалитьВаш пример не попадает под ваше же определение "Mediates between the domain and data mapping layers". Т.к. сам SimpliestDomainObjectRepository сам занимается data mapping-ом, а не должен. И у Александра, которому я отвечал, Data Mapper явно отдельно существует.
Я особо не заморачивался над дизайном, а просто привел запрошенный вами пример псевдокода репозитория без использования ORM в наиболее явно виде.
ОтветитьУдалитьПо поводу не попадания, реализация скрыта за интерфейсом репозитория, и с т.з потребителя - все по феншую т.к. нужная прослойка есть, с точки зрения реализации можно вынести отдельно еще и маппер/запросовыполнитель, но опять же если это действительно надо :) так что думая про SRP не забываем про KISS и "It depends" :)
>
ОтветитьУдалитьи за год там не найдено ни одного бага.
Я рад, что вам не пришлось сталкиваться с таким ужасом, с которым приходилось сталкиваться мне.
>Лично для меня важно что то место работает в 100-200 раз быстрее, чем аналогичное с "тащить все в память",
Мне доводилось видеть тысячекратное ускорение, при отказе от хранимок в пользу ORM и параллельной обработки через NSB.
>где я такое заявил? Вы - нет, но кто-то тут точно это говорил. Факт в том что этот предлог такой же выдуманный, как и тот, что написали именно вы.
>У меня сложилось впечатление, что вы считаете меня фанатом хранимок, и пытаетесь мне что-то доказать.
Нет и нет.
Пытаюсь не доказать, а донести мантру:
1. Не используйте хранимки
2. Вам нужно использовать хранимки? См. п.1
3. Вы точно уверены, что нужно использовать хранимки? Еще раз взвесьте и используйте с осторожностью.
>> Вы - нет, но кто-то тут точно это говорил
ОтветитьУдалитьвот и пытайтесь образумить этого "кого-то", и мантру свою доносите до него же. я то тут при чем?
>> Факт в том что этот предлог такой же выдуманный, как и тот, что написали именно вы.
Это для вас он выдуманный. А для меня на, в конкретном месте на конкретном проекте - суровая реальность. В отличие от общего "хранимки компилируются", который действительно притягивают за уши.
>> Пытаюсь не доказать, а донести мантру:
А с чего вы взяли что именно до меня ее нужно доносить? Вы что, считаете меня студентом-джуниором с нулевым знанием архитектуры?
Есть одна основная мантра - It Depens. Все остальное - от лукавого.
>
ОтветитьУдалитья то тут при чем?
Да не переходите вы на личности. Я же вам не в личной почте доказываю, да и не вам вовсе, а всем тем кто это будет читать.
Сомневаюсь, что фанаты "чисто хранимок" внемлют вашим доказательствам, особенно если учесть что в комментариях они не отметились, а вы уже успели обвинить их в сильной кривизне рук.
ОтветитьУдалитьБуду надеяться что они все вымерли или образумились.
ОтветитьУдалить> но применение всего должно быть много раз обдумано и обоснованоПока вы будете думать, кто-то уже сделает.
ОтветитьУдалитьИнтересный аргумент. Видать народная мудрость на пустом месте возникла и Вы будете сразу пилить, пока кто-то будет мерить. Ну или, продолжая начатую аналогию с авто, вы сядете в свой феррари и ломанетесь в лес не раздумывая, да, туда долетите быстрее, а потом сидя по ... крышу в грязи будете с интересом смотреть на плавно проползающий мимо трактор конкурентов :)
ОтветитьУдалитьДа, я сяду и сразу ломанусь в лес на своем Феррари. И вот почему:
ОтветитьУдалить- TDD,
- "Преждевременная оптимизация - корень зла в программировании" (С) Энтони Хоар http://en.wikipedia.org/wiki/C._A._R._Hoare
В современном информационном обществе принцип "семь раз отмерь - один отрежь" уже не работает, а работает другой - "кто раньше встал, того и тапки".
NH кеш научился работать на нескольких серверах?
ОтветитьУдалитьХранимые процедуры поддерживают несколько серверов? О.о
ОтветитьУдалитьда, есть провайдеры с поддержкой webfarm/webgarden
ОтветитьУдалитьда, например через linked servers.
ОтветитьУдалитьСпасибо, я пожалуй откажусь.
ОтветитьУдалить- TDD не спасет, если большую часть кода, покрытого тестами, вам придется выкинуть. Или если окажется, что она вообще была не нужна, а нужно было наколбасить формочек на стыке трех баз.
ОтветитьУдалить- "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil"
Не стоит забывать про 3 процента времени, когда лучше отключить фанатизм и принять обдуманное решение. В аналогии про машины - это как раз та минута, когда вы, зная про лес и кочки, делаете шаг в сторону феррари, а не трактора. А small efficiencies - это как раз возможность долететь на феррари до съезда в лес, сэкономив аж 5 минут на дорогу.
теоретики такие теоретики
ОтветитьУдалить