Проектирование классов сервисных слоев в PHP - PullRequest
14 голосов
/ 29 июня 2011

Я недавно представил для обслуживания слоев Яни Хартикайнен в дискуссии о том, как лучше всего обрабатывать данные формы в приложении 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, но имеет ли это смысл?Если я создаю объект, это должен быть объект, который он представляет (в данном случае, пользователь), верно?Но имеет ли смысл, что контроллер создает объект пользователя?Разве это не весь смысл сервисного уровня?
  • Может быть, есть аргумент для того, чтобы иметь несколько методов с несколькими аргументами (когда есть только один-три) и некоторые методы, которые принимают массив(когда полей много).Это просто может показаться кошмаром, так как вы всегда должны ссылаться на класс, чтобы узнать, о чем просил этот конкретный метод.

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

1 Ответ

23 голосов
/ 29 июня 2011

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

...