вторник, 7 сентября 2010 г.

Организация Модели в Zend Framework

Введение

Этой статьей я хочу начать небольшой цикл заметок и мыслей об организации модели  в Zend Framework. Тем более что сам фреймворк мало что предлагает в решении этого вопроса. Как говорят разработчики фреймворка: Модель - это то что вы должны реализовать сами, это ваша работа.

Возникают вопросы, а как реализовывать модель, как это сделать правильно? Единого ответа нет, т.к. Модель слишком специфична и реализовывать ее можно по разному, и зависит это от множества факторов.

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



Что есть Модель

Сам термин модель очень обширен, поэтому здесь и далее будем рассматривать модель в архитектуре MVC.
Модель— это объект, предоставляющий некоторую информацию о домене. У модели нет визуального интерфейса, она содержит в себе все данные и поведение, не связанные с пользовательским интерфейсом.
Здесь важно отметить, что модель - это не только данные, но и поведение, таким образом, модель -  это не источник данных!

Классический подход к организации Модели подразумевает три слоя:
  1. Слой Бизнес-логики (Bussines Logic Layer)
  2. Сервисный Слой (Service Layer)
  3. Слой Источника Данных (Data Source Layer)
Каждый из этих слоев будет рассмотрен далее.

Бизнес логика

Мартин Фаулер выделяет три подхода, для реализации бизнес-логики:
  1. Transaction script – организует взаимодействие с бизнес-логикой посредством процедур, принимающих запросы с уровня представления.
  2. Table Module – представляет собой объект, в единственном экземпляре, обрабатывающий бизнес логику для всех записей в таблице базы данных, либо представления.
  3. Domain Model – непосредственно, объектная модель предметной области, включающая в себя как поведение, так и данные.
Первые два подхода хороши для простых задач и приложений, т.к. довольно просты. Но совершенно не пригодны для серьезных систем, т.к. развитие и поддержание таких систем будет требовать все больше и больше усилий.

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

Доменная Модель
Доменная Модель - это система абстракций, которая описывает выбранные аспекты предметной области (домена) и может быть использована для решения проблем относящихся к этой предметной области.
Согласно DDD (Domain Driven Desing) главным местом приложения должна являться как раз Доменная Модель, не источник данных, не структура БД, не пользовательский интерфейс, ни что другое. Все остальные части приложения должны строиться отталкиваясь от Доменной Модели. Таким образом Доменная Модель должна быть чистой, т.е. не зависеть ни от каких слоев системы, подсистем и других частей приложения.

Сервисный слой

Сервисный слой - является проводником к Доменной Модели. Все взаимодействия с Доменом должны осуществляться через Сервисный Слой. Не допускается прямое взаимодействие с Доменной моделью, минуя сервисный слой.

Сервисный слой это связующее звено между различными подсистемами приложения. Между Доменом и Источником Хранения, Доменом и Контроллером, Доменом и Представлением. Так же на этом уровне можно производить кеширование, логирование, управление транзакциями и другие задачи уровня приложения.

Стоит отметить, что Слой сервисов, так же является частью бизнес-логики, отличие в том, что в этом слое сосредоточена логика приложения (application logic), а за логикой домена (domain logic), этот слой непосредственно обращается к Доменной Модели.

Источник Данных

Источник данных — это подмножество функций, обеспечивающих взаимодействие со сторонними системами, которые выполняют задания в интересах приложения. Код этой категории несет ответственность за мониторинг транзакций, управление другими приложениями, обмен сообщениями и т.д. Источником данных не обязательно должна быть База Данных, это могут быть простые файлы, другие приложения, сервисы и т.д.

Организация Источника Данных сильно зависит от слоя Бизнес логики. Так как, мы выбрали Модель Предметной Области (Доменная Модель) то согласно Фаулеру, нам подходят следующие решения:
  • Active Record
  • Table Data Gateway
  • Row Data Gatway
  • Data Mapper
Если кратко, то первые три решения слишком тесно связывают бизнес-логику с источником данных. Поэтому мы остановимся на последнем варианте, который является наиболее предпочтительным для Модели Предметной Области.

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

Не исключено, что со временем, когда объектно-документированные БД наберут оборот, я перейду на одну из них, тем более что уже доступна бета версия ODM (Object Document Mapper) для MongoDB.

Заключение

Нет единственно правильного способа организации модели в MVC. Есть множество рекомендаций и типовых решений для различных ситуаций. И хотя, в настоящее время, Zend Framework кроме модели, базирующейся на Table Data Gateway и Row Data Gateway ничего не предлогает, я остановился на организации бизнес-логики как Модели Предметной Области, а в качестве Источника Данных, решил использовать Объектно Реляционный Маппер Doctrine 2.

Этот выбор связан прежде всего с тем, что на данном этапе я не знаю какие задачи предстоит решать этому фреймворку. И этот выбор позволяет снизить риски, за счет большей гибкости. Кроме того,  как мне кажется, в последние годы, с развитием ООП и в PHP сообществе наметилась тенденция к организации модели именно так, в частности наметилась тенденция к применению Domain Driven Design (DDD).

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

Ссылки по теме

Patterns of Enterprise Application Architecture
Domain-driven design
Writing Robust PHP Backends with Zend Framework
Model Infrastructure
Zend Framework Workshop
Про толстые и тонкие контроллеры и модель
Rethinking the Zend Models
Models in Zend Framework
The Best Models are Easy Models

5 комментариев:

  1. Спасибо за статью. Было бы интересно прочитать про ваш опыт внедрения Doctrine 2 в ZF.

    ОтветитьУдалить
  2. Статья отличная! Ед. не хватает примеров, что бы те кто не в теме, могли понять как же на ZF все сделать правильно. Мне интересно как ты организовываешь Bussines Logic Layer? Сомнительно, что применяешь все паттерны из DDD...

    ОтветитьУдалить
  3. @Yaroslav Vorozhko про это я уже писал http://yugeon-dev.blogspot.com/2010/08/zend-framework-110-doctrine-20.html

    @IgorN из DDD пока что я взял только самое главное: Домен - сердце приложения (Isolatin the Domain). И действительно, с использованием Doctrine 2 домен можно построить независимым.

    Насчет как все сделать правильно, я и сам не знаю ^) Сейчас готовлю статью про организацию процесса валидации, там будет немного критики в сторону ZF

    ОтветитьУдалить
  4. Отличная статья! Сам двигаюсь в этом направлении при рефакторинге ZFEngine. А с валидацией в ZF2 будет попроще.

    ОтветитьУдалить
  5. Огромное спасибо! Статья просто шикарна! Хотел наконец для себя понять что такое DDD все доходчиво написано! Спасибо

    ОтветитьУдалить