La ce folosesc interfețele

La ce folosesc interfețele

După articolul cu Swiftype și Algolia, un cititor m-a întrebat: cum poți folosi ambele servicii fără prea mari bătăi de cap. Răspunsul a fost: folosești contracte.

În PHP, contractele astea se numesc interfețe. Practic spui că o clasă va avea anumite metode, vor accepta un anumit număr de parametri și vor returna un anumit tip de date (presupunând că ai PHP 7.3+).

Contractul§

La oricare dintre aceste două servicii avem nevoie cam de aceleași funcționalități: adăugare/editare/ștergere/căutare. Practic este un soi de CRUD overglorified.

interface Engine
{
    public function indexDocument(Document $document): bool;

    public function getDocumentByID(string $documentID): array;

    public function search(string $query, array $filters = []): Results;

    public function updateDocument(string $documentID, Document $document): array;

    public function deleteDocuments(array $documentIDs, bool $hardDelete = false): bool;
}

Execuția contractului (implementarea)§

În toată treaba asta avem câteva type hints. De exemplu:

 public function indexDocument(Document $document): bool;

Înseamnă că metoda asta va accepta o implementare a interfeței Document și va returna un boolean, în funcție de rezultat.

Motivul pentru care este nevoie de interfețe este următorul: în ciuda faptului că API-ul și structura datelor dintre cele două servicii sunt asemănătoare nu sunt chiar identice 1:1. Deci este nevoie de o implementare diferită pentru fiecare. De exemplu în Swiftype avem așa:

use Swiftype\AppSearch\ClientBuilder;
use Swiftype\AppSearch\Client as SwiftypeClient;

class Swiftype implements Engine
{
    protected $apiKey;
    protected $apiEngine;
    protected $apiEndpoint;

    public function __construct($key, $engine, $endpoint)
    {
        $this->apiKey = $key;
        $this->apiEngine = $engine;
        $this->apiEndpoint = $endpoint;
    }

    protected function client(): SwiftypeClient
    {
        return ClientBuilder::create($this->apiEndpoint, $this->apiKey)->build();
    }

    public function deleteDocuments(array $documentIDs, bool $hardDelete = false): bool;
    {
        if ($hardDelete) {
            return $this->client()->deleteDocuments($this->apiEngine, $documentIDs);
        }
  // implementează soft delete mai departe
    }

Pe când implementarea din Algolia este ușor diferită:

    public function deleteDocuments(array $documentIDs, bool $hardDelete = false): bool;
    {
        if ($hardDelete) {
            return $this->index()->deleteObjects($documentIDs);
        }
  // implementează soft delete mai departe
    }

Și este cam aceeași situație la toate metodele, mai ales la search!

Și repetăm aceeași șmecherie și la interfețele Results respectiv Document, unde Results este, practic, o colecție de Documente. Pare mai îmbârligat decât este de fapt :)

Faptul că avem aceste interfețe și că implementăm codul în baza lor, ne permite să facem o scamatorie de forma:

$engine->deleteDocuments(['doc-123']);

Fără să ne facem griji despre ce tip de date acceptă metoda sau ce întoarce.

Am mai scris despre interfețe și aici:

Adaugă un comentariurăspuns pentru

Poți adăuga bucăți de cod folosind [code]codul tău aici[/code], [js][/js], [php][/php] etc.

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

Acest site 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