Держать модель MVC свободно связанной с БД?


9

Мне нравится, чтобы мой код тестировался, и я решил использовать стратегию Dependency-Injection для моей текущей инфраструктуры MVC, которая, безусловно, оказалась отличным способом обеспечения слабосвязанного кода, тестируемости и модульности.

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

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


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

Ответы:


6

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

Вполне вероятно, что в конечном итоге вы получите что-то на 90 +% идентичное тому, как вы в конечном итоге сохраните данные. Хорошо. Это может быть полностью идентично, не будучи связанным.

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

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

  1. База данных - храните данные, сохраняйте целостность данных, сохраняйте данные в покое.
  2. Модели - содержат бизнес-логику, моделируют проблемную область, поддерживают движение данных, отвечают на события бизнес-уровня и т. Д.
  3. Представления - представление данных пользователям, выполнение пользовательской логики (базовая проверка перед выполнением истинной проверки в моделях и т. Д.).
  4. Контроллеры - отвечают на пользовательские события, передают управление моделям, направляют запросы и возвращают ответы.

Привет, Дэвид. Спасибо за ваш обширный ответ! Поддерживая высокий уровень слабых соединений, как бы вы связали модели с разъемом базы данных?
Промышленное

1
@Industrial: существует несколько способов связать модели с постоянством, но пока единственный найденный мной метод, который действительно удовлетворяет мое желание разделить проблемы, - это иметь интерфейсы репозитория в домене, которые внешне реализуются DAL. Методы репозитория принимают и возвращают доменные модели и внутренне преобразуют между ними и любыми сгенерированными объектами базы данных. (Честно говоря, я не так много сделал в PHP.) Таким образом, вы можете использовать инфраструктуру DAL для автоматической генерации всей вашей базы данных CRUD и т. Д., А затем написать свои репозитории как интерфейс между этим материалом и вашими моделями.
Дэвид

@Industrial: например, если вы используете ORM, то на этот DAL будет ссылаться ваш DAL (который изолирован от моделей предметной области) и будет соответственно преобразовывать ваши модели в доступ к данным. Или, если вы делаете прямой доступ к базе данных с помощью ручного SQL, вы должны делать это в методах хранилища DAL и переводить результаты SQL-запросов в доменные модели, прежде чем возвращать их.
Дэвид

@Industrial: Имейте в виду также, что методы хранилища не должны быть просто CRUD. В этот код может быть включено много интеллекта. Многие из более сложных могут иметь много внутреннего кода, который преобразует данные из базы данных. Или, если сложные включают много поездок в базу данных, то для повышения производительности вы можете поместить логику в хранимую процедуру, а метод DAL просто перейдет к этой процедуре и преобразует результаты в модели.
Дэвид

Привет, Дэвид! Просто хотел еще раз поблагодарить вас за этот ответ. Определенно один из лучших, которые я получил на StackExchange!
Промышленный

2

Вы хотите иметь две вещи.

  1. Ваши модели (обращаются к DBAL и выполняют большую часть логики приложения).
  2. Ваши «доменные модели», то есть объекты данных, представляют объекты вашей системы, такие как пользователи, публикации, продукты и т. Д.

    class PPI_Model_User {
    
        protected $_conn = null;
    
        function __construct(array $options = array()) {
            if(isset($options['dsnData'])) {
                $this->_conn = new PPI_DataSource_PDO($options['dsnData']);
            }
        }
    
        function getAll() {
            $rows = $this->_connect->query("SELECT .....")->fetchAll();
            $users = array();
            foreach($rows as $row) {
                $users[] = new PPI_Entity_User($row);
            }
            return $users;
        }
    
    }

Код использования

    $model = new PPI_Model_User(array('dsnData' => $dsnData));
    $users = $model->getAll();
    foreach($users as $user) {
        echo $user->getFirstName();
    }

Там у вас это есть, вот как вы создаете модели предметной области (Entities) и имеете модели MVC, выполняющие подключение к БД и манипулирование данными.

Если вам интересно, что такое PPI, поищите в Google «PPI Framework».

Удачи в вашем поиске.

С уважением, Пол Драгунис.


1

Помните, MVC возник в smalltalk, который имеет автоматическое сохранение для всех объектов. Таким образом, шаблон MVC не предписывает никакого решения для разделения модели / персистентности.

Я предпочитаю предоставлять объект «Репозиторий», который знает, как создавать объекты модели из базы данных и сохранять объекты модели в базе данных. Тогда Модель ничего не знает о постоянстве. Тем не менее, некоторые действия пользователя должны инициировать сохранение, поэтому, скорее всего, контроллер будет знать о репозитории. Я обычно использую некоторую форму внедрения зависимостей, чтобы не допустить соединения контроллера с репозиторием.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.