Подходы к моделированию

от автора

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

Просто модели

Голые модели без каких-либо аннотаций, например:

class User {     /** @var string */     public $email; } 

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

Модели плюс объекты-типы

Каждая модель имеет свой объект, отвечающий за конкретный тип, обычно они совпадают с именованием свойств модели и содержат мета-информацию:

class User {     /** @var string */     public $email; } 

class UserType {     /** @var EmailInput */     public $email;          public function __construct()     {         $this->email = new EmailInput('email');         $this->email->required = true;         $this->email->unique = true;     } } 

Это требует более четкой работы модели, но дает возможность повторного использования кода объектов-типов, например `$qunique` может быть использована для валидации CSRF-токенов, формирования схем, уникального ID и т.д.

Подход по-прежнему простой, т.к. не требует никаких фреймворков и библиотек.

Аннотированные модели

Мета-данные внедрены внутрь исходного кода в виде аннотаций:

class User {     /**      * @var string      * @input(type="text")      */     public $first_name; } 

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

Мета-моделирование с кодогенерацией моделей

Предполагается создание моделей во время исполнения через фреймворк кодогенерации, это может выглядеть примерно так:

$class = new MetaClass('User'); $class->addProperty(new EmailProperty('email'));  $code_generator->run($class); 

Кодогенератор будет содержать модель, мета-модель и, возможно, другие вещи, такие как фабрика классов и т.д.

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

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

Мета-моделирование по спецификации

Этот подход используется, например, в языке M#, в котором декларативная спецификация записыватется на специальном языке, скармливается парсеру и используется для кодогенерации.

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

Кодогенерация из объектов-типов

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

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

Заключение

Мой фаворит — модели плюс объекты-типы, потому что:

  1. Избегаем генерации кода.
  2. Статическое связывание и автоматический рефакторинг везде.
  3. Нестатические имена свойств в виде строк инкапсулируются в объект-тип, не повторяются и становятся безопасными.

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

Конечно, не все разработчики могут быть согласны со мной, возможно кто-то даже назовет еще пару способов, но основной посыл статьи — открыть путь к новому и вдохновить вас на получение дополнительных знаний.

ссылка на оригинал статьи http://habrahabr.ru/post/267385/