Implementazione di un livello di nascondere la complessità

8

Come parte delle dipendenze del progetto su cui sto lavorando, utilizziamo diversi servizi di base. Questi servizi, ai quali non possiamo apportare grandi cambiamenti, sono un gran casino. A seconda del metodo che invochiamo, dobbiamo convertire i nostri parametri (e restituire i valori) in codifiche, impostazioni locali e fusi orari diversi.

Poiché generiamo questi parametri in più punti nel nostro codice, eseguiamo queste conversioni in più punti. Alcune volte dove li generiamo, prima di passarli dalla nostra parte; qualche volta prima di invocare il metodo nel servizio principale. Quindi il caos si sta diffondendo nel nostro codice e voglio introdurre un livello per isolarlo.

La mia domanda è qual è l'approccio migliore per questo. Inizialmente pensavo di creare solo un servizio / metodo corrispondente a ciascun servizio / metodo che dovevamo usare. Questi metodi eseguono semplicemente la conversione, delegano ai servizi di base ed eseguono la conversione del valore di ritorno. Ma questo sembra in qualche modo ingombrante.

Poi ho pensato di usare le annotazioni, ma non sono completamente sicuro di come usarle. E a quanto ho capito, idealmente avrei bisogno di annotare il metodo invocato. Ad esempio, potrei annotare i parametri con @converToUtc e fare la conversione nell'implementazione dell'annotazione. È corretto? Certo, questo è difficile perché non è il nostro codice e romperà il codice che attualmente usa quei metodi in progetti diversi dal nostro.

Qual è l'approccio migliore per questa situazione?

    
posta user3748908 17.09.2015 - 11:16
fonte

3 risposte

6

Quello che stai cercando di fare è implementare il schema di facciata . Fondamentalmente vuoi mettere una faccia più semplice sul codice base. Probabilmente vorrai creare un set di classi che forniscano un mapping 1: 1 per ogni classe core, quindi utilizzare le classi facade al posto delle classi core. Se i servizi di base sono solo una manciata di metodi in una grande classe monolitica, allora potresti prendere in considerazione la possibilità di suddividerli per dominio funzionale (ad es. Autenticazione, accesso ai dati, funzione aziendale, ecc.) E avere una facciata diversa per ogni dominio. La tua facciata dovrebbe presentare un'interfaccia che abbia senso per il tuo codice e gestire tutta la mappatura e la conversione dei dati necessari per comunicare con i servizi principali.

    
risposta data 17.09.2015 - 14:50
fonte
6

Il problema che stai affrontando è un'istanza di un problema generale che affrontiamo molto spesso in Ingegneria del software: Modellazione degli strumenti per portarli nel nostro specifico dominio problematico mediante livelli di astrazione / conversione.

Hai un'applicazione che risolve un problema. Le entità con le quali contiene, gestiscono e interagiscono sono entità che appartengono al dominio del problema. Sono tutti espressi in termini utili per risolvere il problema in questione e sono "amichevoli" in quanto consentono di concentrarsi sulla risoluzione del problema piuttosto che sprecare tempo e inquinare il codice con conversioni che non hanno nulla a che fare con il problema a portata di mano.

Per tutto il tempo che possiedi tutto il codice, va tutto bene e dandy; ma quando si introducono nell'immagine immagini di strumenti di terze parti (librerie), questi strumenti hanno probabilmente non stati scritti per funzionare all'interno del dominio del problema, quindi richiedono conversioni che sono spesso fastidiose, ingombranti ed errori- prona.

Di solito succede che gli inconvenienti sono minori e affrontiamo semplicemente gli strumenti che ci vengono forniti. Ma quando gli inconvenienti sono maggiori, tanto che rendono la nostra vita quotidiana molto più difficile, o che il risultato finale è più fragile e più incline agli errori, a volte introduciamo livelli di astrazione / conversione tra il nostro codice e gli strumenti che usiamo .

Questi livelli di astrazione / conversione offrono servizi al nostro codice che sono espressi in termini del nostro dominio problematico e delegano agli strumenti di terze parti, eseguendo tutte le conversioni necessarie lungo la strada. Nel fare ciò, questi strati tendono ad astrarre il più possibile le peculiarità degli strumenti che usiamo, in modo da poter, in teoria, sostituire un utensile con uno strumento diverso modificando solo gli strati di astrazione / conversione, senza è necessario modificare la nostra logica di base.

Per quanto riguarda le annotazioni, non vedo come possono aiutare qui. Prima di tutto, se non si possiede il codice sorgente delle interfacce di destinazione, non è possibile aggiungere annotazioni. Ma anche se potessi in qualche modo aggiungere annotazioni alle interfacce di destinazione, affinché le annotazioni funzionassero dovresti incorporare un livello intermedio tra il tuo codice e le interfacce di destinazione, che intercetta le chiamate, esamina le annotazioni dei metodi di destinazione ed esegue il conversioni necessarie. Potresti, forse, usare Spring Framework o qualcosa del genere come il meccanismo Castle Interceptor per incorporare magicamente questo livello intermedio tra il tuo codice e le librerie, ma mi sembra che potresti facilmente scrivere il livello intermedio in modo tradizionale, avere una conoscenza approfondita delle interfacce di destinazione, eseguire le conversioni in modo semplice e diretto e anche astrarre le interfacce delle librerie in base alle tue esigenze.

    
risposta data 17.09.2015 - 11:44
fonte
0

Prima di tutto, tu (o il tuo team) dovete concordare un formato "standard" che userete nel vostro codice. Ad esempio:

  • Codifica: UTF-8
  • Locale: en_UK
  • Fuso orario: UTC

Solo dopo, potresti scrivere un livello che adatterà i valori ai formati richiesti dalle tue dipendenze (non penso che sia ingombrante).

Come ha detto Mike Nakis, anche io non vedo alcun vantaggio nell'usare annotazioni per risolvere questo problema.

    
risposta data 17.09.2015 - 13:01
fonte

Leggi altre domande sui tag