Должен ли класс модели представлять сущность или возвращать ее

Я разрабатываю веб-приложение с CodeIgniter (но я думаю, что вопрос относится в основном к MVC шаблон в веб-приложениях).

когда я разрабатываю класс модели для некоторого объекта базы данных (скажем, a BlogEntry для иллюстрации), у меня в основном есть два варианта:

подход "классический ООП" был бы, чтобы класс представляют сущность, т. е. один экземпляр класса is в BlogEntry. В CodeIgniter, это приведет к коду, как

class Blogentry extends CI_Model {
    function load($id) {
      // Access database
      $this->id = $dbresult.id;
      $this->title = $dbresult.title;
      $this->author = $dbresult.author;
    }
}

чтобы получить доступ к некоторой записи в блоге, я бы сделал $this->load->model('blogentry');, называют $this->blogentry->load($id) а затем работать с экземпляром класса model.

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

class Blogentry extends CI_Model {
  function get_entry($id) {
    // Access database, yielding $dbresult
    return $dbresult;
}

С этим я бы написал

$this->load->model('blogentry');
$the_entry = $this->blogentry->get_entry($id);

в контроллере и работать с $the_entry. В этом втором случае, класс больше похож на завод или строитель класса.

считается ли какой-либо из этих двух подходов "правильным способом" выполнения M в MVC? Я думаю, я видел второй подход чаще, но я не смотрел на столько MVC-Webapps. Любые мысли о том, почему первый или второй подход может быть более подходящим?

3 ответов


прежде всего, CodeIgniter-это не структура MVC. Парадигма, которая подходит лучше всего, вероятно,MVP или что-то вроде ORM-шаблон-адаптер. Поэтому позвольте мне разбить мой ответ, основанный на этой ошибке именования:

в классическом / традиционном MVC (не то, что утверждают фреймворки MVC), модель не является классом или одним файлом, а скорее слой который содержит всю бизнес-логику домена и обычно состоит только из такие вещи, как Объекты Домена, Данные Картографов и что-то для обработки интерфейса между вызывающей сущностью и логикой домена, чтобы держать такой код вне контроллера (например, в MVC). имена Tereško их "услуг", что достаточно хорошо для квази-официального имени.

таким образом, в традиционном MVC запросы к уровню модели com через "службы", которые, в свою очередь, взаимодействуют с объектами домена и данными картографы.

очевидно, что все это имеет мало отношения к тому, что CodeIgniter и другие фреймворки называют "MVC."В этом шаблоне проектирования (я назову его" CIMVC " для краткости) модель-это класс, который вызывается и управляется контроллером и напрямую взаимодействует с базой данных. Хранение данных в переменных-членах в модели не имеет большого семантического смысла, но если вас интересует что-то подобное, проверьте любой из плагинов/библиотек ORM, написанных в CIMVC. (Хотя решения ORM не будут лучше соответствовать традиционным MVC...)

Что касается общих практик, большинство приложений CI, которые я видел, возвращают "сырые" данные базы данных обратно в контроллер для обработки; это сохраняет бизнес-логику домена в модели. Мое личное предпочтение в CIMVC-минимизировать / устранить все, кроме бизнес-логики домена в моделях.

tl; dr - "традиционный / правильный" MVC в CodeIgniter в основном невозможен, поэтому попытка заставить ваш код CI, чтобы соответствовать традиционным парадигмам MVC, глуп (и, вероятно, приведет вас к безумию)

изменить: чтобы прояснить некоторую более раннюю путаницу в бизнес-логике на уровне модели, да, вы должны иметь все бизнес-логики в модели слоя. Однако, если происходит дополнительная обработка данных (сортировка, манипуляция и т. д.), Теперь мы переходим на опасную территорию для сухих и SRP-нарушений; вы хотите, чтобы модель была многоразовой, поэтому будьте осторожны добавление такого количества или такой специализированной логики, что она становится непригодной для использования в других частях приложения.


это общий ответ, связанный с парадигмой MVC, поскольку у меня есть 0 опыта работы с CI, но есть большой опыт работы с Symfony, Zend, Propel и Doctrine.

я обнаружил, что при использовании доктрины, возвращая данные объекта в определенной структуре, лучше всего добавить метод, который определяет указанную структуру. Например, объекты Doctrine_Record имеют toArray() метод, который позволяет мне преобразовать объект в массив, поэтому я могу использовать методы доступа к объектам или вызвать toArray() и обращаться с объектом как с массивом.

// Accessing object data through available methods
foreach ($object->categories() as $category) {
    var_dump((string) $category);
}

// Accessing object data as an array
$objectAsArray = $object->toArray(true);

foreach ($objectAsArray as $element) {
    var_dump($element['Category']);
}

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

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


Первое, что вам нужно понять, это то, что CodeIgniter довольно далек от правильных шаблонов проектирования MVC или MVC. Официального названия шаблона, который реализует CodeIgniter, нет, но он тесно связан с Ruby on Rails.

самая серьезная проблема связана с тем, как был реализован слой модели. Во всей документации рекомендуется использовать активная запись шаблон, который сам по себе вводит несколько дизайн вопросы:

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

лучший способ создать правильный слой модели поверх CodeIgniter-игнорировать CI_Model, потому что, ИМХО, нет никаких преимуществ в расширении этого класса. Вместо этого создайте что-то вроде Services. Эти структуры могут выступать в качестве интерфейсов (не в смысле OO) для взаимодействия со слоем модели. Каждый сервис может иметь дело с несколькими домен объекты и мапперы.

В основном службы получают команды / сообщения от контроллера, которые изменяют состояние слоя модели и предоставляют метод извлечения информации из слоя модели. Обычно извлечение происходит в посмотреть экземпляры, но это невозможно в CodeIgniter. Извлечение информации также произойдет в "контроллерах", которые передают данные в шаблоны.

код будет выглядеть примерно так это:

class Library 
{

    protected $current_document = null;

    public function acquire_document( $id )
    {
        $document = load_class('Document', 'domain_object');
        $document->set_id( $id );

        $mapper = load_class('Document', 'persistence');
        $mapper->fetch( $document );

        $this->current_document = $document;
    }

    public function get_document_information()
    {
        $document = $this->current_document;        

        if ( $document === null )
        {
            return 'empty';
            // you either did not acquire the document
            // or document was not found
        }
        return $document->get_details();
    }
}

MVC Design patter на самом деле представляет собой комбинацию двух слоев: слоя модели и слоя представления (который должен быть сделан в основном из контроллеров и представлений).

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

Итак, в заключение, то, что вы называете "модельными классами", должно возвращать информацию.