A quale livello appartiene un generatore di query?

4

Nel mio progetto ho specificato 5 sottolivelli per il mio DBAL:

  1. Database Layer (il database stesso)
  2. Database Connection Layer (\ PDO e una classe che gestisce le connessioni al database)
  3. Database Request Layer (classi che interrogano effettivamente il database)
  4. Livello del modello di database (tutte le classi che rappresentano 1 tabella di database ciascuna e una classe di fabbrica che consente di accedere facilmente a tutte le classi del modello)
  5. Livello del modello (classi che combinano diverse classi di modelli di database per farle funzionare insieme)

Ora ho impostato la restrizione che ogni livello DOVREBBE avere accesso solo alle classi del proprio livello o delle classi direttamente sotto (il Livello 4 PU access accedere ai Layer 4 e 3 ma NON DEVE accedere al Livello 5 e NON DOVREBBE accedere ai livelli 1 e 2) . Ma quando si tratta di un generatore di query (ho deciso di utilizzare il link in quanto non richiede un connessione al database) Mi chiedo a quale livello questo dovrebbe essere assegnato e dove dovrei usarlo.

Chiaramente la query risultante dovrebbe essere passata al livello 3, quindi il generatore di query dovrebbe essere 3 o 4, ma nella maggior parte dei casi sembra che sia più probabile che tu debba creare una query nel livello 5 quando voglio creare un po 'di livello 4 oggetti.

Attualmente il mio codice che usa il generatore di query è simile a questo (nel livello 5):

$builder = $this->entityFactory->getDbRequest()->getQueryBuilder();
// build the $query
$entity = $this->entityFactory->makeEntityByQuery( Entityname::class, $query);

Così attualmente ho localizzato il QueryBuilder nel Layer 3 ma questo mi costringe ad accedere al Layer 3 dal Livello 5 che vorrei evitare. Potrei spostarlo sul layer 4, ma poi dovrei renderlo dipendente dalla maggior parte delle Classi del Model Layer o renderlo accessibile direttamente da EntityFactory. Ma ancora una volta EntityFactory avrebbe 2 responsabilità, che violano SRP.

In quale livello utilizzi o vuoi utilizzare il Query Builder?

    
posta Tekay37 14.02.2017 - 13:09
fonte

2 risposte

2

Sembra il livello 3, il livello di richiesta del database ha bisogno di questo. In primo luogo, ad essere onesti, la stratificazione potrebbe utilizzare il fissaggio. Se hai "livelli" e la domanda "quale livello fa questo?" non si può rispondere facilmente se non si dispone di livelli sufficienti o non si dispone dei livelli giusto .

Cosa hai:

  1. Livello database

  2. Livello connessione database

  3. Livello richiesta database

  4. (questo è il tuo problema) Database Model Layer

  5. (e così è) Layer modello

Livello 3, il livello di richiesta del database è il luogo in cui appartiene il tuo generatore di query. Niente di fuori di quel livello dovrebbe fare query ad hoc. In realtà, il Layer 3 viene più comunemente chiamato DAL (Data Access Layer) o Repository Layer. Questo è il livello che conosce il database. Dovrebbe anche conoscere le fabbriche necessarie per generare i tuoi oggetti entità.

Pensa al DAL o al Repository come livello di coordinamento tra due sottostrati: i layer Richiesta database e Entity Factory.

Cosa ti serve veramente:

         +----------+
         | Database |
         +----------+
              /\
              ||
              ||
              \/
+----------------------------+    +---------------+    +----------------+    +--------+
| Database Request (Gateway) |    | Query Builder |    | Entity Factory |    | Entity |
+----------------------------+    +---------------+    +----------------+    +--------+
              /\                      /\                       /\                /\
              ||                      ||                       ||                ||
              ||                      ||                       ||                ||
              ||                      ||      ++===============++                ||
              ||                      ||      ||                                 ||
              ||                      ||      ||                                 ||
              ||                      \/      \/                                 ||
              ||                    +------------+                               ||
              ++==================> | Repository | <=============================++
                                    +------------+
                                          /\
                                          ||
                                          ||
                                          \/
                                 +------------------+
                                 | Your Application |
                                 +------------------+

Le tue classi di entità non dovrebbero assolutamente conoscere la persistenza. È il repository / DAL che coordina tra più livelli sottostanti, incluso il tuo generatore di query.

Nulla al di fuori del repository / DAL dovrebbe avere qualcosa da fare con il generatore di query. Questa è un'utilità per semplificare la costruzione di query SQL. Invece, è possibile fornire un oggetto di trasferimento dati (DTO) che conterrà tutti i possibili valori dei criteri se è necessario eseguire una ricerca. Il repository / DAL deve avere un metodo che accetta questo criterio DTO come argomento e quindi utilizza il DTO per creare una query utilizzando il Generatore di query.

Da ciò, qualcos'altro deve tradurre l'oggetto del generatore di query in una richiesta al database. È possibile creare un'altra classe denominata Query Executor che converte il Generatore di query e crea una richiesta DB o semplicemente passa il generatore di query direttamente all'oggetto di richiesta DB. Sì, "rompere la separazione dei livelli" ma quanto accoppiamento hai veramente introdotto? Dipende da te.

Una volta che la tua applicazione raggiunge la complessità in cui hai una domanda come questa, devi investire il tuo tempo nell'apprendimento e nella configurazione di un buon Object Relational Mapper (ORM).

So I Inject those repository classes to my Application classes?

Sì, ma in genere solo i controller e le classi di servizio avranno bisogno di accedere agli oggetti del repository.

Are those repository classes manually created in the controller (or the DI-Container respectively)?

Un po 'essere "Sì" e un po' "No".

Se usi Dependency Injection, il contenitore DI o un oggetto factory che sforna i controller istanzia il repository.

Se inserisci le interfacce per il tuo repository, puoi avere entrambi:

interface IFooRepository
{
    public function find($id);
}

class FooRepository implements IFooRepository
{

}

class FoosController
{
    public function __construct(IFooRepository $repository = null) {
        if (!isset($repository)) {
            $repository = new FooRepository();
        }

        $this->repository = $repository;
    }
}

Il costruttore del controller accetta un IFooRepository come argomento. Se null viene impostato automaticamente sull'implementazione concreta FooRepository . Ora puoi effettivamente testare i tuoi controllori fornendo una simulazione o uno stub dell'interfaccia IFooRepository .

    
risposta data 14.02.2017 - 18:11
fonte
0

Se il generatore di query è in L3 e si accede da L5, è possibile aggiungere un wrapper sottile per il generatore di query in L4 in modo da accedere al wrapper L4 da L5 e il wrapper L4 accede a L3. Tranne che L4 è per le classi che rappresentano una singola tabella, quindi un wrapper per un generatore di query non sembra proprio adattarsi qui ...

Quindi, forse non tutto si adatta perfettamente a questi livelli, ma forse va bene un po 'di tempo. Forse è anche un problema se i livelli sono disposti in una gerarchia stretta, quando la relazione tra loro è un po 'più complessa.

Forse sei troppo restrittivo nel modo in cui pensi alla struttura del tuo codice?

    
risposta data 14.02.2017 - 16:25
fonte

Leggi altre domande sui tag