Secondo me, non è assolutamente così. Ed è una violazione di DRY.
L'idea è che l'oggetto entità / dominio nel mezzo sia modellato per rappresentare il dominio nel modo più buono e conveniente possibile. È al centro di tutto e tutto può dipendere da esso poiché il dominio stesso non cambia la maggior parte delle volte.
Se il tuo database esterno può archiviare direttamente quegli oggetti, mapparli in un altro formato per separare i livelli non è solo inutile, ma crea duplicati del modello e questa non è l'intenzione.
Per cominciare, l'architettura pulita è stata realizzata pensando a un ambiente / scenario tipico diverso. Applicazioni server aziendali con livelli esterni behemoth che richiedono i propri tipi di oggetti speciali. Ad esempio database che producono SQLRow
oggetti e necessitano SQLTransactions
in cambio di aggiornamenti di elementi. Se dovessi usare quelli al centro, dovresti violare la direzione della dipendenza perché il tuo core dipenderà dal database.
Con ORM leggeri che caricano e archiviano oggetti entità, non è così. Fanno la mappatura tra il loro interno SQLRow
e il tuo dominio. Anche se hai bisogno di inserire @Entitiy
un'annotazione dell'ORM nel tuo oggetto dominio, direi che questo non stabilisce una "menzione" del livello esterno. Poiché le annotazioni sono solo metadati, nessun codice che non le sta cercando specificamente le vedrà. E, cosa ancora più importante, nulla deve cambiare se li rimuovi o li sostituisci con un'annotazione di un database diverso.
Al contrario, se cambi il tuo dominio e hai creato tutti quei mappatori, devi cambiare molto.
Emendamento: sopra è un po 'semplificato e potrebbe anche essere sbagliato. Perché c'è una parte in un'architettura pulita che vuole che tu crei una rappresentazione per livello. Ma questo deve essere visto nel contesto dell'applicazione.
Vale a dire quanto segue qui https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html
L'importante è che strutture di dati isolate, semplici, passino attraverso i confini. Non vogliamo imbrogliare e passare le entità o le righe del database. Non vogliamo che le strutture di dati abbiano alcun tipo di dipendenza che viola la regola di dipendenza.
Passare entità dal centro verso i livelli esterni non viola la regola di dipendenza, eppure vengono menzionate. Ma questo ha una ragione nel contesto dell'applicazione prevista. Il passaggio di entità in giro sposterebbe la logica dell'applicazione verso l'esterno. Gli strati esterni dovrebbero sapere come interpretare gli oggetti interni, dovrebbero effettivamente fare ciò che dovrebbero fare gli strati interni come lo strato "use case".
Oltre a ciò, disaccoppia i livelli in modo che le modifiche al nucleo non richiedano necessariamente cambiamenti nei livelli esterni (vedere il commento di SteveCallender). In quel contesto, è facile vedere come gli oggetti dovrebbero rappresentare in modo specifico lo scopo per cui sono utilizzati. Inoltre, i livelli dovrebbero dialogare tra loro in termini di oggetti realizzati appositamente allo scopo di questa comunicazione. Questo può anche significare che ci sono 3 rappresentazioni, 1 in ogni strato, 1 per il trasporto tra i livelli.
E c'è https://blog.8thlight.com/uncle-bob/2011/11/22/Clean-Architecture.html che si rivolge sopra:
Altre persone si sono preoccupate che il risultato netto del mio consiglio sarebbe stato un sacco di codice duplicato e molta copia automatica dei dati da una struttura di dati a un'altra attraverso i livelli del sistema. Certamente non lo voglio neanche io; e nulla di ciò che ho suggerito porterebbe inevitabilmente alla ripetizione delle strutture di dati e a una sovraordinata copia sul campo.
Che IMO implica che la semplice copia 1: 1 di oggetti è un odore nell'architettura perché non stai effettivamente usando i livelli e / o le astrazioni corretti.
Spiega in seguito come immagina tutta la "copia"
Separare l'interfaccia utente dalle regole aziendali passando semplici strutture di dati tra i due. Non comunichi ai tuoi controller nulla sulle regole aziendali. Al contrario, i controller scompattano l'oggetto HttpRequest in una semplice struttura di dati vanilla, quindi passano quella struttura di dati a un oggetto interattore che implementa il caso d'uso invocando oggetti business. L'interattatore quindi raccoglie i dati di risposta in un'altra struttura di dati vanilla e li restituisce all'interfaccia utente. Le viste non sono a conoscenza degli oggetti business. Guardano solo in quella struttura di dati e presentano la risposta.
In questa applicazione, c'è una grande differenza tra le rappresentazioni. I dati che fluiscono non sono solo le entità. E questo garantisce e richiede classi diverse.
Tuttavia, applicato a una semplice applicazione Android come un visualizzatore di foto in cui l' Photo
entità ha circa 0 regole aziendali e il "caso d'uso" che le tratta è quasi inesistente e in realtà è più preoccupato per la memorizzazione nella cache e il download (tale processo dovrebbe essere IMO rappresentato in modo più esplicito), il punto di rendere rappresentazioni separate di una foto inizia a svanire. Ho persino la sensazione che la foto stessa sia l'oggetto di trasferimento dei dati mentre manca il vero livello di business-logic-core.
C'è una differenza tra "separare l'interfaccia utente dalle regole aziendali passando semplici strutture di dati tra i due" e "quando si desidera visualizzare una foto rinominandola 3 volte lungo la strada" .
Oltre a ciò, il punto in cui vedo che quelle applicazioni demo non riescono a rappresentare l'architettura pulita è che aggiungono un'enfasi enorme sulla separazione dei livelli per motivi di separazione dei livelli, ma nascondono effettivamente ciò che l'applicazione fa. Ciò è in contrasto con quanto detto in https://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Architecture.html - vale a dire che
l'architettura di un'applicazione software urla sui casi d'uso dell'applicazione
Non vedo quell'enfasi sulla separazione dei livelli nell'architettura pulita. Riguarda la direzione delle dipendenze e si concentra sulla rappresentazione del nucleo dell'applicazione - entità e casi d'uso - in java idealmente semplice senza dipendenze verso l'esterno. Non si tratta tanto di dipendenze verso quel nucleo.
Pertanto, se l'applicazione ha effettivamente un core che rappresenta le regole aziendali e i casi d'uso e / o persone diverse lavorano su livelli diversi, separarli nel modo previsto. Se invece stai scrivendo una semplice app tutta per te, non esagerare. 2 strati con limiti fluidi possono essere più che sufficienti. E i livelli possono essere aggiunti anche in seguito.
BankAccount
ma con regole specifiche dell'applicazione cosa puoi fare con quell'account.