2015-11-29 27 views
7

Ho una certa confusione sull'uso del controller con pattern di repository pur mantenendo il principio SOLID. Si consideri, ho due tipi di citazioniPrincipio SOLID in Laravel con pattern di repository

  1. Preventivo Commerciale
  2. Quotazione privato

e v'è un'alta probabilità di nuovi tipi di citazioni in futuro. Ogni offerta ha campi diversi, logiche di business eppure condividono molte funzioni comuni. Così ho creato un QuotationInterface

Quotazione Inteface

interface QuotationInterface 
{ 
    public function save(array $data); 

} 

classe citazione che implementi l'interfaccia

class CommercialQuotation implements QuotationInterface 
{ 
    public function(array $data) 
    { 
     // save commercial quotation 
    } 
} 

class PrivateQuotation implements QuotationInterface 
{ 
    public function(array $data) 
    { 
    // save Private quotation 
    } 
} 

Quotazione Repository

class QuotationRepository 
{ 
    public function save(array $data, QuotationInterface $quotation) 
    { 
     $quotation->save($data); 
    } 
} 

QotationController

public function store(Resource $resource) 
{ 

    $inputs = $resource->all(); 

    /** 
    * Clearly here Open/Close Principle is broken 
    */ 

    if ($inputs['type'] == 'private'){ 
     $quotation = new PrivateQuotation;; 
    } 
    else if($inputs['type'] == 'commercial'){ 
     $quotation = new CommercialQuotation; 
    } 

    $this->repo->save($inputs, $quotation); 
} 

Qui nel mio QuotationController, è chiaramente violando Open/Close Principio ..

E 'una buona idea per creare un controller per ogni tipo di quotazione (potrebbe essere 10+ un giorno, chi lo sa?) per evitare la violazione OCP o il mio design è solo sbagliato? Qualsiasi suggerimento, consigli sul cambio di design, risorse sono ben accetti.

NOTA: Il mio controller di quotazione avrà molte altre funzioni eccetto il solo salvataggio.

risposta

5

Se stai andando avanti il ​​modo in cui hai mostrato, vi suggerisco di utilizzare un unico controller per i vostri preventivi e utilizzare un fabbrica modello disegno per creare i vostri oggetti $quotation

Ad esempio, con un semplice fabbrica in questo modo:

//FACTORY CLASS 
abstract class QuotationFactory 
{ 
    /** return QuotationInterface */ 
    public static function createQuotation($type) 
    { 
     switch($type) 
     { 
      CASE "private": 
       return new PrivateQuotation(); 
      break; 

      CASE "commercial": 
       return new CommercialQuotation(); 
      break;  
     } 
    } 
} 

è possibile utilizzare la fabbrica dalla metodi controllori:

//YOUR CONTROLLER'S METHOD 
public function store(Resource $resource) 
{ 
    $inputs = $resource->all(); 

    //delegate objects creation to factory class 
    $quotation = QuotationFactory::createQuotation($inputs['type']); 

    $this->repo->save($inputs, $quotation); 
} 

In questo modo non violerai il principio di apertura/chiusura nei tuoi controller, perché quando aggiungi le citazioni, dovrai solo modificare il metodo di fabbrica (aggiungendo casi all'istruzione switch) e restituirà un QuotationFactory oggetto ovunque sia necessario.

Questo sarà anche mantenere il vostro codice di DRY e SOLID perché non c'è bisogno di ripetere il if/else per creare i vostri oggetti nei metodi del vostro controller come si delega la responsabilità della creazione degli oggetti ad un classe industriale specifica

Come indicato correttamente nei commenti qui sotto, la fabbrica semplice ti aiuterà a evitare il Principio Aperto/Chiuso nei tuoi controllori ma sarà utile che, da un punto di vista più generale, la stessa Fabbrica stessa è intrinsecamente violare l'OCP in quanto utilizza un caso switch.

In ogni caso, da quello che vedo della vostra applicazione, la fabbrica semplice potrebbe essere una buona soluzione, poiché la vostra preoccupazione principale è quella di costruire in molti luoghi istanze da un tipo variabile. Quindi, usando la Simple factory puoi "nascondere" questo processo di creazione degli oggetti in fabbrica e ottenere le istanze necessarie nei tuoi controller. Quindi stai violando l'OCP solo all'interno della fabbrica nel caso dell'interruttore, ma penso che questo potrebbe essere un compromesso accettabile

+1

Ho intenzione di seguire il tuo esempio. Grazie. –

+0

La necessità di modificare la fabbrica è una classica violazione del Principio Aperto/Chiuso: significa che il codice non è chiuso alla modifica. In effetti, switch/case è sempre una violazione dell'OCP, motivo per cui non è incluso nel modello di progettazione del metodo Factory GoF. Il modello di progettazione è basato sul polimorfismo. – jaco0646

+0

@ jaco0646: Gli schemi di progettazione non sono regole assolute, ma è importante per adeguarli alla situazione attuale. In un caso come questo una fabbrica semplice potrebbe essere una buona soluzione.Alla fine del mio post, a seconda dell'architettura dell'app, l'op poteva implementare una fabbrica astratta o un metodo factory – Moppo

1

Penso che questo dipenda principalmente dall'ambito dell'applicazione. Di questi tempi, nel mondo PHP, le persone sono così arrabbiate con le dichiarazioni if ​​/ else :). Tuttavia, se ciò funziona per la tua applicazione e sembra ragionevole nell'ambito del tuo contesto, penso che vada bene.

Le aziende cambiano e le modifiche aziendali non sono sempre facili da pianificare. Puoi solo provare a rendere più facili questi cambiamenti quando si presentano.

Ciò detto, le classi sono a buon mercato e penso che avere classi separate a questo punto (e in futuro) sia molto ragionevole. Se i requisiti per ciascun tipo di offerta si espandono, sarai in buona posizione e non credo che tu stia astratizzando fino ad ora che il tuo codice sarà difficile da capire.

+0

Hmm .. Penso che tu abbia ragione .. Non ci sono risposte assolute assolute di questa domanda e quello che hai detto è logico. Devo fare del mio meglio per attenermi alle migliori pratiche, ma a volte devo andare fuori strada a causa del contesto dell'applicazione. –

+0

Questa risposta è così generica ... non potrebbe essere copiata e incollata su ogni domanda di modelli di progettazione PHP su SO? – jaco0646

+0

Generico o no, è realistico. Il fatto è che non puoi applicare una verità assoluta a questo tipo di domande. Sì, ci sono molti modi per fare le cose, e non tutte sono applicabili in ogni contesto. E penso che sia bene pensare a questo tipo di domande e, inoltre, rendersi conto che l'approccio può differire in un dato contesto. – djt