Архитектура приложения. Когда использовать отдельный класс для значений свойств объекта? - PullRequest
0 голосов
/ 16 ноября 2018

Давайте останемся, что у вас есть 2 объекта, подобные следующим:

class State {
    const FRIENDLY = 1;
    const ANGRY = 2;
    const SAD = 3;
}

class Dog
{
    public $state_id;
}

// Usage
$dog = new Dog();
$dog->state_id = State::FRIENDLY;

Примечание: Объект State может получить больше значений, но это очень маловероятно.

Объект State будет использоваться только с объектом Dog (см. Примеры использования).

Вы бы написали код как выше или как после :

class Dog
{
    const STATE_FRIENDLY = 1;
    const STATE_ANGRY = 2;
    const STATE_SAD = 3;

    public $state_id;
}

// Usage
$dog = new Dog();
$dog->state_id = Dog::STATE_FRIENDLY;

Пожалуйста, объясните свой выбор.

1 Ответ

0 голосов
/ 16 ноября 2018

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

Если вы собираетесь делить одни и те же состояния между разными объектами (например, у вас может быть разное животное, скажем, Cat, и Кошка также может быть дружелюбной / сердитой / грустной -> тогда вполне имеет смысл иметь один State класс, который имеет все возможные состояния животных.

В вашем сценарии я бы не стал $dog->state_id = ...., он подвержен ошибкам, так как каждый может назначить что угодно. Вместо этого лучше использовать набор из трех функций ($dog->setAngry(), $dog->setSad(), $dog->setFriendly()) или, если у вас есть несколько состояний, например, $dog->setState($state);. setState может подтвердить, что вы передали правильный параметр (убедитесь, что это один из ....).

Короче говоря, если есть только один потребитель этих констант (Dog в вашем примере), я бы не стал создавать отдельный класс. Когда у меня несколько потребителей, я бы подумал, имеет ли смысл быть отдельным классом / интерфейсом или абстрактным классом. Скорее всего, я бы пошел абстрактный класс, если только мой код будет использовать эти константы (например, Dog и Cat). Если бы я писал библиотеку для подключения к серверу, и некоторые другие пользователи собирались использовать эту библиотеку (чтобы константы использовались как моей библиотекой, так и чьим-либо другим кодом), я написал бы их как отдельный файл / экземпляр), для пример

$request = MyLibrary\RequestBuilder::makeRequest($url);
if ($request->getStatus() == MyLibrary\Request::FAILED) {
    // handle failed request
}

В этом сценарии Request будет интерфейсом, который имеет все возможные состояния, и пользователю не нужно думать, какой конкретный класс RequestBuilder возвращает, я просто знаю, что могу использовать интерфейс Request, чтобы узнать, как работать с полученным объектом.

И еще одна вещь, есть плагин PHP под названием https://github.com/myclabs/php-enum,, если вы собираетесь использовать его, вы получаете встроенную проверку, и ИМХО, совершенно логично создать другой класс только для состояний что-то вроде:

class DogState extends Enum {
    const FRIENDLY = 1;
    const ANGRY = 2;
    const SAD = 3;
}
class Dog {
    private $state_id;
    public function setState( DogState $state) {
        $this->state_id = $state;
    }
}

$dog->setState( DogState::FRIENDLY() );

Для меня это синтаксический сахар, и я предпочитаю использовать чистый PHP, но я знаю людей, которым это нравится.

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