Folosește-te de polimorfism!

Folosește-te de polimorfism!

Am făcut refactor zilele astea la o metodă dintr-o clasă care arăta cam așa:

class DomainData
{
    public function getDataForDomains()
    {
        $host = request()->header('host');
        if ($host === 'domeniu1.com') {
            return $ceva;
        } elseif ($host === 'domeniu2.com') {
            return $altceva;
        } elseif ($host === 'domeniu3.com') {
            return $încăCeva;
        }
    }
}

În multe cazuri chestia asta ar fi mers de minune, dar încalcă principiul Open-Closed: ar trebui să o poți extinde dar să nu o poți modifica. Iar în acest caz, lucrurile ar fi fost modificate periodic, în asemenea hal că s-ar fi ajuns la

Prin urmare, poți face următoarea chestie:

  1. Pui logica pentru fiecare use-case într-o clasă;
  2. Definești o interfață (un contract), ce va fi implementată de fiecare clasă

Interfața

Interfața ar trebui să aibă două metode: una pentru host, alta pentru datele întoarse:

interface Host
{
    public function getHostName(): string;
    public function getData(): array;
}

Implementarea

Fiecare implementare va conține practic logica din fiecare ramură a if-ului de mai sus. De exemplu, ar putea arăta așa:

class Domain1 implements Host // Domain2, Domain3 etc
{
    public function getHostName(): string
    {
        return 'domeniu1.com'; // domeniu2.com, domeniu3.com, etc
    }

    public function getData(): array
    {
        $ceva = [];
        return $ceva;
    }
}

Polimorfismul

Ce înseamnă polimorfism? If it looks like a duck, moves like a duck, quack like a duck, then it’s a duck. Altfel spus, interfața ne va garanta că instanța unei clase va arăta și va funcționa într-un anumit fel.

Prin urmare, modificăm clasa DomainData pentru a i se injecta instanțele potrivite:

class DomainData
{
    private $domains = [];

    public function registerDomain(Host $domain)
    {
        $this->domains[$domain->getHostName()] = $domain;

        return $this;
    }
....

Când e să înregistrăm domeniile, le înregistrăm pe rând:

$domainData = new DomainData;

$domainData->registerDomain(new Domain1);
$domainData->registerDomain(new Domain2);
$domainData->registerDomain(new Domain3);

Și facem refactor la metoda getDataForDomains, astfel încât să eliminăm blocul if/elseif:

public function getDataForDomains()
    {
        $host = request()->header('host');
        return ($this->domains[$host] ?? false) ? $this->domains[$host]->getData() : false;
    }

Și…. cam atât.

Avantaje

Cred că sunt evidente avantajele:

  1. Am redus complexitatea la o singură condiție;
  2. Am închis clasa, astfel încât pentru a adăuga un domeniu nou nu este nevoie să o modificăm;
  3. Am extras responsabilitățile în clase separate;

Un Comentariu

Adaugă un comentariurăspuns pentru

Link-urile în context sunt binevenite. Comentariile fără nume/email valid sunt șterse.
PS: Comentariul NU este editabil.

Acest sit folosește Akismet pentru a reduce spamul. Află cum sunt procesate datele comentariilor tale.

Site-ul blog.iamntz.com utilizează cookie-uri. Continuarea navigării presupune acceptarea lor. Mai multe informații.

windows apple dropbox facebook twitter