Rimanere OO e testabile mentre si lavora con un database


16

Quali sono alcune strategie OOP per lavorare con un database ma mantenere le cose testabili? Supponiamo che io abbia una classe User e che il mio ambiente di produzione funzioni con MySQL. Vedo un paio di possibili approcci, mostrati qui usando PHP:

  1. Passa una $ data_source con interfacce per load()e save(), per astrarre la fonte di dati back-end. Durante il test, passare un altro archivio dati.

    $ user = nuovo utente ($ mysql_data_source);
    $ user-> load ('bob');
    $ user-> setNickname ('Robby');
    $ User-> save ();
    
  2. Utilizzare una factory che accede al database e passa la riga dei risultati al costruttore dell'utente. Durante il test, generare manualmente il parametro $ row o simulare l'oggetto in UserFactory :: $ data_source. (Come posso salvare le modifiche al record?)

    class UserFactory {
        static $data_source;
    
        public static function fetch( $username ) {
            $row = self::$data_source->get( [params] );
    
            $user = new User( $row );
            return $user;
        }
    }
    

Ho modelli di progettazione e codice pulito qui accanto a me, ma faccio fatica a trovare concetti applicabili.


Risposte:


11

Quindi quello che vuoi raccogliere è Patterns of Enterprise Application Architecture di Martin Fowlers (Qui fornisce anche un catalogo sul suo sito Web ).

In esso descrive diversi schemi per astrarre l'accesso ai dati. Il primo approccio che descrivi è Active Record . Il secondo approccio è simile a Table Data Gateway .

Un approccio ancora migliore consiste nell'utilizzare un O / RM per rimuovere la necessità di scrivere manualmente il codice di accesso ai dati. Non uso PHP da quando eravamo preoccupati per Y2K, ma Wikipedia ha un elenco di opzioni per te . Non so se siano buoni comunque. Posso dirti alcune cose da cercare in un O / RM comunque:

  • Ignoranza della persistenza : O / RM non dovrebbe forzare i tuoi oggetti business a derivare da una specifica interfaccia / classe per partecipare alla strategia di accesso ai dati.
  • Mappatura delle relazioni : dovresti essere in grado di mappare le relazioni tra i tuoi oggetti (un cliente ha ordini, gli ordini hanno elementi pubblicitari, gli elementi pubblicitari hanno un prodotto, ecc.)
  • Mappatura gerarchica : dovresti essere in grado di mappare le gerarchie di classi sul database.
  • Sintassi della query / Supporto criteri : Dovresti essere in grado di creare una query in fase di esecuzione in termini di oggetti non in termini di database e O / RM dovrebbe tradurre ed eseguire la query sul database. Punti extra se la query è una catena fortemente tipizzata anziché una stringa.

Ci sono altri fattori da considerare, ma questi sono alcuni dei più importanti. Spero che sia di aiuto.


6

IMHO dipende da cosa vuoi testare, se vuoi testare l'unità della tua logica aziendale dovresti stub / deridere ( Martin Fowler ) l'accesso ai dati in modo che il tuo primo suggerimento sia un buon inizio. Questa domanda di StackOverflow fornisce un bell'esempio di C # (ho provato a trovare alcuni esempi di PHP ma non ne ho trovati).

Se si desidera testare l'accesso ai dati in sé non si parla più di unit test ma di test di integrazione. Leggi qui per alcune indicazioni generali, questa domanda di StackOverflow ha anche alcuni link interessanti.

Se si desidera testare la logica della procedura memorizzata nel database, consultare xUnit TestPattern

Spero che sia di aiuto


2

Questa non è necessariamente una risposta immediatamente utile, ma se sei davvero preoccupato per la testabilità del database, dovresti esaminare come viene fatto in Ruby on Rails. Per quanto ne so, nessuno ha trattato l'argomento in modo migliore o più intuitivo.


2
Ruby on Rails implementa il modello Active Record per impostazione predefinita. Potrebbe anche fornire un link: en.wikipedia.org/wiki/Active_record_pattern
Spoike

0

Ti ho raccomandato di verificare la soluzione Symfony Framework per questo tipo di problema. Symfony è un framework OO php con test funzionali.

Ecco un link , hanno usato qualcosa come quello a cui stai pensando.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.