Come ridurre l'accoppiamento stretto tra due origini dati


10

Ho dei problemi a trovare una soluzione adeguata al seguente problema di architettura.

Nella nostra impostazione (illustrata di seguito) abbiamo 2 origini dati, in cui l'origine dati A è l'origine principale per gli elementi di tipo Foo. Esiste un'origine dati secondaria che può essere utilizzata per recuperare informazioni aggiuntive su un Foo; tuttavia questa informazione non esiste sempre.

Inoltre, l'origine dati A può essere utilizzata per recuperare elementi di tipo Bar. Tuttavia, ogni barra si riferisce a un Foo. La difficoltà qui è che ogni barra dovrebbe fare riferimento a un Foo che, se disponibile, contiene anche le informazioni aumentate dall'origine dati B.

La mia domanda è: come rimuovere l'accoppiamento stretto tra Sottosistema A.1 e DataSourceB?

http://i.stack.imgur.com/Xi4aA.png


10
È un bellissimo schizzo. Quale programma hai usato per disegnarlo?
Marcelo MD,

Voglio anche sapere quale programma hai usato per disegnarlo. Per favore.
Tulains Córdova,

2
yuml.me è il sito che ha usato più che probabilmente per creare il diagramma.
Jason Turner,

1
Non sono DataSourceAe DataSourceBgià disaccoppiato? DataSourceAha una dipendenza da entrambi SubSystemA.1e SubSystemA.2, ma non da DataSourceB.
Tulains Córdova,

1
@fstuijt No, non lo è. Se si modifica SubsystemA.1per utilizzare qualcosa di diverso da DataSourceB, DataSourceAnon lo saprei. DataSourceAimporta solo che SubsystemA.1ha un getFoo(id)metodo. C'è un'astrazione tra DataSourceAe DataSourceB.
Tulains Córdova,

Risposte:


3

Ho creato un'app con quasi la stessa architettura di dati dietro di essa; disponiamo di un database SQL in loco contenente la maggior parte dell'automazione e delle informazioni quotidiane interne, quindi un servizio cloud di terze parti utilizzato per vendite, gestione degli account, personale sul campo, ecc. L'helpdesk necessitava di informazioni provenienti da entrambe le posizioni fisiche dei clienti e attrezzature, e l'avevo preso da due diverse applicazioni fino a quando non sono entrato.

Il lungo e breve è che un'origine dati deve avere un riferimento ai record dell'altra. Nel nostro caso, i dati cloud di terze parti contengono riferimenti ai dati onsite perché è la disposizione su cui abbiamo avuto il massimo controllo. Ora, con un ID per un record da entrambe le origini dati, possiamo ottenere dati da entrambi; con un ID cloud, estraiamo il record dal cloud, otteniamo l'ID in loco e estraiamo i dati in loco. Con un ID in loco, eseguiamo il polling di entrambe le origini dati in base a tale ID.

Nel mio sistema, non ho reso nessuno degli oggetti figlio dell'altro nel livello del dominio; qualsiasi utilizzo dei dati da entrambi i negozi deve conservare due istanze di oggetti. Nessuno dei due è garantito per esistere, motivo per cui l'ho fatto in quel modo; l'app può funzionare solo con dati cloud, o con dati onsite o entrambi, con più limitazioni meno dati ha.

Tuttavia, non è difficile cambiare, soprattutto se si è sicuri che un lato esisterà sempre; includere semplicemente una proprietà nell'oggetto che rappresenta il lato per il quale i dati saranno sempre presenti, ovvero del tipo di oggetto che rappresenta il record dell'altro archivio dati. È possibile una "fusione" più avanzata dei due grafici in uno solo.

Questo tipo di accordo deve necessariamente essere accoppiato ad un certo livello. Puoi avere un DAL in grado di interfacciarsi con entrambi gli archivi di dati, oppure puoi segmentare i DAL, uno per ogni archivio di dati, e avere un livello superiore come un Controller che acquisisca i dati da ciascuno di essi e li agganci insieme. Ma, a un certo livello, il tuo programma deve avere gli strumenti per mettere insieme i dati di queste due diverse fonti di dati.

È possibile ridurre l'accoppiamento richiesto nella maggior parte dei casi estraendo i dettagli esattamente da dove provengono i dati. Se ottieni dati da un servizio web, che ti viene dato come istanze di classi generate, quindi crea un convertitore per creare una copia profonda della classe di servizio in qualcosa che controlli, che non dovrà cambiare se i dati la fonte fa (solo se lo schema fa).

Ora, questa può essere un'impresa enorme; il cloud che utilizziamo ha dozzine di classi di dominio, alcune delle quali hanno centinaia di campi di dati e - ecco il kicker - potresti facilmente dover apportare grandi modifiche al tipo di dati astratto per consentire il passaggio a un altro cloud o altro telecomando fonte di dati. Per questo motivo, non mi sono preoccupato; Uso direttamente il dominio del servizio Web generato e ora che si profila un passaggio dal cloud a un archivio dati fuori sede (ma sotto il nostro controllo), i cui dettagli ancora non lo so, sto semplicemente pianificando di cambiare i moduli e codebehind dell'app, che è dove i dati vengono "combinati", per riflettere il nuovo schema e / o oggetti dati. È un grande lavoro in qualunque modo lo tagli.


