modello per condividere oggetti tra API e applicazione

7

Ho seri dubbi sul design della mia applicazione Web.

Volevo separare la logica di business dall'interfaccia, quindi ho creato un'API Web che gestisce tutte le richieste al database.

È un'API Web ASP.NET con framework Entity e un'unità di pattern di repository generico e di lavoro. Finora, tutto è buono.

PROBLEMA

Dove ho bisogno di aiuto non riesco a capire un modo efficace per condividere oggetti tra l'API e l'applicazione.

Non voglio serializzare direttamente l'oggetto entità, ho pensato che sarebbe una cattiva pratica, perché se il modello dell'entità cambia, potrei finire con la serializzazione di oggetti di grandi dimensioni senza motivo.

Come è implementato ora

Poiché la mia interfaccia è l'applicazione Web ASP.NET in C # e la mia API è in C #, ho creato una libreria comune con la definizione di tutte le mie classi che voglio condividere tra loro.

So che la soluzione non funzionerà quando svilupperò un'app per Android, dovrò creare nuovamente le mie classi in Java ma non è il mio problema più grande.

Il problema è che mi sento come se stessi sempre convertendo i miei oggetti.

Esempio

Ecco un esempio del mio flusso di lavoro:

Comincio con un modello con tutti gli oggetti e le annotazioni dei dati per il mio modulo, quindi l'utente POSIZERÀ quel modello a un controller.

Nel controller devo convertire questo modello in una classe nella mia libreria comune, quindi inviare quell'oggetto alla mia API.

Quindi un controller nella mia API intercetta la chiamata e converte tale oggetto in un oggetto entità per aggiornare il database.

Quindi ho 3 classi

  1. Il modello per la vista con tutte le annotazioni di dati per la convalida (Client)
  2. Le classi di libreria comuni per condividere gli oggetti (DLL)
  3. Le classi di entità (API)

Ho la sensazione di fare qualcosa di veramente sbagliato. C'è qualcosa di più elegante? Vorrei assicurarmi di avere una buona soluzione per questo problema prima che il progetto diventi troppo grande.

    
posta Marc 15.05.2014 - 16:12
fonte

1 risposta

11

So che può sembrare che tu stia convertendo oggetti avanti e indietro tutto il tempo tra gli oggetti del tuo database, gli oggetti di trasferimento dati, gli oggetti client con logica di convalida e così via, ma direi che no, non lo sei fare qualcosa di sbagliato.

Ognuno di questi oggetti può rappresentare la stessa unità di informazioni, ma hanno responsabilità molto diverse. L'oggetto del database è l'interfaccia di comunicazione con il database e deve essere conservato nel livello del database poiché potrebbe o meno avere annotazioni di metadati del database differenti e / o dettagli non necessari sull'implementazione del database al suo interno.

Il tuo oggetto di trasferimento dati è l'interfaccia di comunicazione con i tuoi utenti API. Questi dovrebbero essere il più puliti possibile per facilitare il consumo da diverse lingue / piattaforme. Ciò potrebbe imporre alcune restrizioni su come questi si comportano e si comportano in base ai consumatori di API che desideri supportare.

Gli oggetti client con logica di convalida non fanno realmente parte del tuo progetto API, fanno parte del tuo progetto consumer. Questi non possono essere gli stessi oggetti di trasferimento dati in questo caso poiché si aggiungono ulteriori logica specifica del client (in questo caso attributi di convalida) su di essi di cui il server non sa nulla (e non dovrebbe sapere nulla!) Non si dovrebbe conta questi oggetti come parte della tua API, perché in realtà non lo sono. Sono altamente specifici per le applicazioni consumer e alcune applicazioni che consumano la tua API potrebbero addirittura non aver bisogno di creare questi oggetti e potrebbero sopravvivere anche solo sugli oggetti di trasferimento dati. Ad esempio, se non avessi bisogno di convalida, non avresti bisogno di un ulteriore livello di oggetti completamente identici agli oggetti di trasferimento dati. In generale, la mia strategia qui è quella di evolvere il progetto per fasi, cominciando a utilizzare chiaramente gli oggetti di trasferimento dei dati come oggetti delle mie applicazioni consumer e quando vedo la necessità di una gestione specifica dei dati dell'applicazione (convalida, implementazione di INotifyPropertyChanged, ecc.) I fai un rapido refactoring e aggiungi il nuovo livello, se necessario.

Per me, sembra che ognuno dei tre tipi di oggetti si adatti molto bene a una singola responsabilità, che è un codice pulito e una buona pratica. Purtroppo, il codice pulito e le buone pratiche a volte significano che stai scrivendo un sacco di codice extra e saltando attraverso i cerchi extra "solo perché". E mentre stai programmando, potrebbe essere difficile apprezzare il valore che questo ti sta dando - ma non appena rilasci la tua applicazione e inizi a supportarla o aggiungi nuove funzionalità per la prossima versione, probabilmente inizierai ad apprezzare che ti sei preso il tempo per separare correttamente queste preoccupazioni in primo luogo. (Per non parlare del fatto che eviterai certi problemi che potrebbero verificarsi a causa di una separazione non corretta delle preoccupazioni - e dal momento che hai evitato questi problemi, potrebbe essere difficile apprezzare il disordine in cui ti trovi quando non hai separato le tue preoccupazioni. )

Odio anche scrivere codice di conversione tra diversi tipi di oggetti come questo, ma la mia soluzione è solitamente una delle seguenti:

  • Utilizza una libreria che fa in modo che la maggior parte della conversione degli oggetti sia pesante per te - ad esempio, se usi C # puoi usare la fantastica libreria AutoMapper ( link ). Credo che ci siano un paio di altre librerie come questa, ma AutoMapper è il più potente che abbia mai visto finora.
  • Se non riesci a trovare una libreria che ti aiuti con le conversioni degli oggetti, scrivi una serie di metodi di utilità per la conversione tra di essi. Questo potrebbe far schifo, ma ne vale la pena a lungo termine, scrivi il metodo di conversione la prima volta che devi convertire qualcosa - non aspettare.
risposta data 16.05.2014 - 15:21
fonte

Leggi altre domande sui tag