Devo nidificare repository come bambole russe?

3

tl; dr Posso avere un repository dipendente da un altro repository, dove entrambi implementano la stessa interfaccia?

Sto lavorando su un sistema di analisi dei siti web che implica l'acquisizione di dati da fonti diverse. Una di queste fonti è molto lenta per dataset di grandi dimensioni e l'altra è deprecata e ci stiamo allontanando da essa.

interface TrafficInterface
{
    public function getVisits(DateTime $from, DateTime $to);
}

Ho già un'interfaccia ( TrafficInterface ) per recuperare i dati da entrambe le fonti.

class TrafficRepository implements TrafficInterface
{
    private $client;

    public TrafficRepository($apiClient)
    {
        $this->client = $apiClient;
    }

    public function getVisits(DateTime $from, DateTime $to)
    {
        // get data from an API
    }
}

TrafficRepository viene utilizzato per accedere ai dati dal sistema di monitoraggio corrente.

class LegacyTrafficRepository implements TrafficInterface
{

    public function getVisits(DateTime $from, DateTime $to)
    {
        // get old data that is stored locally
    }
}

LegacyRepository viene utilizzato per accedere ai dati dal vecchio sistema che è archiviato localmente come file JSON.

Voglio creare altri repository che utilizzano TrafficRepository e LegacyRepository come dipendenze.

class CachingTrafficRepository implements TrafficInterface
{

    private $repository;

    public CachingTrafficRepository(TrafficRepository $repository)
    {
        $this->repository = $repository;
    }

    public function getVisits(DateTime $from, DateTime $to)
    {
        // check the cache for data, delegate to the repository if not
        // return data
    }
}

CachingRepository riduce il problema con l'API lenta. Poiché i dati dell'API non cambieranno dopo il periodo corrente (giorno, settimana, ...), potranno essere memorizzati per sempre nella cache.

Incorpora TrafficRepository e gestisce l'aggiunta di dati alla cache quando non è già presente.

class TransitionalTrafficRepository implements TrafficInterface
{
    private $legacy;
    private $caching;

    public TransitionalTrafficRepository(LegacyTrafficRepository $legacy, 
        CachingTrafficRepository $caching)
    {
        $this->legacy = $legacy;
        $this->caching = $caching;
    }

    public function getVisits(DateTime $from, DateTime $to)
    {
        // get data from the relevant repository
        // combine data and return 
    }
}

TransitionalRepository gestisce la combinazione di dati da ciascuna delle fonti in modo che sembriamo avere un'unica fonte per i dati.

  • Esiste un nome per questo sistema (diverso dalla composizione)?
  • Ci sono dei problemi associati a questo?
  • Ci sono alternative migliori?
posta James Fenwick 24.03.2017 - 20:14
fonte

2 risposte

4

Is there a a name for this system (other than copmosition)?

Tipo di. Avere un'interfaccia e quindi un'implementazione che implementa l'interfaccia, mentre avvolge un'altra istanza dell'interfaccia (il tuo CachingTrafficRepository dovrebbe funzionare davvero contro qualsiasi TrafficInterface , non solo TrafficRepository ) è chiamato il Pattern di decorazione . Il caching è un classico esempio in cui può essere utilizzato.

Il tuo TransitionalTrafficRepository è il classico Pattern composito .

Al di fuori della nota di flessibilità di cui sopra, questi sembrano ottimi casi per questi modelli e difficilmente troverai alternative migliori, tranne forse per eliminarne la necessità.

    
risposta data 24.03.2017 - 20:21
fonte
0

Risposta breve: , il tuo repository può "dipendere da" un altro repository.

Potresti voler dare un'occhiata a qualcosa come Data Access Object (DAO) .

Il punto qui è che ti stai nascondendo COME ottieni i dati di cui hai bisogno. Il tuo codice non deve preoccuparsi se i dati provengono da un database legacy, da un file locale, da un complesso back-end di Hadoop o da un mocking immediato.

Avrai bisogno del tuo repository o dipendenza più profondo / interiore per definire questa interfaccia DAO di base. Quindi gli altri repository aggiungono o definiscono nuovi oggetti che implementano questa interfaccia DAO di base. Puoi usare Decoratori e Composizione come necessario in questi repository (come suggerisce @Telastyn).

    
risposta data 24.03.2017 - 20:37
fonte