Как правильно проектировать модели: объектно-ориентированный или «пакетный»? - PullRequest
4 голосов
/ 12 апреля 2010

Я знаю, что в ООП вы хотите, чтобы каждый объект (из класса) был "вещью", например. пользователь, валидатор и т. д.

Я знаю основы MVC, как они взаимодействуют друг с другом.

Однако мне интересно, должны ли модели в MVC разрабатываться в соответствии с традиционным ООП-дизайном, то есть должна ли каждая модель быть базой данных / таблицей / строкой (решение 2)?

Или нам больше нравится собирать методы, которые влияют на одну и ту же таблицу или несколько связанных таблиц (решение 1).

пример модуля адресной книги в CodeIgniter, где я хочу иметь возможность "CRUD" для контакта и добавлять / удалять его в / из группы контактов, способной работать в CRUD.

Модели решения 1: объединение всех связанных методов (не реальный объект, а «пакет»)

class Contacts extends Model {

     function create_contact() {)
     function read_contact() {}
     function update_contact() {}
     function delete_contact() {}

     function add_contact_to_group() {}
     function delete_contact_from_group() {}

     function create_group() {}
     function read_group() {}
     function update_group() {}
     function delete_group() {}

}

Модели решения 2: способ ООП (один класс на файл)

class Contact extends Model {
     private $name = '';
     private $id = '';

     function create_contact() {)
     function read_contact() {}
     function update_contact() {}
     function delete_contact() {}

}

class ContactGroup extends Model {
     private $name = '';
     private $id = '';

     function add_contact_to_group() {}
     function delete_contact_from_group() {}

     function create_group() {}
     function read_group() {}
     function update_group() {}
     function delete_group() {}

}

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

решение 2 работает по ООП. но я не знаю, почему я должен сделать такое разделение. Каковы преимущества, например, наличие объекта Contact. Это определенно не объект User, так почему Контакт должен «жить» со своим собственным состоянием (свойствами и методами). Потому что я склонен думать так: если что-то нуждается в состоянии, я создаю класс ООП, чтобы методы могли влиять на состояние или другие вещи, основанные на состоянии.

так что модели тоже должны быть "с состоянием"? если они не требуют состояния, почему я должен создать его в соответствии с шаблоном ООП. тогда я мог бы просто собрать все это вместе, как «пакетное» решение.

вы опытные ребята с OOP / MVC, пожалуйста, пролите свет на то, как следует думать здесь, в этой очень конкретной задаче (и вообще при создании модели)

РЕДАКТИРОВАТЬ: думать о контроллерах в MVC. они создаются в соответствии с «пакетным» решением. Это заставляет меня задуматься ...

Ответы [ 3 ]

2 голосов
/ 12 апреля 2010

каждая модель должна быть база данных / таблица / строка (решение 2)?

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

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

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

Сама модель должна просто представлять собой набор данных, либо хранящихся в виде общедоступных свойств, либо предпочтительно с соответствующими установщиками и получателями (пожалуйста, не просто определяйте пару функций get / set для каждой переменной или вы может также просто оставить их открытыми), наряду с другими методами, работающими с данными. Он не должен иметь понятия или зависеть от хранилища данных. Ответственность за создание и инициализацию модели через ее интерфейс лежит на картостроителе. Это позволит вам гибко создавать и сохранять свои модели. Вы можете сделать это из базы данных, XML-файла, в коде, из сериализованного потока, отправленного по сети, независимо от того, что действительно плавает на вашей лодке, и все это, заменив другой маппер, и модель остаётся совершенно незаметной.

2 голосов
/ 12 апреля 2010

Я не знаю, есть ли лучший способ , но я поделюсь тем, как я это делаю ...

У меня есть шлюз таблицы, например ContactTableGateway, который содержит все sql для работы с контактами. Мне нравится, что все sql находятся в одном месте.

class ContactTableGateway extends Model {

    function saveContact( Contact $contact )
    function getContact ( $contact_id )
    function createContact ( Contact $contact )

}

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

class Contact extends Model {

    function getName()
    function getAddress()
    function getEmail()
    ....

}

Вот упрощенный пример

if ( isset( $_POST ) ) {

    // some validation here
    $contact = new Contact;
    $contact->name = $_POST['name'];
    $contact->email = $_POST['email']
    $contactTableGateway = new ContactTableGateway;

    if ( $contactTableGateway->createContact( $contact ) ) {
        echo "YAY";
    }
}
1 голос
/ 12 апреля 2010

Я думаю, что ваше Решение № 2 лучше, так как оно более молекулярное / модульное, поэтому более понятное, гибкое и расширяемое (в области ООП). Это также более дружественно к ресурсам, поскольку позволяет загружать класс контактов только в том случае, если не требуется функциональность группы контактов, и наоборот. В этом преимущество разделения.

Если модели не нуждаются в состоянии, это не означает, что OOP / MVC не применяется. Модели таблиц могут не иметь состояния в своем дизайне, но именно поэтому у нас есть статические методы / члены, то есть Contact :: read ($ id).

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