Come ridurre la ridondanza in un servizio implementato utilizzando l'architettura multilayer mantenendo la coerenza nel sistema?

2

Attualmente il nostro servizio è implementato utilizzando un'architettura multistrato che divide l'intero servizio in tre:

  • API
  • Affari
  • Persistenza

Tuttavia questo introduce molta ridondanza all'interno del nostro sistema. Un comune adagio nel settore è "DRY" (Do not Repeat Yourself). La ridondanza ha aumentato i tempi di sviluppo e reso il sistema più fragile e ingombra il nostro codice con metodi di "copia".

Per dare un'idea migliore, diciamo che abbiamo un servizio Person . Ciò richiederebbe quanto segue:

  • Person entity - Classe annotata JPA per ORM
  • Richiesta del servizio di repository - contiene i valori dei campi da perseguire dell'oggetto Dominio persona con opzioni di persistenza aggiuntive
  • Risposta del servizio di repository - contiene i valori di campo dell'entità Person
  • Person - classe con business logic, campi di dominio e campi calcolati
  • Richiesta del servizio di dominio - contiene valori di campo di Person risorsa e opzioni aziendali aggiuntive
  • Risposta al servizio di dominio - contiene valori di campo di Person oggetto business esclusi quelli che non dovrebbero essere visibili agli utenti API
  • Person risorsa - classe che rappresenta ciò che dovrebbe essere visibile agli utenti API

E le cose peggiorano quando si prendono in considerazione oggetti nidificati.

Il design attuale facilita la differenza tra preoccupazioni (business, API, persistenza), tuttavia:

  • Attualmente le differenze sono molto piccole. Questo ci sta causando classi molto simili con solo piccole differenze
  • Servizi di ritorno oggetti di risposta del servizio con campi anziché solo gli oggetti esso stesso ostacola altri servizi a seconda di altri servizi

Domande:

  • Ne vale la pena di portare a termine questo design?
  • Quali sono le nostre alternative?
  • Che cosa potremmo cambiare per migliorare la nostra situazione?
posta Chad 30.08.2015 - 10:58
fonte

2 risposte

1

A prima vista, trovo la tua architettura eccessivamente complessa .

Qual è lo scopo di avere una persona ( @Entity ), una ServiceRequest , ServiceResponse , DomainServiceRequest , DomainServiceResponse oltre a dormire bene la notte con le astrazioni per il sake delle astrazioni?

Stai affogando cuccioli qui

Nel backend dell'applicazione, utilizzando solo il Person POJO (= Entity ) sarebbe sufficiente.

In una tipica applicazione (web-) in stile MVC hai una percentuale di% di rest-% in cui tutte le richieste dalla terra "esterna". A seconda dell'azione richiesta, puoi fare una richiesta al repository per interrogare dati (es. Controller che chiami GET /api/users/1 e restituire il risultato) o chiedi a un servizio di manipolare dati o fare qualcosa di più complesso di un semplice recupero dei dati .

Allora hai servicelayer , dove si trova la tua logica aziendale e il tuo personRepository.findOne(1) è manipolato. Le modifiche vengono quindi mantenute in Livello repository (ad esempio POJOS ).

Questa è un'architettura piuttosto pragmatica che ortodossa: interrogare i dati in personRepository.save(person) non è una separazione al 100% delle preoccupazioni - d'altra parte, cosa si otterrebbe, quando la query è incapsulata nel livello di servizio

Potresti anche andare oltre e organizzare il tuo codice in modo tale che tu abbia un pacchetto Controller che contiene Person , Controller e Service , il che rende più facile il taglio successivo del tuo app in servizi separati (se necessario).

Oltre all'utilizzo interno di Repository , forse ha senso utilizzare un altro oggetto di modellazione da trasferire sul filo. Dipende dal caso d'uso.

The redundancy has increased the development time, and made the system more fragile and cluttered our code with "copy" methods.

Questo è un chiaro segnale che la tua architettura ha bisogno di una revisione.

Il tuo design è un tipico onion -design: ha molti livelli e ti fa piangere.

    
risposta data 30.08.2015 - 12:04
fonte
1

Se la tua opinione personale è già che è troppo lavoro, allora sì, guarda come semplificare la progettazione unendo o omettendo certe classi.

Alcune cose da considerare:

  • Unisci l'entità e le classi di business. Se può essere fatto in modo 'pulito' con il tuo framework ORM.
  • Sii adattabile. Per alcune classi folli puoi beneficiare di tutta questa infrastruttura, ma semplifica i semplici casi. Se una Person ha una proprietà Ethnic che ha schermate di amministrazione che stanno praticamente prendendo i campi dell'interfaccia utente e aggiornandole nel database, non preoccuparti di tutto il sovraccarico. Un DTO, un'entità e un repository generico possono fare il trucco.
  • Richiesta / Risposta / classi di risorse: qui ci sono diverse opzioni
    • Consenti al servizio di repository e al servizio di dominio di essere più intimi: utilizza le stesse classi di richiesta / risposta per questo limite.
    • Richiesta del servizio di repository: se estrai tutte le opzioni nella sua classe, potresti non averne più bisogno. (Particolarmente utile se dovessi finire con una / poche classi di opzioni identiche) - potrebbero essere usate classi di opzioni simili invece di oggetti di richiesta di servizio speciali del dominio.
    • Risposta del servizio di dominio: questi potrebbero già essere restituiti direttamente dal repository o dal livello di dominio in quei casi in cui i livelli sottostanti non fanno effettivamente nulla con i campi che sono stati rimossi.
  • Mantieni i repository verso il basso usando root aggregati per oggetti nidificati. ex: il repository Person aggiorna automaticamente / inserisce / elimina tutto Hobby s invece di avere il proprio Hobby Repository.

Tieni presente che se hai grandi composizioni di oggetti tutta questa serializzazione / deserializzazione tra i livelli potrebbe iniziare a ricevere un tempo notevole.

    
risposta data 30.08.2015 - 12:09
fonte

Leggi altre domande sui tag