Так нужен ли ORM в крупном и сложном Enterprise-проекте?

    Недавно на Хабре мелькал вопрос — так нужен ли на самом деле ORM в крупном и сложном проекте? Ведь он часто медленный, громоздкий, поддерживает только некоторое подмножество SQL, не поддерживает специфический и очень удобный синтаксис, например, Oracle (тот же connect_by для иерархических запросов) и прочее и прочее.

    Высказывалось мнение, что ORM в действительности нужен только в примитивных проектах, для сокращения размера кода, а в реально большом и сложном проекте лучше обойтись без него. Я скажу за большие проекты — за мелкие пусть скажут другие :) Оговорюсь, что рассуждения и примеры строю на Java / Oracle, классическая связка.

    Почему необходим ORM


    Сам по себе ORM, именно как mapping, в крупных проектах нужен как раз очень сильно.

    Представьте себе — у меня есть очень крупная система, и есть в ней таблица orders, на ней скажем, 50 колонок (на самом деле у нас 150, ну да ладно. Нормализаторы, молчать! Про нормальные формы я тоже знаю). И вот надо представьте, что вам выбрать один ордер и показать его на экране. Допустим, вы пишете селект, вопрос — дальше что делать с его результатами, в промежуточном слое, в server-side Java? Вы не же вызываете хранимую процедуру или запрос напрямую с, скажем, JSP страницы (я надеюсь), вам все равно надо получить данные и передать их как-то, в виде какой-то структуры данных.

    Так что же, передавать их в виде массива, ArrayList-a, ассоциативного массива как [имя колонки: значение]? Это громоздно, неудобно, и очень легко ошибиться. А если вам надо несколько ордеров, тогда что, создавать вложенные коллекции для конвертации результатов? Это по своему вредному влиянию будет уже напоминать известный антипаттерн «Строковая типизация». Использовать коллекцию векторов или ассоциативных массивов там, где можно использовать коллекцию объектов типа Order.

    Мы нашли пример случая, нам нужен объект Order, имеющий все нужные property, и, следотельно, нам нужен код, который умеет конвертировать результаты SQL запроса в объекты (коллекцию таких объектов).

    Далее, очевидно, что писать руками все запросы трудно и нудно, легко ошибиться, т.к. в Java они будут представляться или в коде в виде строк (а значит, никакой статической типизации и compile-time проверок), и их надо держать либо в Java коде (если они мелкие, и все равно получается замусоривание Java кода), либо, если побольше, выносить в отдельные XML файлы.

    Здесь небольшое лирическое отступление. Спор — держать ли SQL код коротких запросов прямо в Java коде, или же выносить их в отдельные файлы в Enterprise-e идет уже долго.
    Аргумент за то, чтобы держать из внутри Java кода — вместе используемый код находится рядом, код SQL запроса легче найти и посмотреть, чем если он лежит где-то отдельно, в случае изменений в VCS надо будет не забыть изменить только один файл, а не два.
    Аргумент за разделение по разным классам — многострочные SQL запросы сильно замусоривают Java код (в том числе потому, что Java не поддерживает полноценно многострочные строковые литералы в отличие от, скажем, того же Groovy) + если они определены как константы класса, то при изменении содержимого этой константы сделать java hotswap, например, уже не получится. Я сам обычно смотрю по обстоятельствам :)

    В общем, ORM в больших проектах нужен для упрощения рутинной части. Без него — никуда :)

    Почему нужен чистый SQL


    Безусловно, обойтись ТОЛЬКО ORM не получится. Есть у нас масса мест, где сложная логика написана в запросах хранимых процедурах в 500-1000 строк на PL/SQL, ибо написанная через ORM /Java она бы занимала в 10 раз больше места и работала в 2 раза медленнее (при этом, она была бы еще и менее понятна, т.к. есть такая логика, которые в терминах реляционной алгебры описывается проще, чем в терминах ООП :), и такая логика ложится на ORM со скрипом). Сколько нибудь сложные запросы с подзапросами, юнионами, хитрыми джойнами тоже писать через чистый ORM громоздко. Оптимизировать запросы, работающие с таблицами где, хотя бы, несколько сотен миллионов записей, без доступа к планам SQL оптимизатора и статистики/средствам мониторинга уровня СУБД (для Oracle это Explain Plan, tkprof, Grid Control) тоже крайне сложно. Так что без SQL тоже — никуда :)

    Можно поговорить о том, как все-таки немного подсластить работу с чистыми SQL-запросами в крупном проекте.

    Один из вариантов — использование макросы. Пишется свой фреймворк для написания SQL макросов (в сущности, движок для выполнения умеренно примитивных парсеров, позволяющий людей писать собственные макросы и парсеры к ним). Макросы могут помочь решать следующие задачи:
    • Вынесение реюзабельных частей запросов (обычно, подзапросов) в отдельные скажем так, именованные SQL-компоненты, и включение их затем в запросы с помощью макроса
    • Унификация некоторых надоедливых различий в синтаксисе SQL, например когда параметр запроса может быть скалярным числом, а может быть массивом, тогда вы пишете макрос, которые абстрагирует вас от отличия между t.property = x и t.property in (x1, x2)
    • Добавление предикатов в where clause в целях безопасности
    • Оборачивания всего запроса в SELECT * FROM (query body) t order by… для унифицированной поддержки сортировки и paging-a

    и многое другое.

    О переносимости между различными СУБД


    Да, и еще, напоследок. Я ни слова не сказал тут о совместимости с разными СУБД, т.к. это часто ненужное требование. Большие и сложные системы активно использует СУБД-specific фичи (расширения синтаксиса SQL, синтаксис процедурных расширений, таких как PL-SQL, T-SQL, pgplsql вообще отличается очень сильно, схемы секционирования и прочая, и прочая), и требования писать SQL-код, одновременно совместимый с Oracle/MSSQL/DB2 часто не ставится (я перечислил тут классические признанные Enterprise-level СУБД, поклонникам остальных просьба не обижаться). Все понимают, что это — огромное усложнение и удорожение системы, далеко не всегда оправданное. Подлинная независимость от серьезного вендора, такого например, как Oracle или IBM — стоит дорого, очень дорого. А часто ли она реально нужна?
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 219
    • 0
      На питончике использовал потому, что нужно было запускать проект на MySQL, PgSQL, Oracle и Sybase. Т.к. Oracle и Sybase у меня не было возможности поставить, то SQL Alchemy отлично подошел. Помимо этого сократил время разработки.

      Естественно, если бы я все делал на знакомом мне MySQL, то ORM бы не стал использовать, т.к. многие запросы она делает совсем не логично.
      • +2
        А вот в джанго ORM очень удобный. Но проекты на нем такие большие, как на J2EE, нормально не сделаешь.
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            Банально сложнее и нет практик.
            • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                Не те практики. К примеру посмотрите Spring Framework. И сравните с django
            • 0
              Ну например в джаве есть EJB, которые созданы изначально для распределенных приложений, которых в джанго нет. Ну и спринг (хотя есть какой-то спринг под питон, но я его не пробовал).
        • +1
          Есть опыт работы с NHibernate, переход на чистый ADO.NET на порядок увеличил производительность. К тому же, при использовании для всяких advanced штук в NHibernate часто вылезают баги и недоделанные реализации драйверов под СУБД. Сам низкоуровневый исходный код явно изначально был сконвертирован из Java, и очень сложен в сопровождении.

          Так что в этом смысле, NHibernate годится только для простых проектов.
          Возможно, с оригинальным Hibernate ситуация лучше. Но те же lazy-техники с коллекциями в сотни тысяч элементов часто проще реализовать на уровне ADO.NET/JDBC с постраничной подгрузкой.

          • +13
            Любой ORM требует аккуратного обращения. Прежде чем использовать ORM надо уметь делать приложения без его применения.
            • 0
              Так никто не спорит. Я просто привел конкретный пример, когда прямая работа с СУБД выгоднее использования ORM. Каждому свое, все зависит от задачи.
              • +8
                В хорошем ORM есть средства для работы напрямую с СУБД ;)
                • –1
                  ага, только в этом случае нет необходимости в ORM ;)
                  • 0
                    Не сказал бы. К примеру если у вас используется MVC для web-приложения, то лучше как раз использовать ORM, а там где это уже не оправдывает себя использовать чистый SQL.
                    • +1
                      Не спорю. Я уже выше писал, что все зависит от задачи. В данном конкретном случае запуск SQL-скрипта через ORM ничем не лучше исполнения запроса напрямую. Опять же, по опыту с NHibernate даже здесь заметна разница в производительности (раза в два), видимо выполняется какая-то пред- или постобработка.

                      Кстати, есть такая интересная штука — MyBatis (раньше назывался iBatis). Это не совсем ORM в традиционном понимании. И производительность в нем вроде практически эквивалентна прямому исполнению SQL (разумеется, при сравнении с ручной генерацией объектов). Он просто позволяет с помощью XML-конфигурационных файлов вынести скрипты INSERT/UPDATE/DELETE, написать интерфейсы объектов и MyBatis сам их замаппит. Получается такая легковесная ORM. Есть под .NET и Java. Подробнее: www.mybatis.org/
                      • 0
                        Я предпочитаю использовать JPA :) Там разницы нет особой. MyBatis я видел, не сказал бы что особо хорошо при сложной базе.
                        • 0
                          JPA это стандарт… а реализаций этого стандарта несколько… например хибернейт его вполне поддерживает…
                          • 0
                            Я бы даже сказал больше. JPA это стандарт, набор интерфейсов. Он отстает по развитию от Hibernate, и по сути пишется с него. Поэтому это наиболее распространенная реализация. Хотя в последнее время уже появляются и другие реализации, да.
                            • 0
                              Черт знает с чего он там пишется, но у него есть один не маловажный плюс. Он декларативный и второй версией пользоваться удобно. У первой версии были кое-какие неудобные ограничения, но в двойке их уже нет.
                            • 0
                              Я использую EclipseLink
                            • 0
                              Или вы свою реализацию JPA имели ввиду? Тогда извините…
                          • –1
                            MVC это чисто UI часть, ORM — это доступ к данным и по наличию MVC определять необходимость ORM — весьма странная затея. ))
                            • –1
                              M — в MVC это model. А он к ORM имеет отношение.
                              • 0
                                Модель в рамках MVC, не имеет никакого отношения к ORM.

                                MVC в первую очередь паттерн, который описывает взаимодействие между слоями. Но не накладывает никаких ограничений на технологии используемые в том или ином слое.

                                Если уж говорить про то, когда выгоднее всего использовать ORM, с точки зрения архитектуры приложения, то скорее всего вы замете связь между реализацией слоя бизнес логики по паттерну доменная модель и технологией ORM. Вот тут, при реализации такого подхода, плюсы ORM очевидны.
                                • 0
                                  Не накладывает, но удобнее использовать там именно ORM.
                                  • 0
                                    Может быть вы про конкретно Asp.Net MVC?

                                    Если про паттерн в целом, то не соглашусь. Хотя нет, соглашусь, но из за того, что ORM всегда удобнее использовать и дело не в MVC паттерне. :)
                                    • 0
                                      Не я не про него :) Именно что всегда удобнее использовать :] А удобнее из-за того что обычно ООП :]
                                      • 0
                                        Все вы хотите что то к ORM притянуть за хвост. Зачем?

                                        Ну ООП? И что? Т.е. вы подразумеваете что если ООП то полюбому ORM удобнее использовать? Ну че за бред то? :(

                                        Вы ищите какое то золотое объяснение использования ORM. Не надо. Поймите чем хороша технология сама по себе. Что она дает по сравнению с другими (вот тут сейчас важно) ПОДОБНЫМИ технлогиями, которые решают туже задачу. И выясните с помощью какой технологии вам удобнее решать эту задачу. Но не тяните сюда какие то бессмысленные объяснения.
                                        • 0
                                          Все вы хотите что то к ORM притянуть за хвост. Зачем?

                                          Там где это удобно это надо делать.

                                          Т.е. вы подразумеваете что если ООП то полюбому ORM удобнее использовать? Ну че за бред то? :(

                                          Если вы работаете с MVC в ООП среде, то обычно Model это объект или коллекция объектов. В случае если вы не хотите ничего ломать у вас где-то возникнет хоть какой-то примитивный ORM который будет маппить данные из базы в объекты и обратно.

                                          Вы ищите какое то золотое объяснение использования ORM. Не надо. Поймите чем хороша технология сама по себе.

                                          Я использую технологии только там где они приносят profit, если они его не приносят я его там не использую.
                                          • 0
                                            Там где это удобно это надо делать.


                                            Там где удобно тащить за хвост, надо тащить за хвост? :) Я тут говорил не про применимость ORM, а про ваше объяснение причин использования ORM. Объяснения, которые вы тяните за хвост.

                                            Если вы работаете с MVC в ООП среде, то обычно Model это объект или коллекция объектов. В случае если вы не хотите ничего ломать у вас где-то возникнет хоть какой-то примитивный ORM который будет маппить данные из базы в объекты и обратно.


                                            Уважаемый, хочу подчеркнуть что я сторонник ORM. Я часто использую ORM. Но причины этого не использование MVC + ООП. Поймите что здесь нет связи.

                                            Я могу разрабатывать приложение с использованием MVC + ООП, без использования ORM и не надо будет ничего ломать. Вообще ничего. Будет полноценный MVC. И я буду использовать ООП где захочу (если честно я вообще не понимаю зачем вы ООП притянули сюда).

                                            Я использую технологии только там где они приносят profit, если они его не приносят я его там не использую.


                                            Вы немного вытащили мои высказывания из контекста. Безусловно нужен profit. Ток этот profit вы сможете выяснить ток в том случае, если знакомы с другими технологиями. Именно это я и говорил.
                                            • 0
                                              Я тут говорил не про применимость ORM, а про ваше объяснение причин использования ORM. Объяснения, которые вы тяните за хвост.

                                              Вообще я проводил причины почему стоит это делать. Если вас они не устраивают вы можете и не использовать.

                                              Но причины этого не использование MVC + ООП. Поймите что здесь нет связи.

                                              Не делайте не верных выводов. Я сказал только что в MVC удобно использовать ORM в силу того что MVC применяется чаще всего вместе с ООП и M чаще всего представлен как объект или коллекция объектов. А вы тут напридумывали что я из-за MVC использую ORM.

                                              • 0
                                                Не делайте не верных выводов. Я сказал только что в MVC удобно использовать ORM в силу того что MVC применяется чаще всего вместе с ООП и M чаще всего представлен как объект или коллекция объектов. А вы тут напридумывали что я из-за MVC использую ORM.

                                                К примеру если у вас используется MVC для web-приложения, то лучше как раз использовать ORM

                                                Извините, но из ваших слов у меня складывается именно такое представление.

                                                Если вы имели ввиду что то другое, приношу свои извинения. :)

                                                • +1
                                                  И все таки, в рамках MVC, даже с использованием ООП :), модель чаще всего объект или коллекция объектов, не из за того что используется ООП в рамках MVC. :) А из за того, что при построении бизнес логики очень хорошо зарекомендовал себя паттерн DomainModel (по Фаулеру). Вот ЭТА штука, очень хорошо ложится на ORM.
                                      • 0
                                        Кому как. Мне в последнее время удобно использовать ODM (Object Document Mapping), а не ORM, особенно когда работаю с документоориентированными СУБД, а не реляционными :)
                                        • 0
                                          Да, согласен, кому как.

                                          Вы кстати какие СУБД документоориентированные используете? И на чем у вас клиент? Просто интересно. Тут знакомые мне хвастатлись про одну СУБД такую, интересно ваше мнение.
                                          • 0
                                            MongoDB выбрал, но в принципе чисто из-за того, что ODM для неё «от Doctrine» в beta3, а не alpha1 стадии как для CouchDB :) Переход не исключаю, и даже чуть ли не в планах, сама Кауч по идеологии нравится больше.

                                            Клиент на html5 :) Апп сервер на php (Смотрел другие варианты, но преимуществ, оправдывающих серьёзное изучение других технологий при поверхностном не обнаружил, на PHP напишу быстрее. Была бы РСУБД — были бы варианты, а с документоориентированными инструментами ориентированными на отсутствие схемы БД как-то везде плохо, особенно в статических языках, но задачи типа «создание пользовательских объектов (и их типов даже) с произвольным количеством и типов атрибутов, включая составные» на реляционную модель как-то плохо ложатся).
                                            • 0
                                              Спасибо! Мне кстати знакомые как раз про MongoDB говорили. :)

                                              За клиента на HTML5 респект! У нас пока ток в планах, далеких. Ждем новой винды и будем смотреть чего там MS сделает с Silverlight + WPF. Правда ли на HTML5 + JS перейдет. Если перейдет, то бум думать. :)
                                  • +1
                                    >MVC это чист UI часть

                                    Более бредового высказывания про MVC не слышал. :)
                        • 0
                          Да, NHibernate это и есть порт ява-версии на .NET, разумеется.

                          Насчет коллекций в сотни тысяч элементов… Тут я весьма скептичен вообще.

                          Если вам реально нужно вытаскивать такие объъмы на клиента, то вытаскивать их в одну коллекцию сразу целиком в память нельзя, т.к. может запросто быть OOM или просто будет отъедено непозволительно много памяти. В таком случае лучше использовать streaming и передавать данные из курсора (result-set-a) порциями фиксированного размера сразу туда, куда нужно.

                          Так же, в реальности, если вам это нужно для какой-то сложной аналитики, обычно куда проще пре-агрегировать эти данные на уровне СУБД в какой-то временной таблице или materialized view, и использовать дальше в рассчетах, тащить их все на промежуточной слой далеко не всегда нужно.

                          • 0
                            О том и речь. Трудно себе представить, чтобы пользователю реально нужно было просмотреть все сто тысяч. Но выводить Grid с таким количеством элементов на уровне хранилища — такая задача часто встречается. Пользователю удобно выполнять сортировку, фильтрацию, скроллинг по всем данным. Но вот на клиент нужно подгружать только страницу отображаемых в данный момент данных. Т.е. у пользователя на уровне интерфейса создается полная иллюзия работы с огромной коллекцией. А по факту выполняется подгрузка/выгрузка данных в режиме on demand.

                            Для таких задач ORM неприменим, либо наблюдается серьезный проигрыш в производительности/памяти.
                            • +4
                              а в чем проблема подгружать нужные страницы через ORM?
                              • 0
                                Не все ORM умеют и не все знают что так можно :)
                              • +1
                                «Для таких задач ORM неприменим»
                                Да что вы говорите???

                                Именно для подобных сценариев в том же Nhibernate поддерживается кэш первого и второго уровня, продвинутый lazy-loading и масса других пирожков.

                                Любая серьезная ORM обязана уметь как минимум lazy-load-ить, и загружать данные постранично.
                                • 0
                                  В теории оно все так. На практике конкретно в NHibernate lazy-loading коллекций реализован не так уж хорошо в плане производительности и используемой памяти. Ну и опять же, для построения Grid'а с сортировкой по разным столбцам коллекции не подходят (хотя да, подходит исполнение запросов на hql), но там опять же вылазят эти lazy-коллекции. Возможно, в других «серьезных ORM» ситуация лучше.
                            • 0
                              NHibernate годится для конкретных штук. В частности, и Ayende не раз об этом упоминал — OLTP-сценарии. Народ часто начинает гнать на NH, попытавшись использовать его для ETL (batch processing) или OLAP.

                              Насчет того, что только для простых проектов — не соглашусь.
                              • 0
                                Ниже уже писали в комментах, что ORM проявляет себя лучше всего при не очень сложной структуре данных и не очень больших объемах данных, подтягиваемых «за раз». Когда основная трудоемкость в бизнес-логике, накрученной над этими данными. При этом сами проекты могут быть очень и очень сложными.
                            • +3
                              ORM выгодно использовать в случае если приложение заточено под работу оператора с объектами от одного до десяти. Проще говоря нет никаких яростных табличных интерфейсов и требуется достаточно сложная логика при обработки объекта. А такой класс приложений очень велик и это подавляющее большинство веб-приложений.
                              • +2
                                Я и не думал, что мой вопрос так всбудоражит.
                                • +15
                                  Просто это очень старый срач «ORM vs pure SQL», но видимо о нем все забыли. Я еще года 3 назад попадал в подобные даже чаще, чем в срачи про РНР. Эта тема вбрасывает так же как «зачем Linux на десктопе», только если второе уже всех достало, про ORM давно все забыли и можно посраться заново.

                                  Думаю краткое содержание предыдущих серий вам рассказывать не надо, в комментариях к вашему вопросу можно встретить все типичные ответы обоих сторон для подобного срача. Остальные читайте там ↓
                                • +2
                                  Недавно прочел ORM is an anti-pattern мнения автора статьи в чем-то пересекается с вашим. Вкратце плюсы-минусы:
                                  1. ORM проще понять, чем SQL (можно и не знать SQL если использовать ORM)
                                  2. Он эффективен на ранних стадиях (по быстренькому чего-нить написать)
                                  3. Если приложение усложняется, то все плюсы ORM гаснут — приходиться учить SQL, дописывать…
                                  4. 20+% проектов ломают абстракцию ORM
                                  5. Объекты — это не адекватный способ представления реляционной структуры
                                  6. Если ваши данные — объект, то лучше использовать NoSQL-решения
                                  7. Из-за реляционной природы появляются накладные расходы при создании объекта

                                  Почитайте, достаточно интересное мнение + интересные отзывы в коментах
                                  • +7
                                    ORM проще понять, чем SQL (можно и не знать SQL если использовать ORM)

                                    Отправлять изучать SQL. Никакого ORM пока нет понимания во что он транслирует и как. Иначе такие чудеса будут…

                                    Он эффективен на ранних стадиях (по быстренькому чего-нить написать)

                                    Как я уже говорил он эффективен когда у вас мало данных много действий.

                                    Если приложение усложняется, то все плюсы ORM гаснут — приходиться учить SQL, дописывать…

                                    См. ответ на пункт один :)

                                    Объекты — это не адекватный способ представления реляционной структуры

                                    Генерация объектов ORM должна идти от таблиц в базе, а не наоборот. В этом случае этой проблемы у вас не возникнет. В любом случае умеет или не умеет это ORM сначала должна быть спроектирована схема базы. А уже потом на ее основе созданы объекты. Это залог жизнеспособности решения.

                                    Если ваши данные — объект, то лучше использовать NoSQL-решения

                                    Кто вам сказал что это лучше? Оно лучше на очень малом спектре задач.

                                    Из-за реляционной природы появляются накладные расходы при создании объекта

                                    Кеширование объектов спасает :)
                                    • +1
                                      Во многом я с вами согласен. Те пункты — это выдержки из статьи и с какими-то из них можно согласиться, да и просто интересно мнение «другой стороны».

                                      ORM это абстракция/инкапсуляция т.е. теоретически можно инкапсулировать как SQL так и NoSQL и не знать ни один из них, однозначно нельзя сказать будет ли лучше со знанием основ или нет. Например, вы можете не знать как устроена машина, но водить можете. Если вы будете изучать строение авто, то не известно поможет ли вам сэкономить деньги, скажем, на починке, то потраченное на изучение время.

                                      «Как я уже говорил он эффективен когда у вас мало данных много действий» — безусловно.

                                      «Кто вам сказал что это лучше? Оно лучше на очень малом спектре задач.» — момент спорный. Можно мыслить реляционно и тогда реляционная БД в большинстве случаев будет для вас лучше, а можно мыслить документами, тогда мнение может измениться. Я ни в коем случае не говорю, что NoSQL > SQL.

                                      «Кеширование объектов спасает» — вы предлагаете обход/маскировку проблемы :)
                                      • 0
                                        Можно мыслить реляционно и тогда реляционная БД в большинстве случаев будет для вас лучше, а можно мыслить документами, тогда мнение может измениться. Я ни в коем случае не говорю, что NoSQL > SQL.

                                        Основное больное место NoSQL это агрегация. Как только надо что-то из хранимого обработать агрегативно и тут что называется приплыли. Реляционная модель во многих случаях лучше и дает большую производительность. И что самое главное можно дать оценку производительности. В случае NoSQL это не всегда так, да и правильное его применение сложнее.

                                        вы предлагаете обход/маскировку проблемы

                                        Оно работает :)
                                      • –3
                                        >> Отправлять изучать SQL. Никакого ORM пока нет понимания во что он транслирует и как. Иначе такие чудеса будут…

                                        т.е. прежде чем писать на C# надо изучить IL!
                                        • +6
                                          Вообще изучение любого низкоуровневого языка полезно, для понимания что же там будет на выходе. Но в случае ORM совершенство трансляции существенно ниже. Из-за этого надо учитывать особенности работы СУБД и не делать выборки вида select * from из двух таблиц чтобы что-то посчитать. А такие ошибки на уровне ORM делаются на раз.
                                          • 0
                                            я с вами согласен, более того, вы говорите очевидные вещи. Просто вставил ироничную аналогию.
                                        • +2
                                          Генерация объектов ORM должна идти от таблиц в базе, а не наоборот.

                                          Вот тут я с вами не соглашусь. Все зависит от точки зрения — строим базу данных для приложения, или приложение для базы данных.

                                          Замечу, что подход, где приложение первично, заметно выигрывает по простоте разработки и надежности.
                                          • 0
                                            Все зависит от точки зрения — строим базу данных для приложения, или приложение для базы данных.

                                            Еще раз напоминаю реляционная модель беднее чем объектная.

                                            Замечу, что подход, где приложение первично, заметно выигрывает по простоте разработки и надежности.

                                            Только пока у вас простая модель данных. Как только у вас в базе будет больше 20-30 таблиц этот подход будет проигрывать. Особенно если у вас будет много данных. Вы можете не соглашаться, но это так.
                                            • 0
                                              Спор на тему что использовать: DatabaseFirst\CodeFirst. В первую очередь зависит от самой ORM, и что она позволяет делать. Поэтому про сложность использование того или иного подхода, следует отнести к богатству/бедности той или иной ORM реализации.

                                              Но если например взять подход ModelFirst, который возможен с использованием EntityFramework, то вы будете удивлены, плюсы того и того там присутствуют. Другие минусы, конечно, тоже. :)

                                              А вообще спор на тему SQL or ORM. ;) Всегда поражался широте спора хабражителей. :)

                                              • 0
                                                Спор на тему что использовать: DatabaseFirst\CodeFirst.

                                                Очень часто те кто использует ORM и CodeFirst пишут приложение большая часть логики направлена на работу с СУБД. А это проводит к плачевным последствиям.
                                                • 0
                                                  Не вижу зависимости. CodeFirst и логика работы с СУБД не вяжется у мну. Раскройте пожалуйста.
                                                  • 0
                                                    К примеру у вас есть приложение обладающее сложной структурой данных. К примеру биллинг. Если вы начнете сначала писать код, а потом с нее генерить базу у вас будет ад и израиль.
                                                    • 0
                                                      Это у вас будет ад и израиль. А у меня, с использованием EF и головы, будет все ок. И не один большой проект писали через CodeFirst. Живы и здоровы.

                                                      Безусловно проблемы есть всегда. Но скорее проблемы технологии, а не подхода.
                                                      • 0
                                                        ER-диаграмму предварительно рисуете или нет? :)
                                                        • 0
                                                          А какое это имеет отношение к тому, что из чего генерируется, что я использую CodeFirst или DatabaseFirst? Вы хотите сказать что я заведомо подразумеваю что это все будет ложиться на реляционное отображение? Так вот, конечно я это подразумеваю, и буду проектировать свою доменную модель так, что бы ее можно было замаппить без последствий на реляционное отображение. И если вы думаете что кто то начнет использовать по максимуму наследование и полиморфизм, то вы ошибаетесь. И если даже кто то начнет, то проблема не в подходе CodeFirst, а проблема в не знании технологий.

                                                          Тут вопрос понимания технологии играет роль. И если человек знает что такое ORM, он не встретит никаких проблем при использовании подхода CodeFirst.

                                                          А ER иногда рисуем, иногда нет. Иногда рисуем диаграммы классов, иногда нет. Иногда используем еще что то. Но проблем в подходе CodeFirst, не более чем в любом другом.
                                                          • 0
                                                            А какое это имеет отношение к тому, что из чего генерируется, что я
                                                            использую CodeFirst или DatabaseFirst?

                                                            Прямое. ER-диаграмма это результат проектирования базы данных. Если она у вас есть, то разницы от entities генерить таблицы или entities генерить от таблиц нет. Это только метод генерации уже готового проекта базы. И в этом случае это не CodeFirst.

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

                                                            Это и есть DatabaseFirst. Я под CodeFirst подразумеваю подход когда народ колбасит декомпозицию предметной области сначала в ООП, а потом уже как-то пытается это упихнуть в базу.

                                                            Тут вопрос понимания технологии играет роль. И если человек знает что такое ORM, он не встретит никаких проблем при использовании подхода CodeFirst.

                                                            Если он знает что такое ORM он знает какие на нее накладывает ограничение реляционная модель. И как факт он приходит к проектированию базы данных, если она достаточно сложна и требует такого проектирования.
                                                            • 0
                                                              Это и есть DatabaseFirst. Я под CodeFirst подразумеваю подход когда народ колбасит декомпозицию предметной области сначала в ООП, а потом уже как-то пытается это упихнуть в базу.


                                                              У нас с вами разное понятие CodeFirst. В моем понимании это не имеет никакого отношения к проектированию системы.

                                                              Это один из подходов при работе с ORM. Не более того. Если кто то «наколбасит» декомпозицию предметной области через ООП, с использованием наследования и полиморфизма, то это его непонимание технологий ORM и что это такое. Но это не минус подхода CodeFirst.

                                                              При этом подходе вы просто генерируете БД по вашим классам, т.е. сначала описываете в коде ваши классы которые будут маппится на БД и по которым БД будет генерироваться. Конечно ваши зависимости должны ложится на реляционное представление.
                                                              • 0
                                                                Вот поэтому ваши слова:
                                                                Генерация объектов ORM должна идти от таблиц в базе, а не наоборот.

                                                                Абсолютно не имеют под собой почвы.

                                                                Вы затронули тему генерации классов по БД. Что есть подход DatabaseFirst. Когда по классам генерируется БД — CodeFirst. И там и там необходимо поддерживать реляционное представление. И проблемы тут не в том что люди не умеют использовать CodeFirst. Проблемы в том что люди не понимают что такое ORM.
                                                                • 0
                                                                  А подход, когда описывается предметная область через «наследование и полиморфизм», а потом выбирается лучше она ляжет на реляционную модель, или, скажем на key-value (а то и часть туда, часть туда, а часть вообще на файлах), ничем себя не оправдывает?
                                                                  • 0
                                                                    Вы сейчас в принципе о тех случаях когда удобнее создать сначала объектную модель? Да, вы правы, такой подход оправдывает себя.

                                                                    Но это не есть CodeFirst, при использовании ORM. И я думаю что вы сейчас и не имели его ввиду.
                                                                    • 0
                                                                      Частично имел, то есть я пишу сначала классы, а потом когда вижу, что часть (или все) из них хорошо ложатся на реляционную модель, то генерирую по ним таблицы (возможно предварительно чуть изменяя эти классы, чтобы ложились ещё лучше). Но при разработке модели возможность использования ORM (да и вообще РСУБД) держу в уме только как одну из потенциально возможных, стараясь преждевременно к ней не привязываться. Когда решу, что хранилищем будет только РСУБД, тогда часть классов ляжет на неё через ORM без переделки, часть с незначительной, а часть, возможно, придётся сильно изменить. Но в любом случае таблицы буду генерировать по классам :)
                                                                      • 0
                                                                        Понял. Но так я еще не пробовал. :) Обычно сразу стараюсь решить что будет выступать в роли хранилища. Но если не буду уверен, то буду делать точно также. :)
                                                                        • 0
                                                                          Сложно решить заранее, когда толком не знаешь, что в итоге должно получиться. Кажется это называется «Agile development» :)
                                                                          • 0
                                                                            У нас, у дотнечтиков, настолько аджальный Agile не прижился. :) :)
                                                  • 0
                                                    И что за «часть логики, которая направлена на работу с СУБД». Что это такое и почему оно приводит к печальным последствиям?
                                        • 0
                                          Макросы подходят лишь для использования небольших возможностей СУБД, у которых синтаксис различается довольно слабо. Например, это может быть что-то вроде следующего (для поддержки MS SQL и Sybase в одном приложении, где все основные тонкости языка могут уместиться в макросах)
                                          #M_FORCEPLAN
                                          select ...
                                          from table1 #M_NOLOCK_INDEX (XPkTable1)
                                          inner join table2 #M_NOLOCK_INDEX (XpkTable2)
                                          on ...
                                          where ...
                                          #M_FORCEORDER


                                          Т.е. тут мы может использовать четко указанные индексы и строго определенную последовательность соединения таблиц. Внешне достаточно понятно. Но, чрезмерное усложнение количества возможных макросов очень отрицательно сказывается на качестве кода. Его потом очень трудно понять или еще хуже, не знания «во что превращается макрос на данной СУБД» приведет к неправильному и неоптимизированному запросу.
                                          • +1
                                            Rails–разработчики смотрят на этот топик с умилением :)
                                            • 0
                                              Кстати о рельсах. В чем принципиальные отличия от того-же hibernate в кратце можете пояснить?
                                              • +1
                                                Я редко встречался с Java, часто посещаю конференции .net'чиков, так вот от NHibernate отличий просто миллион. Главное приемущество (и проблема) в самом Руби: он позволяет делать безумное метапрограммирование, но цена тому — скорость.

                                                Если не сранивать скорость работы, то NHibernate — это ActiveRecord из Rails, сделанный будто бы лет 20 назад.

                                                Ассоциации, валидации, миграции — все это есть. Адаптеры для различных бд тоже. Настроенные из коробки 3 окружения (development, test, production), для каждого из них создается своя база данных.

                                                Откройте ссылку: gist.github.com/1062185

                                                Допустим, что вам нужно создать модель (сущность) пользователя. Вы пишите в консоли подобное тому, что написано в первой врезке. Создаются: миграция, файл модели и тесты.

                                                Далее смотрим на файл миграции, которая только что создалась: вторая врезка. Есть 2 метода: up и down. Первый вызывается, когда вы «накатываете» миграции командой консоли rake db:migrate, вторая выполняется, когда «откатываете»: rake db:migrate. Уже в заготовке мы видим, что описано создание таблицы users (модель User — таблица users). В down уже прописано, что при откате миграции эту таблицу нужно удалить. Допишем туда пару своих полей: третья врезка. Мы добавляем 2 строковых поля (login и password) и указываем, что они не могут принимать значение null. И плюс одно булево поле (active), которое по умолчанию ставится в false.

                                                После этого в консоли нужно вызвать rake db:migrate и наша миграция «накатится» (если у вас уже создана бд, которая создается командой rake db:create согласно настройкам, прописанным в конфиге по умолчанию). Увидите то, что находится в следующей врезке.

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

                                                Теперь у вас есть база, таблица с данными (пока что пустая, но не важно) и модель для работы с этими данными.

                                                Можно зайти в rails-console (rails console или rails c) и создать нового юзера, допустим. Консоль идентична обычному рельсо–приложению, в ней можно делать те же действия. В следующей врезке то, что можно теперь делать (даалеко не полный список).

                                                В следующей врезке — тоже милые вещи.
                                                • +9
                                                  > NHibernate — это ActiveRecord из Rails, сделанный будто бы лет 20 назад.

                                                  Это фактическая ошибка. NHibernate реализует сложный набор паттернов: Data Mapper, Identity Map, Unit of Work.
                                                  ActiveRecord в свою очередь реализует паттерн Active Record, который является одним из самых простых вариантов реализации ORM, и даже нарушает SRP (принцип единственной ответственности) для сохранения максимальной простоты.
                                                  И хоть я сам сейчас программирую преимущественно на Ruby, мне кажется, не очень этично глумиться над людьми, которые в силу специфики своих проектов вынуждены использовать более сложное решение на основе Data Mapper, а не простенькое на основе Active Record.

                                                  P.S. На всякий случай упомяну, что паттерн Active Record реализован для всех популярных языков, а не только для Ruby.
                                                  Так что принципиальные отличия в паттернах «Data Mapper vs Active Record», а не в Rails. Одно из ключевых отличий состоит в том, что Data Mapper создаёт объекты на основе произвольного набора данных из базы данных, а Active Record на основе одной единственной таблицы в базе данных.

                                                  P.P.S. Миграции к ORM вообще никакого отношения не имеют, они относятся к вопросу создания и редактирования схемы базы данных, а не к вопросу преобразования отношений в объекты.
                                                  • –2
                                                    Меня попросили показать, как и что умеет ActiveRecord в рельсах, я показал.
                                                    Про 20 лет — просто наблюдение человека, смотрящего со стороны. Такое все жалкое, недоделанное (Entity Framework, Fluent) и тд.

                                                    Я не то, чтобы смеюсь или глумлюсь, Руби озадачивает скоростью, этого достаточно, чтобы во многих нишах о нем даже не вспоминать.

                                                    И да, я не видел ни одного крупного проекта, написанного на руби/рельсах с помощью DataMapper'a вместо AR.
                                                    • +1
                                                      Меня попросили показать, как и что умеет ActiveRecord в рельсах, я показал.
                                                      Мне показалось, что там было всего пару слов про ActiveRecord, всё остальное — про генераторы кода, миграции и прочие приятности, не имеющие ни малейшего отношения к ORM.

                                                      Про 20 лет — просто наблюдение человека, смотрящего со стороны. Такое все жалкое, недоделанное (Entity Framework, Fluent) и тд.
                                                      Почитайте Фаулера «Patterns of Enterprise Application Architecture», Active Record ничуть не современнее, чем Data Mapper. Если вы не понимаете смысла незнакомого паттерна, это ещё не значит, что его реализация «жалкая и недоделанная», просто паттерн призван решать задачу по другому и ожидать что NHibernate, реализующий Data Mapper, когда-либо станет похож на Active Record из Rails (а видимо именно по мере похожести определяется доделанность в вашем случае) по меньшей мере очень странно.

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

                                                      И да, я не видел ни одного крупного проекта, написанного на руби/рельсах с помощью DataMapper'a вместо AR.
                                                      А уверен, что видел код всех крупных проектов на руби?
                                                      А если серьёзно, существующая для Ruby реализация паттерна Data Mapper, с одноимённым названием, сильно упрощённая и по сути похожа на ActiveRecord под другим углом. О существовании готовых решений уровня Hibernate под Ruby мне не известно.
                                                      • +1
                                                        Я никого (совершенно никого) не хотел обидеть своим комментарием и мне очень жаль, что я таки обидел или задел за живое тех, кто использует H или NH.

                                                        Я сравниваю не DataMapper и ActiveRecord, я сравниваю скорость разработки и удобство разработки двух схожих по функциональности продуктов, основываясь на своем опыте в Rails и чужом — в Hibernate и NHibernate.

                                                        По поводу миграций, я сравниваю, опять-таки, не паттерны из книжки, а два реально существующих проекта (библиотеки, называйте как угодно), призванные упрощать жизнь программистам.

                                                        По поводу скорости — это наоборот камень в огород Ruby (не только ведь расхваливать его можно, верно?).

                                                        Но, видимо, я таки задел за живое любителей H и NH, поэтому живым мне отсюда уже не выйти :) Я не хотел, честное слово. У каждой платформы и технологии есть свои плюсы и минусы.
                                                  • +1
                                                    NHibernate намного сложнее, чем Rails AR, и много более функционален и главное — охватывает куда большее количество подходов. Включая возможность написания на нем реализации паттерна Table Module (Active Record). Пример — Castle AR.

                                                    И у него совсем другое применение. Однако, я бы не был столь категоричен, чтобы отодвигать NH только в нишу «совсем тяжелого энтерпрайза», но, признаюсь, меня и самого напрягает стиль работы с NH (хотя FluentNHibernate и делает жизнь значительно легче).

                                                    NH совершенно точно не предназначен для быстрой разработки аля Rails AR, и поэтому их вообще некорректно сравнивать. С NH можно разрабатывать вещи и быстро, но его изучение требует времени. У AR, и вообще Rails — другой стиль, который мне самому ближе.

                                                    В последних проектах я отошел от NH и от ORM в целом, пытаясь использовать другие подходы. В них, кстати, AR более применим, нежели NH.

                                                    И еще — про 20 лет я бы не говорил — NH очень даже современен в своей функциональности, просто у него другой стиль.
                                                    • 0
                                                      Мне сложно говорить о H и NH, потому что я на них никогда ничего не писал. Но вот на прошлой неделе я был на слете дотнетчиков и слушал доклад о Fluent. Вроде как упрощает жизнь, крутая такая штука, но… очень (ОЧЕНЬ) много вещей нужно писать руками. В Rails есть конвенции, в Fluent почти что тоже есть, но их как бы и нет вовсе.

                                                      Зачем мне каждый раз руками задавать название таблицы для Entity? В рельсах с самого начала был класс Inflector (или как-то так), который отвечает за склонения английских слов: он не такой сложный, этот класс. Почему в 21 веке я вообще должен об этом париться?

                                                      Отошел от конвенции — указал название руками, не отошел — да с какой стати мне из проекта в проект, из модели в модель писать одно и то же?

                                                      И это — только мааленький пример того, почему я написал про 20 лет. H и NH не плохие (я этого и не говорил никогда), но Рельсы (в целом) более человечны, что ли. Все для людей, ну вы и сами знаете :)
                                                      • 0
                                                        Я согласен совершенно по поводу конвенций. Я целиком и полностью за такой подход. И за простоту Rails. Именно что — не писать тривиального boiler-plate-кода. Это бесит и раздражает :) Ну, вы это и так понимаете.

                                                        Но про 20 лет я все равно не стал бы говорить, ибо не так уж много вообще API написано с принципом Convention over Configuration в голове. Т. е., если он не преследуется — вовсе не значит, что технология сразу допотопная.
                                                        • 0
                                                          В NH chaining сделали совсем недавно, если я не ошибаюсь. До этого делать его было нельзя. То есть всякие рельсовые Post.recent.popular.limit(10) сделать было нельзя, что удручает. Насчет наличия named_scope я тоже не уверен. Валидации — не уверен. Ок, не 20 лет, пусть поменьше, но не в ногу со временем.
                                                          • +1
                                                            Валидаторов в .NET хватает. Я бы не стал напрямую сравнивать Rails AR и NH — они слишком уж разные по архитектуре.

                                                            Насчет named_scope — я не в курсе, что это такое :)

                                                            Ну а насчет «Post.recent.popular.limit(10)» — есть LINQ, и у NH есть какой-никакой LINQ-провайдер. Получается что-то вроде Data.FindAll<Post>().Where(IsPopular).Paginate(10).
                                                            • 0
                                                              named_scope — это когда я в модельке описываю один раз некое recent (например, граница по дате добавления), а потом где угодно в проекте указываю Post.recent — выберет все посты с заданными (один раз и в одном месте) условиями.

                                                              Аа, или это мне как раз про LINQ новый говорили, что вот в нем как раз это появилось. Ну, в общем я не против NH, но таки Rails AR мне кажется более продвинутым. Опять же, я напомню всем про скорость работы.
                                                              • 0
                                                                Понял про named_scope. Хорошая вещь. Разумеется, это делается и в .NET, обычно с помощью паттернов Specification или QueryObject (но можно и расширением к Repository). Задается в одном месте — это однозначно, DRY — иначе никак.
                                                  • –1
                                                    По поводу ассоциаций еще немного. Поддерживаются все типы ассоциация, рассмотрим ассоциацию один-ко-многим:

                                                    Создадим еще одну модель (Post) и укажем, и добавим в таблицу posts (по аналогии с пользователями) 1 поле: заголовок (например) и еще int'овое поле user_id. Опять выполним миграции, пропишем 2 строки кода и получим полностью рабочие ассоциации.

                                                    В файле модели user.rb нужно (между class и end) написать has_many :posts, :dependent => :destroy, а у поста — наоборот belongs_to :user.

                                                    Теперь если мы удалим юзера, удалятся все его посты (dependent можно не указывать, тогда не удалятся). После этого можно делать такие вещи:

                                                    user = User.create(:login => "login", :password => "password")
                                                    user.posts — тут будет пустой массив, у юзера нету постов
                                                    user.posts.create(:title => "first post")
                                                    user.posts.count — вернет 1, у юзера есть 1 пост
                                                    user.posts.first.title — вернет заголовок первого поста
                                                    user.posts.first.user — вернет то же, что и user.

                                                    Post.create(:title => "second post", :user_id => user.id)
                                                    Post.create(:title => "third post", :user => user)

                                                    post = Post.new(:title => "fourth post")
                                                    post.user = user
                                                    post.save!



                                                    И так далее. Можно настраивать валидации и вообще все, что душе угодно.
                                                    • +3
                                                      В файле модели user.rb нужно (между class и end) написать has_many :posts, :dependent => :destroy, а у поста — наоборот belongs_to :user.

                                                      Теперь если мы удалим юзера, удалятся все его посты (dependent можно не указывать, тогда не удалятся)

                                                      Управление ссылочной целостностью данных на уровне приложения — это не та вещь, которой стоит гордиться… А вот задать нормальные foreign keys на уровне БД в Rails, к сожалению, до сих пор довольно сложно, если не использовать raw SQL под конкретную СУБД, особенно «из коробки».
                                                      • 0
                                                        … а еще хранимые процедуры и триггеры, да побольше, побольше. давайте по всему серверу размажем бизнес–логику одного-единственного приложения, а?

                                                        Ну, половина бизнес–логики будет храниться в моделях, другая половина — в хранимых процедурах, вот только… при установке приложения на другой сервер, вы скорее всего устанете (я — так точно устану) переносить все это, вместо просто обычного скачивания исходного кода приложения и запуска.

                                                        А уж если переезжать на другую базу (c Mysql на Postgres, например) — вот вообще веселье начнется.
                                                        • 0
                                                          Ваша логика понятна, и полностью применима к маленьким веб-проектам.

                                                          К крупным проектам, как я указал в посте, это мало применимо, ибо есть масса сложной аналитики, которая на реляционную модель ложится куда лучше + Enterprise-СУБД поддерживают как правило из коробки очень многие аналитические функции.

                                                          Про перенос приложения на другой сервер — это отдельная история.

                                                          Вам надо с нуля развернуть приложение на новом сервере? Отлично, у вас есть инсталлятор, который создает схему БД, раззиповывает JBoss, подкладывает под него нужные библиотеки и ваше приложение — все готово.

                                                          Вам нужно применить патч на существующий сервер? Обновить его до следующей версии?

                                                          Патч состоит из двух частей — миграционный скрипт СУБД, собранный с помощью TOAD или других инструментов и тщательно проревьювленный, и патч код промежуточного уровня (Java классы, ресурсы, client-side code).

                                                          Да, и то и другое требует определенного времени и усилий (правда автоматизируемо — например, у нас есть самописные инструменты для установки приложения или апдейтов на кластер, конфигурация которого (адреса узлов и их роли) задана декларативно). Но так живет крупный Enterprise :)
                                                          • 0
                                                            Я ниже написал, да, что конкретно к данной статье Rails не к месту, ибо не тот уровень.
                                                            • 0
                                                              Да почему не тот уровень? Rails вполне успешно применяется для крупных веб-проектов. Говорите за себя, а не за Rails в целом.
                                                              • 0
                                                                Крупных — да.
                                                                Мне всегда казалось, что Enterprise — это немного бОльшее, чем просто «крупный». На более менее крупных я и сам работал, я говорю именно об Enterprise.

                                                                Крупные банковские системы, прочие вещи, связанные со стабильностью, надежностью и деньгами. Я _не_ против Rails, я кроме них ничего и не умею толком, но я отчетливо понимаю, что все это — не их стихия. Но написать, понятное дело, можно все что угодно.
                                                          • 0
                                                            Я, наверно, вас сильно удивлю, но бывают случаи когда от хранимых процедур никуда не денешься и это реальная необходимость для Rails-проекта.
                                                            Что касается, обеспечения ссылочной целостности, то это задача СУБД и лучше уж реализовать её и в ключах и в моделях, чем только в моделях и потом получать пачками «NoMethodError: undefined method `xxx' for nil:NilClass».
                                                            • 0
                                                              По поводу хранимых процедур хотелось бы пример. Возможно, и мне стоит их использовать, а я и не в курсе. Заранее спасибо.
                                                              По поводу целостности: я писал выше, что очень хорошо в миграциях прописывать :null => false для полей, где null недопустим. Этот параметр сохраняется именно в СУБД, а не в модели, и он очень полезен. Именно чтобы сразу видеть, что где-то что-то пошло не так.

                                                              Просто я немного против того, чтобы логику размазывать по всему серверу, как-то это нелогично.
                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                                            • 0
                                                              Спасибо, я знаю про плагин, поэтому и написал «из коробки», вообще логично было бы включить эту функциональность в Rails.

                                                              > Но вообще говоря, в рельсах есть штуки, на которые люди, умеющие готовить sql, смотрят с презрением.

                                                              Ну такие штуки есть в любом ORM, именно поэтому надо понимать как конкретный ORM работает и какие запросы он генерирует за кадром, иначе такой фигни можно понаписать…
                                                              А вообще Active Record в Rails очень прилично реализован, ему бы ещё поддержку DISTINCT получше сделать и вообще шикарно будет :-)
                                                      • +2
                                                        С умилением могут смотреть лисперы, запомните. А Rails-разработчики могут смотреть со смутным трепетом.
                                                        • 0
                                                          Ну хотя тут речь идет об Enterprise, а это не особо ниша рельсов, тут таки Java и прочие рулят.
                                                        • –1
                                                          Поддерживаю,

                                                          Если взять любой ORM для PHP или NET, то по сравнению с Rails проблемы следующие:

                                                          * Код компактно не получится написать

                                                          * Сложные запросы не получится написать. Все может сломаться уже на запросе вида a=b and (c=d OR c=e), не говоря о having count или order by вычисляемое поле. Приходится переходить на полностью написанный свой SQL код.

                                                          * Из своего SQL запроса, написанного без использования ORM к одной таблице, нельзя получить стандартный объект ORM. Т.е запросы
                                                          member = Member.ById(param_id)
                                                          и
                                                          member = Member.sql('SELECT * FROM member WHERE id = ?', param_id)
                                                          не будут равноценны. Второй запрос может выдать просто массив.

                                                          * Если мы создаем модель Member, то методы взаимодействия с базой данных находятся в ORM и приходится под каждый чих создавать свой метод в модели Member типа

                                                          function Member::ById(param_id)
                                                          {
                                                          connection = ORM::get_connection();
                                                          connection.get_table('member')->where('id = ?', param_id);
                                                          }
                                                          т.е. по сути получается 2 модели — одна для обычных запросов (CRUD логики), вторая для нестанартной бизнес-логики

                                                          * очень часто нужно либо хранить структуру базы в виде XML конфигов, моделей, либо при вызове ORM прописывать типы для значений, которые передаешь (характерно для NET)

                                                        • 0
                                                          Быть может, было бы неплохо начать топик с описания что такое ORM?
                                                          • –8
                                                            ORM — это такая специальная херня, благодаря которой малейшее изменение схемы базы приводит к правке кода не меньше чем в 50 местах.

                                                            Особо упоротые любители ООП каждому полю ещё прописывают геттеры и сеттеры. Чтобы жизнь тому, кто будет разгребать эту кучу говнокода, совсем уж мёдом не казалось.
                                                            • 0
                                                              Ммм, нет.

                                                              У нас например модели описана в XSD-схемах, при изменении которых DDL для таблиц СУБД и измененные Java-классы перегенерируются / рекомпилируются, так что не всегда все так плохо. Я ведь не противник ORM as such.
                                                              • 0
                                                                Прикольно! Вы только не сильно злоусердствуйте. Если весь код будет генерироваться по шаблонам, вы можете остаться без работы.
                                                                • 0
                                                                  За меня не стоит так беспокоиться, написание парсеров и кодогенераторов тоже вполне интересная и сложная задача…
                                                                • 0
                                                                  А миграции у вас как-то реализованы?
                                                                  • 0
                                                                    Какие именно? Используется www.liquibase.org/ и ручная миграция с помощью schema objects diff, через PL/SQL developer / TOAD.
                                                                • +5
                                                                  ORM — это такая специальная херня, благодаря которой малейшее изменение схемы базы приводит к правке кода не меньше чем в 50 местах.
                                                                  Приведите пример 50 мест, в которых приходится править код при малейших изменениях схемы данных.
                                                                  • +9
                                                                    И мне тоже интересно послушать. И интересно, в каком кол-ве ТЫСЯЧ местах придется править код, если ORM не использовать :)
                                                                    • 0
                                                                      Присоединяюсь к вопросу. С попкорном :)
                                                                    • 0
                                                                      наверное, вы не слышали о CodeFirst
                                                                      • +2
                                                                        Видимо вы не работали с современными ORM. К примеру в Entity FrameWork достаточно произвести синхронизацию с базой данный — и модель обновляется. Без правки «в 50 местах». Это к замечанию про «малейшее» изменение. Если изменение будет достаточно сильно влиять на архитектуру приложения — правка кода понадобится в любом случае.
                                                                        • 0
                                                                          В EF уже появились миграции?
                                                                          • +1
                                                                            Что именно вы подразумеваете под «миграцией»?
                                                                            • 0
                                                                              Допустим, мне нужно переименовать поле (колонку в БД) без потери данных. Как это сделать с помощью EF? Или, например, перенести поле в другую таблицу, без потери данных?
                                                                              • +3
                                                                                Вопрос поставлен не корректно.
                                                                                Переименовываете колонки и переносите данные в базе — это уровень базы данных.
                                                                                EF используется для того что бы вы на уровне кода могли обращаться к сгенерированной по структуре базы объектной модели.

                                                                                То что вы описали — это не задача ORM.
                                                                                • 0
                                                                                  Я пытался пояснить, почему считаю ваше замечание про EF некорректным. В настоящий момент EF не решает задач по гибкому изменению структуры БД, а может лишь уничтожать ее и создавать по новой.

                                                                                  Поэтому любое изменение в БД на уровне сервера БД требует тех самых изменений в «50-и местах». Иначе мы потеряем все данные в таблице, т.к. EF ее тупо пересоздаст. На сколько я слышал, функционал миграций тиснут из Ruby в EF лишь к следующему крупному релизу.

                                                                                  З.Ы. по поводу того, что миграции это не задача для хорошей ОРМ — можно поспорить ;-)
                                                                                  • +2
                                                                                    Стоп. ORM создает объектную модель в коде на ЯП.
                                                                                    «Иначе мы потеряем все данные в таблице» — каким образом мы можем потерять данные если работа с моделью базы (именно моделью базы, а не объектной моделью) происходит за пределами ORM?
                                                                                    ORM вообще не решает задачу «изменения структуры БД».
                                                                                    ORM генерирует объектную модель по существующей модели базы данных.
                                                                                    • 0
                                                                                      Не всегда, ORM-фреймворки могут еще наоборот, генерить схему БД по объектной модели. Привет, Том Кайт!
                                                                                      • 0
                                                                                        Они то может и могут. Только так лучше не делать.
                                                                                        Качество такой базы данных лично у меня вызывает большие сомнения. Тем более если говорим о проекте уровня Enterprise — плохо продуманная структура именно на уровне базы данных может потом вылиться в большие проблемы на остальных уровнях.
                                                                                        В то же время при хорошо спроектированной базе данных ORM снимает рутинную работу по маппингу объектов и записей в БД. При этом все узкие моменты можно описать хранимыми процедурами и вью. А ORM обернет их в функции и объекты. То есть опять же снимет с разработчика рутинную работу. Но при этом не стоит перекладывать на ORM те функции и задачи которые должны решаться разработчиком. Надо четко понимать для чего именно используется ORM в каждом конкретном проекте.
                                                                                        • 0
                                                                                          Я это все отлично знаю, это была тонкая ирония) как можно было заметить по привету переданному самому горячему стороннику того, чтобы плясать от базы :)
                                                                                          • 0
                                                                                            Это даже больше что бы довести мысль до логического конца :)

                                                                                            А Кайта мне видимо стоит наконец-то прочесть. Вы — уже не первый человек кто упоминает этого автора.
                                                                                            • 0
                                                                                              Если так, я советую начинать его читать не с книг «Оракл для профессионалов» где описывается архитектура и многие детали, а с книги «Эффективное проектирование приложений Oracle». Именно в ней даны мысли и идеи автора, подходы. А не конкретные детали.

                                                                                              Все имхо.
                                                                                              • 0
                                                                                                Спасибо за совет!
                                                                                      • 0
                                                                                        Это смотря что называть модным словом ORM. Это я к тому, что MS Sql это не только SQL.

                                                                                        Для меня ORM в широком смысле — это фреймворк по натягиванию данных на объектры… с утилитами и дополнительными инструментами для разработчика.

                                                                                        Поэтому ORM эту задачу не решает, а фреймворк, коей частью будет ORM — может решать.
                                                                          • –2
                                                                            у вас опять же неверное использование ORM. Генерация ORM от объектов а не от таблиц бред. Если кто-то так делает он ССЗБ.
                                                                            • 0
                                                                              > Генерация ORM от объектов а не от таблиц бред.
                                                                              Это почему?
                                                                              • +1
                                                                                Просто потому что объектная модель хуже транслируется в реляционную. Объектная модель богаче реляционной. Из простого получить сложное проще чем упростить сложное.
                                                                                • 0
                                                                                  Если честно, не понимаю о чем именно речь. Пишу на Django, в SQL почти не лезу. Структура базы полностью создается из моделей и не требует ручного вмешательства.
                                                                                  • +2
                                                                                    ООП к примеру обладает такими свойствами как наследование, полиморфизм. Это довольно сложно реализовать в реляционной схеме. Опять же когда вы сначала делаете ER-диаграмму для приложения, а потом уже генерируете код на его базе вы получите более качественное приложение, за счет учета особенностей реляционной модели.
                                                                                    • –2
                                                                                      Объясните это Борису Нуралиеву. 1С-Предприятие 7.х и 8.х по такой схеме прекрасно работают уже второй десяток лет.
                                                                                      • +2
                                                                                        1C предприятия это, гм, не безусловный идеал…
                                                                                        • –2
                                                                                          ORM в ней работает если не идеально, то очень близко к идеалу.
                                                                                          • 0
                                                                                            Я бы сказал что это, во первых, не фреймворк как таковой, а скорее сравнительно специализированная система. А во вторых — можно поподробнее здесь? Идеал тут что? И насколько к нему близок 1С?
                                                                                            • 0
                                                                                              Идеал в том, что разработчику (не говоря уж о пользователе) совершенно не надо париться по поводу базы данных и есть ли она вообще. Работа идет с объектами приложения (справочники, документы, регистры, итд.), а система сама их проецирует в реляционную базу данных, берет на себя заботу о блокировках, контроле целостности. Даже при написании запросов используются имена объектов приложения, а не БД, и при выполнении запроса они транслируются в имена таблиц и полей БД.

                                                                                              Возможно, это не самый оптимальный подход в плане эффективности работы, но очень эффективный в плане скорости и простоты разработки.
                                                                                            • 0
                                                                                              Смотрите ниже. Там ORM работает вообщем-то никак. Опять же почитайте как реализованы транзакции в 8.1 поверх СУБД.
                                                                                              • 0
                                                                                                В 1С на уровне приложения есть логические транзакции, когда можно «откатить» состояние произвольного объекта. Это что-то вроде возможности выборочно откатывать уже закрытые транзакции без нарушения целостности. Не уверен, что СУБД так умеют, а сама 1С делает это неэффективно (автоматом блокирует чуть ли не всю базу целиком), но зато гарантирует целостность и непротиворечивость. В последних версиях сделали управляемые блокировки, можно даже в ногу стрельнуть, если очень надо.
                                                                                                • 0
                                                                                                  В 1С на уровне приложения есть логические транзакции, когда можно «откатить» состояние произвольного объекта. Это что-то вроде возможности выборочно откатывать уже закрытые транзакции без нарушения целостности.

                                                                                                  ORM делает через транзакции именно СУБД. А не через логические транзакции.

                                                                                                  Не уверен, что СУБД так умеют, а сама 1С делает это неэффективно (автоматом блокирует чуть ли не всю базу целиком), но зато гарантирует целостность и непротиворечивость.

                                                                                                  СУБД умеет лучше. Оно умеет делать это и без блокировки всей базы целиком.
                                                                                                  • 0
                                                                                                    Вы случайно не путаете откат всей базы до контрольной точки и откат отдельной транзакции, закоммиченной еще вчера?

                                                                                                    Дайте ссылку или ключевые слова по поводу выборочного отката транзакций. Что-то я по «выборочный откат транзакций» или «selective transaction rollback» ничего дельного не нахожу.
                                                                                                    • 0
                                                                                                      Это вы транзакции в контексте СУБД и контексте бухгалтерии путаете :) Первые никакого отношения ко вторым не имеют. Первые обеспечивают целостность и непротиворечивость данных при операциях записи, вторые обеспечивают возможность отменить какие либо операции после их проведения. Разный уровень. И вот ради второго уровня блочить всю базу вместо проведения операций в отдельной транзакции достаточно бредовая идея.
                                                                                          • 0
                                                                                            Вы видели как это оно делает? К примеру обработка данных выглядит так. Делаем select * from table, далее полученные данные фильтруем уже прикладным кодом. Я бы не сказал что оно прекрасно работает. Про схему внутри базы я вообще молчу и про то что в случае файловой базы оно тупо по сетке работает очень хреново.
                                                                                            • 0
                                                                                              Это в версии 7.7, которая изначально была файловой (DBF), а потом к ней коряво прикрутили MS SQL. SELECT * она не делает, а использует курсоры. Она действительно очень хреново работает по сети, но великолепно работает через терминал, когда БД и приложение на одном компе. И не забывайте о цене решения — косарь зелени за безлимитную лицензию — это почти что даром.

                                                                                              Версия 8.х изначально разрабатывалась под SQL, и там маразма поменьше. Она уже вполне годно работает по сети, и позволяет писать запросы SQL руками.

                                                                                              А что касается самого принципа ORM «от приложения» — то он работает, и с этим трудно спорить.
                                                                                              • 0
                                                                                                Версия 8.х изначально разрабатывалась под SQL, и там маразма поменьше. Она уже вполне годно работает по сети, и позволяет писать запросы SQL руками.

                                                                                                Меньше, но не намного. Использование же курсоров по всей таблице мало чем от select * from отличается.
                                                                                          • 0
                                                                                            > на его базе вы получите более качественное приложение, за счет учета особенностей реляционной модели.

                                                                                            это зависит от бизнес-модели. чем мы рискуем — излишним качеством или недостаточной скоростью разработки?

                                                                                            так или иначе, изменять предметную область только из-за того, что она неэффективно хранится в БД — лютое ССЗБ. Большая часть предметных областей «реальной жизни» криво хранится в SQL-based. И эмулируя ручками переход от предметной области к SQL-based, кто поручится, что эта эмуляция будет намного лучше автоматической работы ОРМа?
                                                                                            • 0
                                                                                              Я слышал подобные подходы от тех людей, которые мутят аттрибутное программирование в БД. Ну знаете, где все аттрибуты моделей хранятся в виде имя-значение, и все чрезвычайно гибко и круто. Есть правда некоторые несущественные недостатки, например работает чертовски медленно, ибо противоречит принципам реляционной алгебры… а еще ссылочной целостности нет… и прочее.
                                                                                              • 0
                                                                                                это зависит от бизнес-модели. чем мы рискуем — излишним качеством или недостаточной скоростью разработки?

                                                                                                Это зависит от объема данных и предметной области. В случае если предметная область проста и понятна то сугубо фиолетово от чего генерить.

                                                                                                так или иначе, изменять предметную область только из-за того, что она неэффективно хранится в БД — лютое ССЗБ. Большая часть предметных областей «реальной жизни» криво хранится в SQL-based.

                                                                                                Эта кривизна зависит от опыта разработчика.

                                                                                                И эмулируя ручками переход от предметной области к SQL-based, кто поручится, что эта эмуляция будет намного лучше автоматической работы ОРМа?

                                                                                                Вот автомат в ORM я просто гарантирую вам наделает такое с точки зрения реляционной логики, что производительность будет ниже плинтуса. Почему? Да потому что в случае автоматической генерации базы из ORM вы можете легко не учесть необходимость третьей нормальной формы. Что приведет к значительной деградации производительности.
                                                                                                • 0
                                                                                                  > Эта кривизна зависит от опыта разработчика.

                                                                                                  эта кривизна зависит от предметной области!

                                                                                                  вот, допустим, есть у нас документооборот. Там всё таблицами, да связями между ними. Эта задача ложится на sql.

                                                                                                  а теперь возьмем сетевую файловую систему, или еще какие-нибудь графы и кубы. Эта задача не ложится на SQL! Документная БД — самое меньшее, что здесь нужно. Опытный разработчик может написать 2 тонны костылей, и таки заставить постгрес прохавать эту задачу, но костылями от этого они быть не перестанут.

                                                                                                  > легко не учесть необходимость третьей нормальной формы

                                                                                                  когда схема БД постоянно меняется в зависимости от ситуации (или разработчики кодят очень быстро, или вообще схема строится автоматически by design) — какие тут нормальные формы?!
                                                                                                  • +1
                                                                                                    эта кривизна зависит от предметной области!

                                                                                                    Ерунду говорите :)

                                                                                                    вот, допустим, есть у нас документооборот. Там всё таблицами, да связями между ними. Эта задача ложится на sql.

                                                                                                    Особенно файлы ага :)

                                                                                                    а теперь возьмем сетевую файловую систему, или еще какие-нибудь графы и кубы. Эта задача не ложится на SQL!

                                                                                                    На noSQL эта задача ложится еще хуже.

                                                                                                    Документная БД — самое меньшее, что здесь нужно. Опытный разработчик может написать 2 тонны костылей, и таки заставить постгрес прохавать эту задачу, но костылями от этого они быть не перестанут.

                                                                                                    Документная БД тут может быть нафиг не нужна. Как вы туда куб собираетесь класть или там графы?

                                                                                                    когда схема БД постоянно меняется в зависимости от ситуации (или разработчики кодят очень быстро, или вообще схема строится автоматически by design) — какие тут нормальные формы?!

                                                                                                    Фигню говорите. В случае если изменения идут от БД а не от кода, никаких проблем с нормальными формами не возникает. Если у вас возникают такие проблемы значит у вас проблемы с декомпозицией предметной области и реляционной логикой.
                                                                                      • 0
                                                                                        а я всегда думал что orm как раз для этого и задумывалась: проектируем entities и relations и знать не знаем ни о какой нижлежащей реляционной модели. ну это в идеале
                                                                                        • 0
                                                                                          Это работает очень плохо ;) Лучше оно работает когда у вас есть один ведущий разработчик, который обладает опытом в проектировании баз данных. Дальше он проектирует базу, делает ORM слой, пишет постановку и отдает прикладным разработчикам. Они работают со знакомой объектной моделью и слабо заморачиваются, что там дальше будет. В случае если они таки что-то делают не так, ведущий разработчик может легко найти такое место и дать канделябром по пальцам ;)
                                                                                          • 0
                                                                                            учитывая современную модель распределенной разработки, такая схема работает эээ далеко не всегда ;)