Немного об OR/M, PHP и .NET

Если вы можете себе позволить не использовать объектно-реляционное отображение – не используйте его.

И тогда не надо читать этот пост :)

Мне же в один прекрасный день, лет эдак пять назад,  стало слишком лениво каждый раз писать код, который занимается сборкой объектов из набора данных, полученных из базы, а потом раскидывает из объектов данные по форме, а потом записывает изменения обратно в объект, а потом формирует запрос на сохранение объекта в базе…

Тут возникает резонный вопрос:  если постоянно нужно решать эти рутинные задачи помещения и извлечения данных  из чёрного ящика под названием “объект”, может вообще ну его, этот ООП?

Я честно отвечу – может и ну его. И попрошу вас ещё раз перечитать первое предложение :)

Можете ещё спросить об этом у Мартина Фаулера, он красиво рассказывает о том, как может вырождаться ООП в процедурный подход. Но будем считать, что вопрос, использовать объекты или нет не стоит, собственно стоит вопрос – КАК использовать?

Вопрос, однако, не праздный. Опустим холивары на тему  реляционные vs объектно-ориентированные базы данных, это тема отдельного разговора. SQL – наше всё! :)

Какую архитектуру объектно-реляционного отображения выбрать? Вариантов, по большому счёту, всего два: Active Record и Domain Model. Неплохая аргументация приведена вот тут. Для меня, кстати, было открытием, что у Фаулера эти паттерны находятся в разных весовых категориях: Domain Logic Patterns и Data Source Architectural Patterns, т.е. фактически описывают одно и то же на разных уровнях абстракции.

Но с практической точки зрения разница между реализациями AR есть, и заключается главным образом в том, что является первичным для определения структуры объекта. В известных мне реализациях Active Record в динамических языках (Code Igniter, RoR) свойства объекта формируются динамически и соответствуют полям таблицы в базе, т.е. структура БД первична и определяет структуру объекта.

В статических языках все с точностью до наоборот: структура класса определяет структуру таблицы. Надо учитывать, что возможности движка OR/M имеют огромное влияние на простоту внесения изменений в структуру, на процесс рефакторинга. Некоторые реализации, например CoolStorage.NET предполагают ручной маппинг структуры класса и таблицы в базе. С одной стороны это увеличивает гибкость решения – например, что если вам необходимо работать с существующей базой данных? Но в большинсте случаев это влечет за собой дублирование изменений в базе и в коде, что нельзя назвать плюсом.
На уровне слоя доступа к данным для меня чистота реализации DM определяется как раз тем, насколько автоматизирован процесс внесения изменений в структуру базы, в соответствии с тем, как изменилась модель домена в процессе рефакторинга.

И, наконец, та мысль из которой родился этот пост: для динамических языков, таких как PHP, Ruby, Python, органично применение архитектуры, где структура таблиц определяет структуру модели домена в приложении. Ведь там так просто добавить свойство в объект в процессе исполнения!

В языках со статической типизацией, в том же .NET, чтобы скомпилировать приложение, нужно определить структуру типов, т.е. фактически структуру таблиц. Это знание незачем дублировать в двух местах: в коде и в БД. Достаточно описать класс с его свойствами, а средство OR/M уже само определит структуру таблиц в базе. Ключевым свойством языка в этом плане является рефлексия, т.к. без возможноси анализа структуры типа во время исполнения, можно даже не думать об автоматической синхронизации БД и модели домена.

P. S. Хорошая штука всё-таки блог. Он стимулирует к письменному выражению своих мыслей. А в процессе написания, приходит и более глубокое понимание вещей, которые пытаешься сформулировать. Например мне в голову больше не приходит противопоставление Active Record и Domain Model. По сути, все с чем мы имеем дело – это AR в том или ином виде, так как каждый бизнес-объект является отображением записи в таблице. Да, чистый AR, конечно расширяется наличием связей с другими объектами в том, что я называю Domain Model. Но это – большой позитив, по крайней мере в теории.. На практике, правда, всё зависит от реализации: например, сохранение и загрузка коллекций (отношения 1-n, m-n) может некисло тормозить. Но это проблема конкретных систем и ни в коей мере не контр-аргумент против поддержки связей в слое объектно-реляционного отображения.

Related posts

Comments

  1. Спасибо! Жду продолжения :-)

    • Nikita Yeryomin says:

      Будет, будет :) Но не сразу, следующий пост – про Continuous Integration, уже руки чешутся написать, но пока текучку разгребаю :)

  2. Объектные базы – интересная штука, но, наверняка, дорогостоящая в плане ресурсов сервера, на котором всё это дело крутится! А так – незаменимая вещь в некоторых архитектурах. Попробую ORM в дипломном проекте :)

  3. Very Nice website. I just finished mine and i was looking for some design ideas and your website gave me some. May i ask you whether you developed the website by youself?

    Thank you

  4. one good guy says:

    Really great article with very interesting information. You might want to follow up to this topic!?! 2011

  5. VovaN says:

    получается в .Net всю работу с бд можно свалить на ORM и работать с обьектами не думая о сохранении? жаль правда, что вся эта красота ест много ресурсов(
    еще немного не по теме, но все-же: http://ru.wikipedia.org/wiki/%D0%A4%D0%B0%D0%BD%D1%82%D0%BE%D0%BC_(%D0%9E%D0%A1)

    • Nikita Yeryomin says:

      Вообще ORM реализованы далеко не только в .NET… ну и “работать с объектами не думая” – это ты погорячился :) Кстати, когда доберёшься до офиса?)

Submit a Comment