Come gestire le funzionalità comuni che non sono business logic nell'architettura pulita

2

La regola di dipendenza in Pulisci architettura afferma che:

... that source code dependencies can only point inwards.

Mi sono imbattuto in un problema che non riesco a capire da solo.

Supponiamo che abbia un modulo con regole di business dell'applicazione abr e 2 moduli per servizi che implementano interfacce da abr .

           +---------+
           |   abr   |             Business Layer (defines interfaces
           +---------+             'Service1' and 'Service2')
      +----^         ^---+
 - - -|- - - - - - - - - |- - - - -
      |                  |
+-----+----+       +-----+----+
| service1 |       | service2 |    Dependencies (implement Interfaces 
+----------+       +----------+    define in abr)

Ora i 2 servizi utilizzano la libreria di rete OkHttp e dovrebbero utilizzare la stessa stringa di agente utente per le loro richieste.
Sfortunatamente non so come ottenerlo bene.
Le possibilità sono:

  • Crea un modulo sharedokhttpconfig che entrambi i servizi dipendono da
    Ciò violerebbe la regola di depdency
  • Inserisci il codice in abr
    Ciò violerebbe il fatto che abr non dovrebbe conoscere la rete o anche che i servizi utilizzino okhttp
  • Duplica il codice per impostare l'agente utente in entrambi i servizi
    La duplicazione del codice è errata

Un altro esempio potrebbe essere che il progetto ha 2 diversi moduli dell'interfaccia utente che sono fondamentalmente diversi, ma che in alcuni di essi la logica sarebbe la stessa.
Come formattare l'indirizzo di un utente.

Qualche suggerimento su come gestirlo?

Per chiarire perché penso che violerebbe la regola di dipendenza.

Il abr è il mezzo della mia applicazione, non dovrebbe conoscere l'interfaccia utente o qualsiasi altra cosa, quindi tutte le dipendenze devono puntare nella sua direzione.
Ma quando aggiungo un modulo dal quale dipendono i 2 moduli, mi sembra che puntino verso l'esterno.

           +---------+
           |   abr   |
           +---------+
      +----^ Inwards ^---+
      |                  |
+-----+----+       +-----+----+
| service1 |       | service2 |
+----------+       +----------+
      |     Outwards?    |
      +----v         v---+
           +---------+
           |  snbl   | snbl = share non-business logic
           +---------+

O sta andando in quel modo ok perché dal punto di vista di abr non è cambiato nulla?

    
posta Altoyr 22.08.2017 - 12:59
fonte

3 risposte

1

Dopo una discussione con l'OP, siamo giunti alla seguente conclusione mutuamente condivisa:

Le interfacce di entrambi i servizi sono dichiarate come parte della logica aziendale, mentre le implementazioni non ne fanno parte. Pertanto, ha senso se queste implementazioni dipendono dai dati di configurazione per OkHttp .

La soluzione più promettente per andare avanti è dichiarare il modulo snbl , che include i dati di configurazione, nella stessa cerchia il servizio come implementazioni. Quindi una dipendenza tra questi e i dati di configurazione per OkHttp non costituisce una violazione della regola di dipendenza.

    
risposta data 22.08.2017 - 14:11
fonte
3

Vorrei solo aggiungere qualcosa alla risposta accettata , così come ampliare l'intuizione risposta di Doc Brown. Ciò che è implicito nella Architettura pulita di Uncle Bob è che "sotto" tutto ciò che esiste è un'infrastruttura comune a cui ogni cerchio dipende (ad esempio, le librerie standard fornite con la lingua e, eventualmente, alcuni altri componenti che è possibile scegliere di trattare come standard).

Quindi, si tratta di decidere quale livello di isolamento si desidera per la libreria OkHttp . Supponiamo per un momento che il livello "Dipendenze" corrisponda più o meno alla cerchia "Schede di interfaccia" dello zio Bob; se non ti dispiace questo strato / cerchio a seconda di OkHttp direttamente, allora puoi posizionare snbl lì e farlo riferimento direttamente a OkHttp .

Sevuoi,invece,evitareasecondadiOkHttp,allorapuoiapplicarelostessotruccodiinversionedidipendenzachehaiusatoperiltuolivelloaziendale.Questoèinrealtàciòchel'insertoinbassoadestrarappresenta;maeccoun'altraimmagineI trovata su Internet che mostra come avviene l'inversione:

Fondamentalmente,quellochefaièdichiarareun'interfacciacheiltuolivello"Dipendenze" richiede (nello stesso livello), e poi lo implementerai in un altro strato che è "più lontano". Questo strato esterno corrisponderebbe approssimativamente al cerchio "Frameworks & Drivers"; il tuo componente snbl sarebbe implementato lì, dove sarebbe, di nuovo, riferimento OkHttp direttamente.

Alla fine, vorrei riconoscere che questo è (a meno che non sia terribilmente sbagliato) più o meno ciò che Doc Brown ha detto molto più concisamente nel suo risposta (almeno quando si tratta di punti chiave).

    
risposta data 23.08.2017 - 20:32
fonte
2

Hai fondamentalmente due opzioni:

  • o gestiscilo nello stesso modo in cui lo fai con libs e framework di terze parti: usando Dependency Inversion. È necessario disporre alcune interfacce per "agganciare" la parte SNBL dell'applicazione ai diversi servizi, quindi i servizi dipendono solo dalle interfacce, ma non direttamente da SNBL . Se lo desideri, puoi posizionare la parte SNBL in una cerchia da sola, tra l'anello in cui hai posizionato i servizi e l'anello in cui OkHttp vive

  • oppure, dichiari che SNBL fa parte della stessa cerchia in cui vivono i servizi. Potrebbe non essere "business logic" in senso stretto, ma potrebbe essere una funzionalità di supporto non necessaria da qualche altra parte, quindi il "migliore" posto potrebbe essere ancora il livello della logica aziendale. Questo ti dà la possibilità di omettere DI.

risposta data 22.08.2017 - 14:01
fonte