Progettazione di un CMS. Quando utilizzare le interfacce correttamente e dipendenze e livelli

0

Sto costruendo un CMS e ho bisogno di una guida su come strutturare l'applicazione. Semplicemente non capisco quando dovrei usare le interfacce o una classe astratta.

Il sistema in fase di sviluppo utilizza .Net Core e EF core I pianifica di consentire a MySQL e SQL Server come origine dati. Voglio anche un approccio modulare in cui posso aggiungere elementi su base retribuita come ad esempio e-commerce e modulo di pagamento.

Il design dei livelli correnti è elencato sotto

Database - Contiene dipendenza di terze parti in EF Core

Contiene tutte le BusinessEntities con più classi, ma due interfacce una è IGenericProperties (che ha proprietà condivise tra le classi, ad esempio IsDeleted) e IPrimaryKey, molte entità implementano queste interfacce.

Inoltre contiene DataAccessLayer e un'interfaccia IGenericMethods che ha più metodi come Aggiungi, Eliminato, Recupera ecc. che la classe GenericObject implementa. Tutte le altre classi DAL ereditano GenericObject

Infine, anche l'EF DatabaseContext è specificato in questo livello.

quadro

Questo ha contenuto di framework come i metodi di estensione, la ricerca e cose non relative a db.

Sicurezza

Questo ha le identità di ASP.NET come UsersStore, Ruoli ecc.

Infine ho i livelli MVC e Test.

I controller nei livelli MVC possono quindi eseguire operazioni CRUD come questa

    CategoriesDAL categoryObject = new CategoriesDAL();
    IList<Category> getAll = categoryObject.RetrieveAll().ToList();

Tuttavia, dopo aver letto di più su Dependency Injection e layering (leggendo Adaptive Code: Agile coding con schemi di progettazione e principi SOLID (Developer Best Practices, Gary McLean)) , mi chiedo se l'approccio I sto scendendo è utilizzabile o se avessi problemi in futuro. Un paio di cose che posso individuare è come potrei rendere questo modulare come aggiungere moduli di e-commerce come dovrei fare riferimento a EF.

Ho esaminato esempi di codice sorgente su github di altri CMS / Framework Umbraco, MrCMS, Orachard, Piranah. Questi sistemi hanno un sacco di livelli e interfacce e sto semplicemente cercando di capirlo.

Quindi riassumi la mia domanda.

Quando e perché dovrei usare le interfacce / classe astratta?

Come posso rendere la mia attuale applicazione più modulare? (come avere moduli di e-commerce)

Grazie

    
posta 09.09.2017 - 21:45
fonte

3 risposte

1

Semplicemente non capisco quando dovrei usare le interfacce o una classe astratta.

Il modo migliore per comprendere la differenza è il seguente:

  • Le interfacce hanno una funzione di relazione
  • Le sottoclassi hanno una una relazione

In pratica, usi le interfacce quando hai una parte del codice che vuoi essere completamente libera di scambiare. Le interfacce funzionano bene quando il design si basa sulla composizione (unità completamente testate assemblate e funzionanti insieme).

Si useranno le classi base quando si desidera condividere un comportamento comune con tutte le sottoclassi. Poiché la relazione tra la classe base e la classe figlio è più intrecciata, è più difficile eseguire il test delle unità. Per essere onesti, il numero di volte in cui è necessario condividere il comportamento di base con tutte le classi figlie è un sottoinsieme relativamente piccolo.

Esempi di dove le interfacce funzionano bene

L'accesso al database è un luogo in cui in realtà desideri la possibilità di sostituire le implementazioni, anche se è solo per test. Un modello comune consiste nell'utilizzare un oggetto di accesso ai dati (DAO) per separare le chiamate al database dal resto della business logic. Se sei mai stato in una posizione in cui il reparto IT ha un cambiamento di politica e il fornitore di database che hai utilizzato costa troppo, questo aiuta a minimizzare l'impatto sul resto del tuo sistema. Hai la libertà di gestire diversi backend di database, integrare server di ricerca (come ElasticSearch o Solr), ecc. Senza rompere il funzionamento della tua applicazione.

Accesso alla rete è un altro posto in cui desideri essere in grado di scambiare le implementazioni. Un conto è se l'applicazione deve effettuare chiamate di rete ai servizi Web ospitati, ma è possibile testare l'interazione senza effettuare effettivamente una chiamata di rete. Inoltre, consente di adattarsi a diverse versioni di servizi Web o protocolli di rete più rapidamente.

Anche le sottoclassi sono utili

