DEV Community

Cover image for Cómo superar una prueba técnica PHP - segunda parte
Roberto Manchado
Roberto Manchado

Posted on

Cómo superar una prueba técnica PHP - segunda parte

Una vez definido nuestro directorio de trabajo y configurado nuestro composer.json, debemos crear las interfaces
necesarias, esto es:

namespace App\Interfaces;

interface MovieDispatcherInterface
{
    public function match(): void;

    public function addTask(MovieInterface $movie): void;

    public function removeTask(MovieInterface $movie): void;

    public function movies(): array;
}
Enter fullscreen mode Exit fullscreen mode

Necesitaremos una clase que encapsule las reglas discriminatorias de manera escalables. Utilizaremos en esta clase el principio Open/Close.

namespace App\Interfaces;

interface RuleInterface
{
    // map some items from a array
    public function map(array $arrayElements) : array ;
}
Enter fullscreen mode Exit fullscreen mode

Y por último la interfaz con los métodos a implementar para las películas:

namespace App\Interfaces;

interface MovieInterface
{
    public function id(): int;

    public function prioridad(): float;

    public function titulo(): string;

    public function estreno(): bool;

    public function descripcion(): string;
}
Enter fullscreen mode Exit fullscreen mode

Una variante de la prueba técnica, consiste en que ya tienes el código preparado. Tan sólo tienes que crear las clases que te solicitan. En esta variante, es muy posible que tengas que ejecutar tests unitarios.

Una vez diseñados nuestras interfaces, procedemos a construir las clases:

declare(strict_types = 1);

namespace App;

use App\Interfaces\MovieInterface;

class Movie implements MovieInterface
{
    public int $id;

    public float $prioridad;

    public string $titulo;

    public bool $estreno;

    public string $description;

    public function __construct(int $id, string $titulo, bool $estreno, string $description)
    {
        $this->prioridad = 5.00 ;
        $this->id = $id;
        $this->titulo = $titulo;
        $this->estreno = $estreno;
        $this->description = $description;
    }

    public function id() : int
    {
        return $this->id;
    }

    public function prioridad() : float
    {
        return $this->prioridad;
    }

    public function titulo() : string
    {
        return $this->titulo;
    }

    public function estreno() : bool
    {
        return $this->estreno;
    }

    public function descripcion() : string
    {
        return $this->description;
    }
}
Enter fullscreen mode Exit fullscreen mode

Nuestro contenedor de reglas, que permitirá añadir las reglas discriminatorias para nuestros requerimientos.
La idea, es tener un conjunto de reglas que comparten una interfaz en común, y cada regla discrimina o actualiza
el array de películas de forma diferente. De esta manera podemos "escalar" el código sin modificar su estructura. (Principios SOLID)

declare(strict_types = 1);

namespace App;

class ContainerRulesArrayMap
{
    private $rules = [];

    private $items = [];

    public function __construct(array $tasks)
    {
        $this->items = $tasks;
    }

    public function addRule(Rule $rule) : void
    {
        $this->rules[] = $rule;
    }

    /**
     * execRule
     *
     * run each rule and aply the filter method
     * to each item from array origin
     *
     *
     * @return void
     */

    public function execRule() : void
    {
        foreach ($this->rules as $rule) {
            $this->items = $rule->map($this->items);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Y nuestro flamante MovieDispatcher:

    declare(strict_types = 1);

    namespace App;

    use App\Interfaces\MovieDispatcherInterface;
    use App\Interfaces\MovieInterface;
    use App\ContainerRulesArrayMap;
    use App\ArrayMap\Titulo;
    use App\ArrayMap\Estreno;
    use App\ArrayMap\Descripcion;

    class MovieDispatcher implements MovieDispatcherInterface
    {
        private array $movies;

        public function addMovie(MovieInterface $movie) : void
        {
            $this->movies[] = $movie;
        }

        public function match() : void
        {
            $rule = new ContainerRulesArrayMap($this->movies);

            $rule->addRule(new Titulo());
            $rule->addRule(new Estreno());
            $rule->addRule(new Descripcion());
            $rule->execRule();

            usort($this->movies, function ($a, $b) {
                return $a->prioridad() > $b->prioridad();
            });
        }

        public function movies() : array
        {
            return $this->movies;
        }

        public function removeMovie(MovieInterface $movie) : void
        {
            $this->movies = array_filter($this->movies, function ($c) use ($movie) {
                return $c->id() !== $movie->id();
            });
        }
    }
Enter fullscreen mode Exit fullscreen mode

Parte 3

Parte 1

Discussion (0)