Evitare costruttori con molti argomenti

9

Quindi ho una fabbrica che crea oggetti di classi diverse. Le possibili classi sono tutte derivate da un antenato astratto. La factory ha un file di configurazione (sintassi JSON) e decide quale classe creare, a seconda della configurazione dell'utente.

Per raggiungere questo obiettivo, factory utilizza boost :: property_tree per l'analisi di JSON. Cammina attraverso il ptree e decide quale oggetto concreto creare.

Tuttavia, gli oggetti prodotto hanno molti campi (attributi). A seconda della classe concreta, l'oggetto ha circa 5-10 attributi, in futuro forse anche di più.

Quindi non sono sicuro di come dovrebbe essere il costruttore degli oggetti. Posso pensare a due soluzioni:

1) Il costruttore del prodotto si aspetta che ogni attributo sia un parametro, quindi il costruttore finirà con 10+ parametri. Questo sarà brutto e porterà a lunghe code di codice illeggibili. Tuttavia, il vantaggio è che la fabbrica può analizzare il JSON e invocare il costruttore con i parametri corretti. La classe del prodotto non ha bisogno di sapere che è stata creata a causa della configurazione JSON. Non ha bisogno di sapere che JSON o la configurazione sono coinvolti.

2) Il costruttore del prodotto si aspetta solo un argomento, l'oggetto property_tree. Quindi può analizzare le informazioni necessarie. Se le informazioni nella configurazione sono mancanti o fuori campo, ciascuna classe di prodotto può reagire correttamente. La fabbrica non ha bisogno di sapere quali argomenti sono necessari per i diversi prodotti. La fabbrica inoltre non ha bisogno di sapere come reagire in caso di configurazione errata. E l'interfaccia del costruttore è unificata e piccola. Ma, come svantaggio, il prodotto ha bisogno di estrarre le informazioni necessarie dal JSON, quindi, sa come è costruito.

Tendo a preferire la soluzione 2). Tuttavia, non sono sicuro se questo è un buon modello di fabbrica. Sembra in qualche modo sbagliato far sapere al prodotto che è stato creato con la configurazione JSON. Dall'altra parte, i nuovi prodotti possono essere introdotti in modo molto semplice.

Qualche opinione su questo?

    
posta lugge86 17.12.2015 - 13:36
fonte

3 risposte

7

Non farei l'opzione 2, perché così hai convissuto per sempre la costruzione del tuo oggetto con l'analisi dell'albero delle proprietà di boost. Se sei a tuo agio con una classe che ha bisogno di molti parametri, dovresti sentirti a tuo agio con un costruttore che ha bisogno di molti parametri, come la vita!

Se la tua preoccupazione principale è la leggibilità del codice, puoi usare il modello di builder, in pratica è il c ++ / java stopgap per mancanza di argomenti con nome. Finisci con cose che assomigliano a questo:

MyObject o = MyObject::Builder()
               .setParam1(val1)
               .setParam2(val2)
               .setParam3(val3)
             .build();

Quindi ora MyObject avrà un costruttore privato, chiamato in Builder :: build. La cosa bella è che sarà l'unico posto in cui dovrai chiamare un costruttore con 10 parametri. La fabbrica dell'albero delle proprietà di boost utilizzerà il builder e, successivamente, se si desidera creare un oggetto MyObject direttamente o da un'origine diversa, si passerà al builder. E il builder ti permette fondamentalmente di nominare chiaramente ogni parametro mentre lo passi, quindi è più leggibile. Ovviamente questo aggiunge un po 'di codice, quindi dovrai decidere se ne vale la pena rispetto al solo chiamare il costruttore disordinato, o raggruppare alcuni dei tuoi parametri esistenti in strutture, ecc. Basta lanciare un'altra opzione sul tavolo.

link

    
risposta data 20.12.2015 - 16:45
fonte
3

NON utilizzare il secondo approccio.

Non è sicuramente la soluzione e porterebbe solo a istanziare le classi nella tua logica aziendale, invece della parte della tua app in cui si trovano le fabbriche.

In entrambi:

  • prova a raggruppare determinati parametri che sembrano rappresentare oggetti simili in oggetti
  • dividere la classe corrente in diverse classi più piccole (avere una classe di servizio con 10 parametri sembra che la classe faccia troppe cose)
  • lasciatelo così com'è, se la tua classe non è in realtà un servizio, ma un oggetto valore invece

A meno che l'oggetto che stai creando sia effettivamente una classe che è responsabile della conservazione dei dati, dovresti provare a rifattorizzare il codice e dividere la classe grande in più piccoli.

    
risposta data 17.12.2015 - 14:04
fonte
0

L'opzione 2 è quasi corretta.

Un'opzione migliorata 2

Crea una classe "front side" che ha il compito di prendere quell'oggetto JSON-structure e scegliere i bit e chiamare i / i costruttore / i di fabbrica. Prende ciò che produce la fabbrica e la dà al cliente.

  • La fabbrica non ha assolutamente idea che un simile coso JSON esista persino.
  • Il cliente non deve sapere quali sono i bit specifici di cui la fabbrica ha bisogno.

Fondamentalmente il "front end" sta dicendo a i 2 Bob: "Mi occupo di clienti redatti quindi gli ingegneri non devono! Ho abilità di persone! " Povero Tom. Se avesse detto solo "Scollego il cliente dalla costruzione, questo risultato è una fabbrica molto coesa"; potrebbe aver mantenuto il suo lavoro.

Troppi argomenti?

Non per il client - comunicazione front-end.

Front-end - fabbrica? Se non sono 10 parametri, il meglio che puoi fare è rimandare il disimballaggio, se non la cosa originale del JSON, quindi qualche DTO. È meglio che passare il JSON alla fabbrica? La stessa differenza che dico.

Prenderemo seriamente in considerazione il passaggio di singoli parametri. Attenersi all'obiettivo di una fabbrica pulita e coesa. Evita le preoccupazioni della risposta di @DavidPacker

Mitigazione di "troppi argomenti"

  • Costruttori di Fabbrica o Classe

    • prendere solo argomenti per la costruzione di classi / oggetti specifici.
    • parametri predefiniti
    • parametri facoltativi
    • argomenti denominati
  • Raggruppamento di argomenti front-end

    • Esamina, valuta, convalida, imposta, ecc. i valori degli argomenti guidati dalle firme del costruttore sopra.
risposta data 18.12.2015 - 19:29
fonte