Trovo che la sottoclasse sia più utile nelle applicazioni desktop, in particolare quando ho bisogno di estendere i controlli forniti per fare qualcosa di specifico. Tuttavia, sono molto più difficili da testare, sia perché è un pezzo dell'interfaccia utente, sia a causa della sottoclasse.

Detto questo, puoi consolidare il codice della piastra della caldaia che potresti dover copiare tra diversi componenti. Non è una soluzione tutto o niente. Ad esempio, gli helper delle autorizzazioni possono funzionare bene come funzionalità di classe base.

Pensa attentamente se condividere un comportamento comune è la risposta giusta o se puoi semplicemente utilizzare un oggetto completamente autonomo per fornire la funzionalità.

    
risposta data 11.09.2017 - 22:38
fonte
0

> Semplicemente non capisco quando dovrei usare le interfacce o una classe astratta

Regole empiriche inadeguate ma certamente di buon punto di partenza:

1 - Inizia solo creando le classi secondo necessità.

2 - Alla fine, trovi 2+ classi che fanno la stessa cosa ma sono leggermente differenti a causa di alcuni dettagli di livello inferiore di cui l'utente della classe probabilmente non dovrebbe interessare. Devi decidere se l'interfaccia o la classe astratta sono migliori.

  • 2.a - Se le implementazioni delle classi 2+ sono identiche per la maggior parte dei metodi della classe, allora crea una classe base astratta.

  • 2.b - Altrimenti crea una classe di interfaccia.

FWIW - Questo è il modo quasi totalmente "tecnicamente" scorretto di utilizzare le classi di interfaccia, ma è il modo in cui almeno il 90% + degli sviluppatori utilizza le classi di interfaccia.

Il modo più corretto di usare le classi di interfaccia è creare interfacce basate sulla funzionalità piuttosto che sulle classi. Il problema con questo approccio è l'esplosione di classe e la dissonanza cognitiva che causa.

La maggior parte delle persone può gestire più facilmente funzionalità correlate alla classe raggruppate in interfacce perché hanno già identificato che le classi "dovrebbero" ereditare dalla stessa base. Tuttavia, con l'approccio "tecnicamente" corretto e il numero molto più ampio di interfacce tra cui scegliere, diventa più difficile trovare le "corrette" interfacce su cui basare la classe. Ho visto progetti che adottano l'approccio "tecnicamente corretto" che tende ad avere il problema dove spesso ci sono molte classi di interfacce quasi duplicate che esasperano ancora di più il problema dell'esplosione di classe.

Quindi IMO, nel mondo reale; "corretto" è negli occhi di chi guarda. Ora mi avvicino all'approccio "regole del pollice" descritto sopra con l'applicazione dell'approccio "tecnicamente" corretto quando "funziona" meglio per la situazione. Sottolineo l'approccio "tecnicamente corretto" perché ti farebbe un'ingiustizia per non renderti consapevole che nel mondo teorico le interfacce sono basate sulla funzionalità e le regole del pollice sopra sarebbero considerate sbagliate. E questo potrebbe essere quello che stai vedendo negli esempi che stai guardando. Scegli in quale mondo vuoi vivere e cerca di essere coerente. Una misticanza di entrambi gli approcci non funzionerà sicuramente troppo bene.

Mi sto chiedendo se l'approccio che sto seguendo sia utilizzabile o se avessi problemi in futuro.

L'approccio che stai seguendo, e non so nemmeno cosa sia, avrà sicuramente problemi in futuro.

A meno che tu non abbia costruito sistemi simili, ci sono poche possibilità di ottenerlo "giusto". Anche se hai costruito sistemi quasi identici, ti imbatterai in nuovi problemi che il tuo progetto non gestisce per il progetto specifico corrente.

Se la maggior parte dei tuoi moduli può essere sviluppata separatamente e indipendentemente l'una dall'altra, considera che questo sia un grande successo. Per ottenere ciò, è necessario fare un buon uso delle interfacce / classi astratte. Che risponde alla domanda "Perché dovresti usare le interfacce / classi astratte".

    
risposta data 11.09.2017 - 19:49
fonte
0

Se non riesci a vedere dove le interfacce ti aiuteranno, è probabile che tu non abbia bisogno di interfacce. Le interfacce non sono di per sé un segno di buona progettazione, piuttosto sono la soluzione per problemi specifici. Se non hai il problema, non hai bisogno della soluzione per questo!

Sospetto che tu stia soffrendo per "paralisi dell'analisi" perché le tue esigenze sono vaga. Per esempio. cosa significa "più modulare"? Definisci ciò che vuoi ottenere in termini concreti e quindi progetta il codice per renderlo possibile.

    
risposta data 11.09.2017 - 21:39
fonte

Leggi altre domande sui tag