Должен ли класс модели представлять сущность или возвращать ее
Я разрабатываю веб-приложение с 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.
самая серьезная проблема связана с тем, как был реализован слой модели. Во всей документации рекомендуется использовать активная запись шаблон, который сам по себе вводит несколько дизайн вопросы:
- активная запись против объектов
- ORM anti-patterns-Часть 1: активная запись
- расширенные Шаблоны OO [слайды]
другой важной проблемой является отсутствие мнений. Представления должны быть экземплярами, которые содержат логику представления. Это включает в себя выбор шаблонов для представления полученной информации из слоя модели. представления не являются шаблонами, это структуры, которые используют шаблоны.
лучший способ создать правильный слой модели поверх 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 на самом деле представляет собой комбинацию двух слоев: слоя модели и слоя представления (который должен быть сделан в основном из контроллеров и представлений).
контроллер никогда не должен получать руки непосредственно на объектах домена (которые являются частью слоя модели), потому что это означало бы, что у вас есть утечка абстракции.
Итак, в заключение, то, что вы называете "модельными классами", должно возвращать информацию.