Проектирование классов уровня обслуживания в PHP

Недавно я познакомился с уровнями обслуживания Яни Хартикайненом в дискуссии о том, как лучше всего обрабатывать данные формы в приложении MVC. После некоторого чтения я действительно вижу преимущества такого подхода. Мой вопрос таков:

Как структурировать классы услуг?

  • Во-первых, это user_service() соответствующее имя класса для моей модели user() или есть другой стандарт?
  • Поскольку методы моей службы будут выполнять только одну задачу, правильно ли считать, что они всегда могут быть static function ? Класс сервиса не представляет данные, а представляет собой серию действий, поэтому это кажется уместным.
  • Должен ли метод службы принимать только один argument , который будет array ?

Рассмотрим, что форма отправила данные контроллеру для сохранения пользовательских данных:

 <?php class form_controller extends controller { public function process_submit() { if(user_service::update_preferences($_POST)) { echo json_encode(array('success' => true)); } else { echo json_encode(array('success' => false)); } } } class user_service { // Accepts array() public static function update_preferences($fields) { // Check for required fields if(( isset($fields['firstname']) and isset($fields['lastname']) and isset($fields['email']) ) == false { return false; } // Update user try { $s = new user(); $s->set_firstname($fields['firstname']); $s->set_lastname($fields['lastname']); $s->set_email($fields['email']); $s->update(); return true; } catch(Exception $e) { return false; } } } 

Я считаю, что это хороший подход, потому что:

  • Я могу добавить другое поле в свою форму, и мне не нужно будет обновлять controller , просто service . Кажется правильным, что контроллер не должен беспокоиться о том, какие данные передаются, просто передается. Это мешает моему контроллеру и логике в моих моделях.
  • Если бы я не передал array , я мог бы настроить функции с несколькими аргументами. Например, моя функция может быть update_preferences($firstname, $lastname, $email) . Это могло бы сделать для функций с 20 аргументами (для больших форм), и порядок просто стал бы ужасным для работы.
  • Я мог передать object , но имеет ли это смысл? Если я создаю объект, это должен быть объект, который он представляет (пользователь в этом случае), правильно? Но имеет ли смысл, что контроллер создает экземпляр объекта пользователя? Разве это не весь смысл сервисного уровня?
  • Возможно, есть аргумент в пользу наличия нескольких методов с несколькими аргументами (когда их всего один-три) и некоторых методов, которые принимают массив (когда есть много полей). Это похоже на то, что это может быть кошмар, так как вам всегда нужно будет ссылаться на класс, чтобы знать, что просил этот конкретный метод.

Кто-нибудь имеет мнение о том, что нужно делать здесь? Я на правильном пути? Что вы делали в прошлом? Большое спасибо!

Мог бы также ответить на этот вопрос, так как вы пошли, чтобы отправить мне письмо;)

Во-первых, это user_service () соответствующее имя класса для моей модели user () или есть другой стандарт?

Это приемлемо. Тем не менее, вы должны использовать один из установленных правил кодирования PHP, например соглашения PEAR или ZF. В обоих случаях имена классов – это имена UpperCamelCase и методов lowerCamelCase . Используя это, классы будут User и UserService

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

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

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

Здесь есть несколько хороших чтений (на самом деле почти все в этом блоге – хорошее чтение для разработчиков программного обеспечения)

Должен ли метод службы принимать только один аргумент, который будет массивом?

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

Я могу добавить другое поле в свою форму, и мне не нужно будет обновлять контроллер, просто службу. […]

Если бы я не передал массив, я мог бы настроить функции с несколькими аргументами. […]

Да, ваша аргументация по этим двум случаям очень важна для этого случая использования, на мой взгляд.

Я мог передать объект, но имеет ли это смысл? Если я создаю объект, это должен быть объект, который он представляет (пользователь в этом случае), правильно? Но имеет ли смысл, что контроллер создает экземпляр объекта пользователя? Разве это не весь смысл сервисного уровня?

Это зависит. Например, если вы используете фреймворк, который позволяет представлять формы как объекты (например, Zend Framework и Zend_Form ), вы можете рассмотреть возможность передачи объекта формы прямо в службу.

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

Обычно вы должны стремиться к тому, чтобы параметры были, по меньшей мере, полузагадываемыми, основываясь на имени метода. В чем-то, над чем я работаю , у нас есть модель, которая имеет, например, предприятия и продукты, где бизнес может спонсировать продукт. В ProductService у нас есть метод под названием sponsorProduct который принимает бизнес и продукт в качестве параметров. Вы можете догадываться, что это возьмут эти два (если вы все равно знакомы с кодовой базой)

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

Что касается числа параметров, я думаю, что обычно вы должны пытаться иметь отдельные параметры. Это позволяет любому легко видеть, какие параметры требуются, просто глядя на подпись функции, и позволяет довольно легко определить типы и значения по умолчанию.

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