Il mio codice viola il principio DRY?

3

Supponiamo che io abbia due servizi Person Service e Company Service e voglio mantenere dei collegamenti tra loro, ad esempio una persona è collegata alla società perché lavora lì o possiede la società ecc. Quindi andrò avanti e creerò un database tabella come

PersonId, CompanyId, RelationType

Ora la logica aziendale può essere scritta in uno dei servizi che il cliente chiamerà per collegarli. Ma cosa succede se ho bisogno di collegare più persone a una singola azienda e più società a una sola persona. Ho bisogno di avere due metodi, uno che prende solo PersonId e l'elenco di CompanyIds e uno che prende CompanyId singolo e più PersonID. Quindi ho scritto due diversi metodi in ogni servizio. Il seguente metodo è in Person Service

void LinkPersonToCompanies(long personId,
                           IEnumerable<long> companyIds,
                           RelationType type)

e sotto il metodo si trova nel servizio aziendale

void LinkCompanyToPersons(long companyId,
                          IEnumerable<long> personIds,
                          RelationType type)

So che questi sono due metodi diversi ma stanno facendo lo stesso compito, cioè la loro logica si ripete. Può diventare difficile da mantenere perché dovrebbe essere apportato un singolo cambiamento nel meccanismo di collegamento a entrambi i metodi. È contro il principio ASCIUTTO? Quale dovrebbe essere il design giusto per risolvere efficacemente questo problema?

    
posta Saad 15.02.2018 - 09:34
fonte

5 risposte

6

I know that these are two different methods but they are doing the same task

No, non lo sono. Uno è collegare una persona a un'azienda. L'altro collega un'azienda a una persona. Possono utilizzare la stessa implementazione per ottenere questi due compiti, ma non sono lo stesso compito.

Supponiamo però che il codice di ciascun metodo sia identico. DRY è stato violato? Sì, perché ti sei ripetuto e hai creato due copie del codice che devono essere mantenute. Ma potrebbe non essere importante. Dopo tutto, se si estrae il codice in un terzo metodo e si hanno i primi due a chiamarlo, ora si è creato un accoppiamento stretto tra i due metodi originali e il terzo. Per chiarire qui, sto dicendo che ciascuno dei due metodi originali è ora accoppiato al terzo; non sono tuttavia accoppiati l'un l'altro. Vale veramente la pena creare quell'accoppiamento solo per evitare di ripetersi?

DRY è il nemico dell'accoppiamento lento. A volte vale la pena ripetersi per evitare l'accoppiamento. A volte vale la pena creare un accoppiamento stretto per evitare di ripetersi. Usa il tuo giudizio per decidere qual è l'opzione migliore nel tuo caso.

    
risposta data 15.02.2018 - 09:57
fonte
3

Se non avevi il tipo di rapporto, puoi refactarlo in

LinkCompaniesToPersons)(
    IEnumerable<string> companyIds, 
    IEnumerable<string> personIds
    );

e salvati un po 'di codice.

Con il tipo in là, è un po 'più di un rapporto molti a molti. Potresti avere:

LinkCompaniesToPersons)(
    IEnumerable<CompanyPersonTypeRelationShip>
    );

Che è più generico, ma aggiunge codice in ogni sito di chiamata.

Vorrei andare con un approccio combinato. Avere il mio secondo metodo come metodo privato nel repository e chiamarlo tramite i tuoi metodi pubblici attuali facili da leggere. Quindi si salva la ripetizione del codice sia nel repository che nei siti di chiamata.

    
risposta data 15.02.2018 - 10:25
fonte
0

Avere queste due funzioni separate aumenta la leggibilità (del codice client, cioè il codice che li chiama più leggibili se li si lascia "duplicati")? Se sì, dico di tenerli separati.

Puoi sempre aggiungere una funzione throw (privata) che eseguirà la logica effettiva e che le delegheranno queste due funzioni, quindi non avrai duplicazioni ma senza diminuire la leggibilità del codice che usa la tua interfaccia.

    
risposta data 15.02.2018 - 09:54
fonte
0

Dipende dalla tua implementazione di LinkPersonToCompanies e LinkCompanyToPersons. Poiché entrambe le funzioni hanno un lavoro leggermente diverso: una collega più persone a una società e l'altra collega più aziende a una persona.

Se riutilizzi lo stesso codice (come replicare la logica o shudder copia-incolla il codice) - allora questa è una violazione del principio DRY.

Se voi, tuttavia, avete delegato il compito (a una funzione comune, che potrebbe anche essere una delle due funzioni stesse), allora non si tratta di una violazione del principio DRY, in quanto vi sono due compiti distinti (come detto prima ) ma hai mantenuto le cose comuni, beh, comuni.

Ad esempio LinkCompanyToPersons potrebbe chiamare LinkPersonToCompanies una volta per ogni persona (o viceversa), oppure entrambi potrebbero chiamare LinkPersonAndCompany una volta per ogni persona o società (a seconda della funzione di chiamata).

    
risposta data 15.02.2018 - 10:23
fonte
0

What should be the right design to efficiently solve this problem?

Cerca di evitare associazioni bidirezionali.

Lei ha citato nei commenti che avete un oggetto Person con una% di raccolta% co_de e Companies con una% di raccolta% co_de. Anche se ci sono due casi d'uso, con una schermata che permette di aggiungere una società per l'elenco delle società di una persona e uno schermo per aggiungere una persona all'elenco delle persone di una società, ciò non significa che gli oggetti persistenti dovrebbe riflettere che .

Le associazioni bidirezionali possono causare problemi di sincronizzazione. Se una società e una persona collegate vengono caricati allo stesso tempo nella memoria come parte della stessa unità di lavoro, è necessario ricordarsi di aggiornare entrambe le parti non appena i loro cambiamenti di relazione.

trasformarla in un'associazione unidirezionale non allevia solo problema, ma ti costringe anche di scegliere quale entità è primario e che è secondario. Si rende il codice molto più semplice di ragionare su perché sai c'è un unico punto di accesso ai cambiamenti nel rapporto, e solo è necessario per essere caricato in memoria. È necessario implementare solo un metodo di servizio Company e non si verificano problemi di duplicazione del codice.

    
risposta data 15.02.2018 - 11:16
fonte

Leggi altre domande sui tag