Как представить обязательные бизнес-поля в структуре модели?

Если мы используем подсказку типа, мы можем поместить объект в обязательном порядке:

public function myMethodThatDoFineStuff(MyObject $myobject) {

}

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

Должны ли мы всегда размещать ВСЕ объекты несмотря ни на что?


ПРИМЕР для разъяснения предлагает:

Представим, что для перечисления книг определенного автора у нас есть такой метод:

public function listBookOfAuthor(Author $author) {

}

Теперь давайте представим, что у объекта author около 200 свойств, НО для обработки списка книг нам нужны только их имя и фамилия.

Должны ли мы в любом случае получать ВСЕ объекты $author?


person MEM    schedule 04.05.2011    source источник
comment
Извините, но очень сложно понять, о чем вы здесь спрашиваете. Возможно, вы захотите взглянуть на абстрактные классы, чтобы увидеть, делают ли они то, что вы хотите.   -  person James C    schedule 04.05.2011
comment
Я добавил пример, который, возможно, проясняет ситуацию.   -  person MEM    schedule 04.05.2011
comment
Now, let's imagine that the author object has 200 properties or so - мы передаем ссылку на объект, а не копируем.   -  person OZ_    schedule 04.05.2011
comment
@OZ_ Я полагаю, вы добавили сюда важную проблему. Вы говорите, что мы передаем ссылку, а НЕ справляемся, значит, это ложный вопрос для начала? Передача объекта с одним свойством или объекта с 12312312312 свойствами. Это одно и то же. оба ссылаются на одну единственную ссылку каждый, поэтому аргумент производительности не работает. Так ли это? Итак, единственная причина, по которой мы можем делать такие вещи, возможно, заключается в том, чтобы имитировать наш домен как можно лучше и, переводим, лучшее, что мы можем, деловые вопросы, правильно переведя их на язык ООП. Имеет ли это смысл? Спасибо.   -  person MEM    schedule 05.05.2011
comment
Также еще одна причина, по которой мы можем захотеть передать что-то более конкретное, а не объект, заключается в том, что если нам нужно поддерживать этот код или делиться им с другими, будет легче определить, что конкретно мы работаем над этим методом. Являются ли эти два последних комментария двумя вескими причинами?   -  person MEM    schedule 05.05.2011
comment
@MEM позвольте мне сказать вкратце: 1) объекты можно передавать только по ссылке. 2) Подсказка типа — хороший инструмент, чтобы избежать накладных расходов на проверку. 3) всегда лучше использовать интерфейс для подсказки типа, чем имя конкретного класса.   -  person OZ_    schedule 05.05.2011


Ответы (3)


Я бы проверил необходимые свойства следующим образом:

public function listBookOfAuthor(Author $author) {

    if (empty($author->firstName)) {
        throw new listBookOfAuthorException('firstName must be defined');
    }

}

Если вы обнаружите, что делаете это много, вы можете написать какой-то родительский класс, который включает метод проверки наличия свойств.

person James C    schedule 04.05.2011
comment
Дополнительное примечание: следует ли использовать исключения в этом контексте? Не должны ли мы умерить их использование для действительно исключительных вещей? (Я просто спрашиваю, потому что я слышал это много). В любом случае, и несмотря на это, ваш метод кажется менее тяжелым (с точки зрения создаваемых файлов), когда у нас есть несколько необходимых свойств. Однако с предложением интерфейса кажется, что у нас пустая трата ресурсов, но, если возможно, больше места для будущих надстроек. Старый вопрос хм? ... - person MEM; 04.05.2011
comment
Вы можете сгенерировать UnexpectedValueException, это уже часть PHP. Для интерфейсов вам вообще не нужно заботиться о проверке определенных свойств — PHP уже сделал это за вас и выдал бы исключение еще до того, как коснулся кода тела функции. Однако независимо от того, какое решение вы примете: у каждого есть минусы и плюсы. Вам нужно решить, а затем придерживаться своего решения, потому что потом вы знаете лучше. Судя по тому, что ты пишешь, мне кажется, тебе пора что-то делать :) - person hakre; 05.05.2011
comment
Действительно хакре. Мне действительно нужно немного поработать с этим, чтобы почувствовать это... и лучше понять. К тому же можно прийти и при теоретическом изучении, но не при данных обстоятельствах. - person MEM; 05.05.2011

Что, если мы хотим сделать не весь объект, а только некоторые его атрибуты обязательными?

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

Просто потому, что это может иметь больше смысла в нашей бизнес-модели?

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

Должны ли мы всегда размещать ВСЕ объекты, несмотря ни на что?

Тогда вы потеряете подсказку типа, но сможете передать любой объект. Немного зависит от того, насколько строго вы хотите написать свой код. Если вы используете интерфейсы, вы достаточно гибки при рефакторинге кода (изменении конкретных реализаций объектов), а также при работе с объектом stclass. Однако с объектом stdclass функция должна проверить, что она получает в первую очередь, прежде чем обрабатывать входные данные функции.

person hakre    schedule 04.05.2011

В зависимости от вашей схемы, метод listBooksOfAuthor() (который выглядит как метод объекта службы, такого как BookService), вероятно, может быть достаточным только для объекта $authorId, а не для полного объекта Author.

Но, кажется, я понял суть вопроса. Возможно, полное заполнение объекта Author требует больших затрат — скажем, из метода, подобного AuthorService::getAuthorById().

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

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

Просто некоторые идеи.

person David Weinraub    schedule 04.05.2011
comment
Спасибо, что показали мне все эти альтернативы... Мне действительно нужно начать что-то кодировать, иначе я потеряю цель всего этого. ;) Еще раз спасибо. :)) - person MEM; 05.05.2011