Skip to content

abelharisov/php-code-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Задание: Проведите Code Review. Необходимо написать, с чем вы не согласны и почему.

Дополнительное задание: Напишите свой вариант.

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

<?php

namespace src\Integration;

class DataProvider
{
    private $host;
    private $user;
    private $password;

    /**
     * @param $host
     * @param $user
     * @param $password
     */
    public function __construct($host, $user, $password)
    {
        $this->host = $host;
        $this->user = $user;
        $this->password = $password;
    }
    
    /**
     * @param array $request
     *
     * @return array
     */
    public function get(array $request)
    {
        // returns a response from external service
    }
}
<?php

namespace src\Decorator;

use DateTime;
use Exception;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Log\LoggerInterface;
use src\Integration\DataProvider;

class DecoratorManager extends DataProvider
{
    public $cache;
    public $logger;

    /**
     * @param string $host
     * @param string $user
     * @param string $password
     * @param CacheItemPoolInterface $cache
     */
    public function __construct($host, $user, $password, CacheItemPoolInterface $cache)
    {
        parent::__construct($host, $user, $password);
        $this->cache = $cache;
    }

    public function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    /**
     * {@inheritdoc}
     */
    public function getResponse(array $input)
    {
        try {
            $cacheKey = $this->getCacheKey($input);
            $cacheItem = $this->cache->getItem($cacheKey);
            if ($cacheItem->isHit()) {
                return $cacheItem->get();
            }

            $result = parent::get($input);

            $cacheItem
                ->set($result)
                ->expiresAt(
                    (new DateTime())->modify('+1 day')
                );

            return $result;
        } catch (Exception $e) {
            $this->logger->critical('Error');
        }

        return [];
    }

    public function getCacheKey(array $input)
    {
        return json_encode($input);
    }
}
  • Добавить type hint на аргументы и возвращаемые значения методов
  • DecoratorManager нарушает SRP - он одновременно логирует и кеширует запросы - следует сделать два отдельных декоратора LoggingDataProvider, CachingDataProvider
  • Декоратор реализован через наследование - из-за этого нет гибкости настройки декарируемого класса - не получится легко отключить кеширование, но оставить логирование или добавить дополнительные декораторы для других задач, изменять их порядок выполнения, комбинировать и т.д. Также такой декоратор сложнее протестировать. Нужно реализовать декораторы с использованием композиции
  • Декоратор изменяет интерфейс исходного класса - getResponse вместо get. Теряется смысл использования декоратора - расширить поведение не изменяя интерфейса. Нужно выделить интерфейс DataProviderInterface, а DataProvider и декораторы должны его реализовывать
  • Передача зависимости через сеттер setLogger. Эта зависимость обязательна для работы. Ее следует перенести в конструктор. Если разработчик забудет вызывать этот сеттер, то класс будет не верно работать.
  • Обработка исключений в getResponse. В случае какого-либо исключения вызывающий код не сможет отличить пустой ответ от ошибки и не сможет корректно обработать эту ситуацию. Лучше дать возможность отловить и обработать ошибку на уровне выше
  • Метод getCacheKey. По PSR-6 ключ для кеша не должен содержать {}, а в результате json_encode можно получить такой ключ. Лучше воспользоваться каким-либо алгоритмом хеширования для получения хеша. Кроме того, его лучше вынести из класса, а в декоратор передать зависимость новую CackeKeyGeneratorInterface. Тогда алгоритм получения ключа можно будет кастомизировать без изменения самого декоратора
  • Срок годности кэшированного значения жестко задан в коды - из-за этого нельзя изменить этот параметр без изменения класса. Нужно добавить соответствующий параметр в конструктор

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages