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;
}
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 ;
}
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;
}
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;
}
}
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);
}
}
}
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();
});
}
}
Top comments (0)