Толстый конструктор

Темы, не касающиеся фреймворка, но относящиеся к программированию в целом.
Ответить
jakiro
Сообщения: 553
Зарегистрирован: 2013.03.05, 15:15

Толстый конструктор

Сообщение jakiro »

Приветствую граждан.
Появилась дилемма, делать толстый контроллер или оставит все как есть.
Есть небольшой класс RandomService. Он получает список граждан и фильтрует их по критериям

Код: Выделить всё

$randomService = new RandomService($row->getFullWallId());
    $randomService->applyTowns($row->towns);
    $randomService->applyGroups($row->groups);
    $randomService->applyCheckFixed($row->pinned_down);
    $winners = $randomService->getRandomUsers($row->count_winners);
https://db.tt/N0PFw8xtym
https://db.tt/qHxexAnIbU
Но т.к это начало использоваться уже в нескольких местах, есть подозрения, что эти методы надо убрать в сам класс RandomService
Тогда получается, должно быть что то вроде

Код: Выделить всё

$randomService = new RandomService($row->getFullWallId(), $row->towns, $row->groups, $row->pinned_down);
$winners = $randomService->getRandomUsers($row->count_winners);
или вообще всю запись пульнуть сервису.

Код: Выделить всё

$randomService = new RandomService(CompRand $row);
$winners = $randomService->getRandomUsers($row->count_winners);
Так блин до бесконечности можно инакапсулировать и опять в god class скатывается :(
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Толстый конструктор

Сообщение ElisDN »

Если выборки везде разные, то соберите критерии выборки в виде спецификации и используйте:

Код: Выделить всё

$winners = $this->randomService->getRandomUsers($row->getFullWallId(), $criteria, $row->count_winners);
jakiro
Сообщения: 553
Зарегистрирован: 2013.03.05, 15:15

Re: Толстый конструктор

Сообщение jakiro »

ElisDN писал(а): 2017.08.01, 12:50 Если выборки везде разные, то соберите критерии выборки в виде спецификации и используйте:

Код: Выделить всё

$winners = $this->randomService->getRandomUsers($row->getFullWallId(), $criteria, $row->count_winners);
Хмммм, ну критериями служат заполненные (или нет) $row->towns, $row->groups, $row->pinned_down. Они либо есть, либо их нет.
Тогда метод getRandomUsers станет god mode, если я туда запихаю всю логику фильтров applyTowns() applyGroups() applyCheckFixed():

Код: Выделить всё

  public function getRandomUsers($count = 1)
  {
    if(empty($this->usersList))
    {
      return [];
    }

    shuffle($this->usersList);

    if($count > count($this->usersList))
    {
      $count = count($this->usersList);
    }

    $random_array_keys = array_rand($this->usersList, $count);

    return array_values(array_intersect_key($this->usersList, array_flip((array) $random_array_keys)));
  }
Сейчас метод getRandomUsers просто возвращает заданное количество записей в случайно порядке.
Я думал логику фильтров оставить на месте, а их "применять/не применять" перенести в констурктор
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Толстый конструктор

Сообщение ElisDN »

Со спецификацией метод будет тонким:

Код: Выделить всё

public function getRandomUsers(array $users, Specification $specification, $count = 1)
{
    return array_slice(self::random(array_filter($users, function ($user) use ($specification) {
        return $specificacion->isSatisfiedBy($user);
    })), 0, $count);
}
jakiro
Сообщения: 553
Зарегистрирован: 2013.03.05, 15:15

Re: Толстый конструктор

Сообщение jakiro »

ElisDN писал(а): 2017.08.01, 13:59 Со спецификацией метод будет тонким:

Код: Выделить всё

public function getRandomUsers(array $users, Specification $specification, $count = 1)
{
    return array_slice(self::random(array_filter($users, function ($user) use ($specification) {
        return $specificacion->isSatisfiedBy($user);
    })), 0, $count);
}
Ой, новый паттерн для меня :) Спасибо, сейчас буду разбираться
Хотя наверное вместо self::random можно shuffle сделать, если мы все равно делаем array_slice срезаем
jakiro
Сообщения: 553
Зарегистрирован: 2013.03.05, 15:15

Re: Толстый конструктор

Сообщение jakiro »

ElisDN писал(а): 2017.08.01, 13:59 Со спецификацией метод будет тонким:

Код: Выделить всё

public function getRandomUsers(array $users, Specification $specification, $count = 1)
{
    return array_slice(self::random(array_filter($users, function ($user) use ($specification) {
        return $specificacion->isSatisfiedBy($user);
    })), 0, $count);
}
А блин не получится isSatisfiedBy проверять каждого пользователя. Потому что за каждым пользователям лазить проверку устраивать (это запросы). А тут у меня получается сразу вся в три запросы выгребается из api. Если только заранее по всем пользователям слазить за информацией.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Толстый конструктор

Сообщение zelenin »

Код: Выделить всё

$randomService = new RandomService;

$condition = new RandomCondition;
// or
$condition = (new RandomConditionBuilder)->applyA()->applyB()->build();

$randomService->getUsers($condition);
вообще у вас странный сервис, хранящий состояние.
jakiro
Сообщения: 553
Зарегистрирован: 2013.03.05, 15:15

Re: Толстый конструктор

Сообщение jakiro »

zelenin писал(а): 2017.08.02, 11:40

Код: Выделить всё

$randomService = new RandomService;

$condition = new RandomCondition;
// or
$condition = (new RandomConditionBuilder)->applyA()->applyB()->build();

$randomService->getUsers($condition);
вообще у вас странный сервис, хранящий состояние.
Ну вероятно его не стоило сервисом называть. По факту это класс, который получает массив пользователей и накладывает на него фильры, выпиливая неугодных.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Толстый конструктор

Сообщение zelenin »

если есть репозиторий, сделайте один метод findByCondition, который умеет с Condition работать, а random может быть частью Condition, или отдельным сервисом.
Сам Condition собирайте как хотите (см. выше).
Ответить