L'elettricità statica è negativa, ma per quanto riguarda il modello Factory?


13

Sono su un progetto TDD, quindi cerco di attenermi il più possibile alle buone pratiche coinvolte in quel tipo di sviluppo. Uno di questi sta evitando il più possibile statico e globale.

Sto affrontando questo problema: ho un oggetto "articolo" che può avere "opzioni" ("micro-articoli" aggiuntivi) collegati ad esso.

Non riesco a capire come avere un buon approccio che non sia controproducente o generi troppe query perché mi troverei in una situazione in cui tutto è così disaccoppiato che dovrò fondamentalmente fare 1 query per oggetto.

Dal mio punto di vista reale, vedo 3 opzioni:

1) Costruire all'interno dell'articolo:

class Article
{
    //[...]
    public function getArrOption(){
        //Build an array of Options instance.
        //return an array of Options.
    }
}

Pro: dritto

Cost: Manutenibilità: l'oggetto articolo ora contiene la logica di costruzione per l'oggetto Option. Ciò porterà probabilmente alla duplicazione del codice.

2) Utilizzo di un'opzione Factory

class Article
{
    //[...]
    public function getArrOption(){
        return OptionFactory::buildFromArticleId($this->getId());
    }
}

Pro: la logica di costruzione non è fuori dalla classe Article

Costante: sto infrangendo la regola "statico è difficile da deridere", rendendo difficile testare la mia classe di articoli.

3) Separare tutte le logiche.

//Build the array of Option instance in a controller somewhere, using a Factory:
$arrOption = OptionFactory::buildFromArticleId($article->getId());

Pro: l' articolo gestisce solo la propria responsabilità e non si preoccupa del collegamento "padre" alle opzioni. Le cose sono davvero disaccoppiate

Cost: richiederà più codice all'interno del controller ogni volta che avrò bisogno di accedere alle Opzioni. Ciò significa che non dovrei mai usare una Fabbrica all'interno di un oggetto, e quel tipo di suono per me utopico ...

Qual è il modo migliore per andare? (Mi sono perso qualcosa?) Grazie.

Modificare:

Per non parlare del fatto che se non riesco a chiamare factory inside class, non posso praticamente mai usare lo schema di inizializzazione pigra ...


Non sono sicuro che sia pertinente, ma sto programmando in PHP, quindi "applicazione" è meno stato. Dobbiamo ricaricare tutti i dati tra ciascuna pagina se non sono memorizzati in un cookie di sessione. Ciò significa che non possiamo precaricare tutto come in una lingua dell'applicazione.
FMaz008,

@job: Beh, è ​​perché una chiamata statica all'interno di un metodo è per lo più impossibile da sostituire durante il test dell'unità. L'obiettivo è utilizzare l'iniezione di dipendenza. Ma una fabbrica di solito è statica, quindi non può essere iniettata.
FMaz008,

Risposte:


12
  1. Statico non è "cattivo", è smontabile. Puoi ancora usarlo dove deridere non ha senso.

  2. Questo non è un modello Factory, sembra un modello Repository, anche se potrebbe non esserlo. Factory è dove hai più classi con la stessa interfaccia / classe base e vuoi separare la logica che decide quale classe restituire. Il repository ottiene i dati dal suo repository, estraendo l'implementazione di quel repository (l'articolo non ha bisogno di sapere se le sue opzioni sono memorizzate nello stesso DB, un altro, un file XML, un file CSV, qualunque cosa).

  3. Hai ignorato la possibilità di assegnare alla classe Article un oggetto ObjectFactory (o Repository o quant'altro) nel costruttore su cui può chiamare il metodo buildFromArticle.

Il mio PHP è arrugginito, ma penso che assomigli a questo:

class Article
{
    private $_option_repository;

    public function __construct($option_repository) {
        $_option_repository = $option_repository;
    }

    //[...]

    public function getArrOption(){
        return $_option_repository->buildFromArticleId($this->getId());
    }
}

Penso che questo soddisfi tutti i tuoi professionisti sopra.


Quindi va bene avere istanze di Factory / Repository / Mapper? Avrò bisogno di un contenitore di dipendenza o qualcosa del genere perché se dobbiamo iniettare tutto il factory / repository / mapper per tutto il possibile oggetto che può essere restituito da un oggetto, ciò ha rapidamente fatto molto. (Articolo -> Gruppo di opzioni -> Opzione -> Articolo, ecc.)
FMaz008

1
È più che ok, è preferibile. In genere mi riservo un uso statico per rimuovere il codice ripetuto, dove è abbastanza piccolo da poter essere testato in più classi. E sì, un container IOC / DI renderà la tua vita molto più semplice. Usane uno.
pdr,

1

Ecco una citazione dalla carta che sostiene che non hai mai bisogno di metodi statici, che le fabbriche astratte hanno dimostrato di essere fonte di confusione e suggerisce una leggera modifica del linguaggio verso l'iniezione di dipendenza come soluzione.

Lo stretto accoppiamento tra istanze e le loro classi interrompe l'incapsulamento e, insieme alla visibilità globale dei metodi statici, complica i test. Rendendo l'iniezione di dipendenza una caratteristica del linguaggio di programmazione, possiamo eliminare del tutto i metodi statici. Utilizziamo i seguenti cambiamenti semantici:

(1) Sostituire ogni occorrenza di un globale con un accesso a una variabile di istanza;

(2) Consenti a quella variabile di istanza di essere automaticamente iniettata nell'oggetto quando viene istanziata.

"Seuss: disaccoppiamento delle responsabilità dai metodi statici per la configurabilità a grana fine"

Wayback Machine Link


3
Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia.
moscerino del
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.