2016-01-29 27 views
6

Sto considerando l'implementazione di Clean Architecture di Robert Martin in un progetto e sto cercando di scoprire come gestire casi d'uso non banali.Architettura pulita - Robert Martin - Use Case Granularity

Mi risulta difficile scalare l'architettura in casi d'uso complessi/composti, in particolare casi d'uso in cui l'attore è il sistema in contrapposizione a un utente, come nel sistema che esegue una sorta di elaborazione in batch.

A scopo illustrativo, supponiamo che un caso d'uso come "sistema aggiorna tutti i saldi dei conti", realizzata in pseudocodice come

class UpdateAllAccountBalancesInteraction { 
    function Execute() { 
     Get a list of all accounts 
     For each account 
      Get a list of all new transactions for account 
      For each transaction 
       Perform some specific calculation on the transaction 
      Update account balance 
    } 
} 

Inoltre, "ottenere una lista di tutti i conti", "Get un elenco di tutti nuove transazioni per conto "," Esegui qualche calcolo specifico sulla transazione "," Aggiorna saldo conto "sono tutti casi d'uso validi e ognuno di essi è già implementato nella propria classe di interazione.

Alcune domande sorgono:

  • È il caso d'uso "aggiornamenti di sistema tutti i saldi dei conti", anche un caso uso valida o dovrebbe essere suddiviso in casi d'uso più piccoli (anche se da un business prospettiva esso sembra avere senso, è uno scenario aziendale legittimo )?
  • Is UpdateAllAccountBalancesInteraction un'interazione legittima?
  • un'interazione è consentita/supposta di orchestrare altre interazioni?
  • Il codice che orchestra altre interazioni appartiene davvero da qualche altra parte?
  • È solo bene avere UpdateAllAccountBalancesInteraction come un'interazione, ma hanno esso funzioni di chiamata condivise dagli altri interattori piuttosto che agire come un orchestratore di altri interattori?

risposta

1

Chiaramente, si dispone di una nuova interazioni di alto livello che condividono alcune (o molte) funzionalità comuni con interazioni di livello inferiore. Questo va bene.

Se l'azienda richiede un caso d'uso denominato UpdateAllAccountBalances, è un caso di utilizzo valido ed è opportuno che lo si assegni in un modo che rifletta la logica aziendale.

È o.k. affinché una interazione possa chiamare altre interazioni, se questo riflette accuratamente la tua logica di business. Ponetevi la seguente domanda: Se i requisiti per UpdateAccountBalance cambiano, dovrebbe interessare anche UpdateAllAccountBalances esattamente nello stesso modo? Se la risposta è sì, il modo migliore per ottenere questo è di avere UpdateAllAccountBalances chiamata UpdateAccountBalance, perché in caso contrario, sarà necessario apportare una modifica in due punti per mantenerli coerenti. Se la risposta è no, allora si vogliono disaccoppiare le due interazioni, e questo può essere fatto facendoli chiamare funzioni condivise.

+0

Ho dovuto prendere una decisione e andare avanti con il mio progetto, quindi ho concluso che gli esempi forniti nella presentazione/[articolo] (https://blog.8thlight.com/uncle-bob/2012/08/ 13/the-clean-architecture.html) sono banali e che la separazione delle dipendenze si riferisce ai livelli, penso che sia facile essere d'accordo. Con questo in mente, ho concluso che il metodo 'Execute()' di un'interazione non dovrebbe chiamare il metodo 'Execute()' di un'altra interazione, ma possono sicuramente condividere il codice nello stesso livello. – PlusInfinite

0

Il mio suggerimento è di affrontare il problema in modo diverso. Rappresenta il problema stesso in un modello di dominio, piuttosto che utilizzare un approccio procedurale. Vedete alcuni dei problemi con Use Cases, uno dei quali è che la loro granularità è generalmente indeterminata.

In un modello di dominio, il modo standard per rappresentare una specifica cosa (ovvero un "account") è con due oggetti.Uno rappresenta l'account specifico e un oggetto associato che rappresenta quelle cose comuni a tutti gli account.

AccountCatalog (1) ---- (*) SpecificAccount 

Nell'esempio, Account specifico avrebbe un servizio (metodo) "AggiornamentoBalance". AccountCatalog ha un servizio (metodo) "UpdateAllBalances", che invia un messaggio UpdateBalance a tutti gli account specifici nella sua raccolta.

Ora tutto può inviare il messaggio UpdateAllBalances. Un altro oggetto, interazione umana o un altro sistema.

Devo notare che può essere normale che un account "sappia" (ovvero mantenga) il proprio saldo, invece di aggiornarlo.

+0

L'approccio [Clean Architecture] (https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html) suggerisce di utilizzare anche un modello di dominio, proprio come l'hai descritto. Questo è un modello di dominio in cui sono definite le entità e le regole del business aziendale, senza dipendenze da nient'altro. Inoltre, suggerisce un livello sopra il modello di dominio, in cui sono implementate le regole aziendali dell'applicazione e l'implementazione dei casi d'uso come classi che si basano su un'interfaccia simile a quella di un modello di comando. La mia domanda riguardava la composizione in questo ultimo livello. – PlusInfinite