Questa risposta copre meglio il problema che ho riscontrato e, a mio avviso, offre anche la migliore risposta finora. Tuttavia, penso che la combinazione di dati provenienti da più fonti sia un problema comune. Qualche modello di progettazione che potrebbe essere d'aiuto?
fstuijt,

1
Alcune variazioni su un modello Factory potrebbero essere utili. Se si dispone di un oggetto CloudInvoice e SqlInvoice (dalle rispettive origini dati) e si desidera creare una singola fattura unificata, creare una Factory che conosce abbastanza su entrambe le origini dati per recuperare ogni metà del record che sta per creare, quindi unisce le informazioni nella tua classe di dominio.
KeithS

4

Un modo per gestirlo è creare un'origine dati aggregata che contenga i dati di entrambe le origini dati in un'unica posizione. Un lavoro verrebbe eseguito periodicamente per verificare la presenza di cambiamenti nelle fonti Ae B, e scrivere i "delta" nell'origine dati aggregata. Ciò trasformerebbe due origini dati strettamente accoppiate in un'unica fonte dati coerente.

Diverse cose potrebbero impedirti di adottare questo approccio:

  • La quantità di dati può essere proibitiva - Una copia completa Ae Bdeve essere fatta, raddoppiando i requisiti di spazio.
  • I dati devono essere attivi : ci saranno periodi tra il momento in cui i dati nella fonte sono cambiati e il lavoro di aggregazione li ha propagati nella fonte aggregata.
  • Devi conciliare i dati con le fonti originali : il compito di spostare le modifiche nelle loro posizioni originali diventa molto più complesso se segui questo approccio.

Sono d'accordo, l'introduzione di uno strato di astrazione è l'approccio preferito
neontapir,

2
Puoi avere un livello di astrazione senza copiare i dati.
smp7d,

@ smp7d Questo nasconderebbe l'accoppiamento dietro un bel front-end; Supponevo che tu stessi già facendo qualcosa del genere nel tuo sistema, perché altrimenti la complessità sarebbe diffusa su tutto il tuo progetto.
dasblinkenlight,

A seconda dell'ambiente DB, questo potrebbe anche essere gestito con una / più viste, eliminando la necessità di copiare i dati.
Walter,

Non sono DataSourceAe DataSourceBgià disaccoppiato? DataSourceAha una dipendenza da entrambi SubSystemA.1e SubSystemA.2, ma non da DataSourceB.
Tulains Córdova,

1

Sembra che al livello superiore ci siano due tipi: Foo e Bar, e hai solo due azioni di livello superiore: findFoo(...)e findBar(...). Questa è l'interfaccia per il livello I / O.

La descrizione delle fonti di dati implica che ci sono due metodi su A: findFooe findBared un metodo su B: findFooAuxiliaryInformation. In findFoodovrai unire le informazioni da A e B.

Non sono sicuro di quale "accoppiamento stretto" ti riferisci. Ci sono tre tipi di dati contenuti nei due set di dati: Bar, Foo, e FooAuxData. L'accoppiamento tra Fooe FooAuxDataè inerente ai dati di input e non può essere ridotto. Ma quell'accoppiamento dovrebbe apparire solo nel findFoometodo. Questo è il meglio che puoi fare. Il requisito è implementato in un unico posto. Se cambia, devi cambiare quel codice.


0

Non puoi.

Se ho capito bene Fooe Barvengo dsA. Bars appartiene a Foos.
Preferibilmente, non si desidera Barassegnare s a Foos, a meno che non Foosia stato integrato da Foo.enhancedInfoquello dsB.

La tua preferenza per l'assegnazione di Bars a Foos è ciò che sta creando il tuo accoppiamento stretto. Lo qualificherei come una "sfida dei requisiti" che ti sta costringendo a seguire un determinato percorso.

Quindi le sfide tecniche sono che dsBpossono o meno avere informazioni su qualsiasi dato Fooe che dsBpotrebbero anche non essere disponibili.

Devi decidere quanto sia Foo.enhancedInfodavvero dura e veloce questa preferenza . In base a tale requisito, puoi decidere di fornire un oggetto Foo+ Baroppure no. Consentire un non potenziato Fooda fornire complica solo la logica e mi dice che la preferenza non è così severa come potrebbe apparire. Determina quali varianti di Foo, Foo.enhancede le Bartue applicazioni possono supportare e avrai la tua risposta definitiva.

Ci sono altre cose che potresti fare per Fooavvicinare le informazioni correlate e questo potrebbe risolvere alcuni di questi problemi. Il modo in cui la tua domanda viene formulata, sembra che tu stia affrontando il problema a livello di oggetto dati e potresti non essere in grado di considerare le modifiche al tipo di infrastruttura.


Al contrario: Foo s appartiene a Bar s
fstuijt il

@fstuijt Aggiornerò un po 'la mia risposta. Fondamentalmente, rimarrà lo stesso. Devi decidere come vuoi server Bar + Foo's.

0

Se i dati nell'origine dati B non possono essere autonomi, è consigliabile migrarli all'origine dati A, se possibile.

Se sono indipendenti ma correlati, è necessario esaminare la virtualizzazione dei dati . Ciò consentirà alle applicazioni di trattare i dati come un set (quando appropriato) in modo agnostico. A seconda della tua piattaforma, probabilmente ci sarà un framework / libreria esistente che può aiutarti a implementarlo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.