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

Я использую Service Layer, и до сих пор я использовал ServiceObject (который реализует ArrayAccess, Iterator, Countable), но мне интересно, хорошие ли идеи.

Вы бы сделали:

ArticleService::createArticle($articleData, $userId);

или

ArticleService::createArticle(ServiceObject $data);

где $data:

array(
  'title' => 'Lorem ipsum',
  'body'  => 'Dolor sid amet',
  'userId' => 55,
);

Служба ServiceObject имеет преимущество для предоставления общей подписи для каждого метода, однако иногда она не выглядит эффективной и широко не используется, она теряет свои интересы.

Любая обратная связь?

Ответ 1

Измените его на:

ArticleService::createArticle($title, $body, $user_id);

Это очень ясно, что вам нужно для создания "Статьи".

"опции", такие как ваши $articleData и $data, невозможно разумно интерпретировать, и я бы посоветовал это сделать.

Избавьте свою идею от общего ServiceObject, это на самом деле очень плохая идея. Ваши мотивы благородны, но это неправильное решение.

Если вам нужно больше убеждать, не стесняйтесь.

Ответ 2

Я думаю, что лучший подход здесь - иметь что-то вроде

$article = new Article;
$article->title = "Lorem ipsum"
$article->body = "Dolor sit amet"
$article->creator = $userID
ArticleService::createArticle($article)

Хотя предположительно "createArticle" больше не будет лучшим именем для этой функции, поскольку объект Article уже был создан. Вероятно, у вас есть что-то вроде ArticleService::publishArticle($article), хотя я не знаю, что вы делаете.

Вы хотите отделить построение своих данных (Article) от его использования (ArticleService).

То, что я действительно пытаюсь сказать, не делает аргумент createArticle общим массивом или "ServiceObject", оба из которых являются бесполезными абстракциями списков аргументов, делают его классом, который действительно представляет соответствующий объект.

Ответ 3

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

Ответ 4

Второй способ лучше, у вас никогда не будет проблем с людьми, которые назовут ваш метод неправильным! Также гораздо легче читать и видеть, что требуется. Для меня как разработчика было бы ясно, что мне нужно передать объект типа ServiceObject, а затем я начну искать документацию или пример или интерфейс этого класса. Но в первом примере я должен прочитать код createArticle, чтобы выяснить, как будут обрабатываться оба параметра.

Второй подход также поможет вам сохранить ваш API/подпись чистым с течением времени. Когда в createArticle требуются некоторые дополнительные данные, вы просто передаете их через ServiceObject, и вам не нужно менять подпись!

Для первого примера может быть немного лучше подпись:

ArticleService::createArticle(array $articleData, $userId);

В этом случае $articleData должен быть массивом. Это предотвращает ошибки. В параметрах функции PHP для кастинга могут использоваться только массивы и имена классов.

Ответ 5

Нет правильного пути, но я использовал бы ArticleService::createArticle($articleData, $userId); в этом конкретном случае.

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

Таким образом, связь между статьей и объектами пользователя очевидна. Читаемость немного улучшена. Кроме того, вам необходимо полностью ознакомиться как с данными, так и с методом createArticle.

В качестве доказательства: сразу, когда я увидел ArticleService::createArticle($articleData, $userId), я понял, что делает этот метод и что ожидает входных данных, а второй меня озадачил.

Кроме того, если userId отсутствует, в этот момент вы получите сообщение об ошибке, если вы не вставляете его в базу данных, где, вероятно, вы получите ошибку SQL, которую намного сложнее отслеживать.

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

Однако это в основном зависит от ваших предпочтений.

Ответ 6

Я думаю, что лучший подход - это инъекция объекта. Но почему там ServiceObject? У вас есть метод createArticle, тогда было бы логичным передать объект статьи, нет? Таким образом, проще организовать процесс проверки, вы можете просто пометить поля, которые вы хотите проверить в аннотациях.

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

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