Organizza le classi C ++ attorno al database SQL

5

La mia domanda riguarda il modo migliore per organizzare le classi C ++ attorno a un database modello, e capisco che questo possa sembrare molto elementare.

Il software che propongo di creare farà quanto segue. È inteso per piccoli produttori di FMCG e useranno Qt.

  • Il software registra i reclami relativi a prodotti non conformi, azioni correttive e servono come tenuta di registri elettronici
  • Ci sarà un bel po 'di logica di business, come lo standout La funzione è intesa come reportistica completa, ricerca e analisi, così come un approccio flessibile per l'inserimento di dati per lisciare flussi di lavoro (vale a dire una pausa dal "uno schermo per fase del processo" paradigma)
  • L'archivio persistente è un database SQL, con una tabella (s) per ciascuno tipo di record (alcuni record verranno suddivisi in tabelle separate per Indagini / soluzioni. Ciò significa che la maggior parte del lavoro verrà eseguita su a riga singola).
  • Ogni cliente che utilizza questo software richiederà modifiche, colonne / campi aggiuntivi o modifiche nei nomi delle colonne e forse logica di business. Ogni cliente può richiedere aggiornamenti che cambiano il struttura del database. L'idea è che tutto ciò che può essere personalizzato, qualsiasi i requisiti specifici del cliente vivranno all'interno di queste classi.
  • Ci saranno segnalazioni, che riguardano principalmente la raccolta di record corrispondenti categorie particolari, ricerche di parole, ecc.

Ho lo schema del database fatto e preparato, e la logica di come le tabelle riferirsi è chiaro. Ho usato questo schema in un altro framework, ma un'applicazione web non sembra offrire il livello di potenza per l'utente per quanto riguarda la GUI, che è essenziale per differenziare questo prodotto dagli altri.

La mia domanda è come progettare le classi attorno al database. È importante ottenere questo giusto, in modo che l'architettura del software non deve essere riprogettato in seguito. Le classi non saranno responsabili per il persistente negozio, solo per agire come intermediario tra il livello responsabile l'archivio persistente e i controller / viste.

L'approccio più logico sembra essere quello di avere una classe per non conformità / reclami ecc., che memorizza solo l'istanza (cioè un oggetto per record di non conformità), convalida i dati e la logica di business specifica della classe (es. ). Una classe per tabella sembra logica in questo caso. Quello con cui sto combattendo è se sia una pratica standard avere semplicemente membri di dati per ogni colonna, definire getter e setter, o se dovrei creare una classe che non è codificata per mappare una tabella, ma che popola una mappa basata sullo schema del database o sul file esterno che definisce le proprietà del database e della colonna. Il primo significa che la codifica per la classe deve essere modificata quando le colonne vengono modificate, il secondo potenzialmente no. Tieni presente che, per la maggior parte del tempo, ogni utente lavorerà con un record alla volta.

In breve, posso vedere un esempio di come eseguire query SQL, ma ho faticato trova tutto ciò che mi mostra come dovrebbe apparire la classe (o se l'intero approccio è sbagliato) e mi piacerebbe confrontare quello che sto facendo, con quello che l'industria definirebbe una buona pratica (non sono un programmatore di commercio).

Grazie,

    
posta Borax Man 26.09.2014 - 13:56
fonte

4 risposte

1

La prima domanda è se stai bene con la necessità di ricompilare il programma ogni volta che lo schema del database cambia. Non sono abbastanza chiaro sulla tua situazione, ma ad esempio:

Hai un numero di client con esigenze leggermente diverse (ad esempio, A ha bisogno di tenere traccia delle proprietà X, Y, Z, ma B deve anche tracciare la proprietà W) ma per un determinato cliente quelle esigenze sono piuttosto costanti. E puoi lavorare con e distribuire un'applicazione personalizzata per ogni cliente (anche se non lo stai vendendo da solo). In tal caso, avere un modello che è possibile ereditare e modificare in base al cliente potrebbe essere una buona strategia di business, se il numero totale di client non è abbastanza alto da far sì che valga la pena creare un'applicazione altamente adattabile direttamente dal inizio. Avere 5 diverse versioni del programma è ancora mantenibile, 100 non lo è.

D'altra parte, se hai 100 clienti, non puoi semplicemente cambiare il codice ogni volta che uno di loro vuole aggiungere una proprietà (colonna) a qualcosa. O anche aggiungere un nuovo tipo di oggetto. Quindi il programma dovrà essere più dinamico, probabilmente lavorando su una mappa relazionale che viene salvata da qualche parte e che può essere modificata dal programma secondo necessità.

Quindi supponiamo che quello che hai sia più simile al precedente. Avere classi che rappresentano i tipi di record che hai è un buon modo per farlo. Queste classi possono contenere direttamente query SQL. Tuttavia dovresti comunque avere cose come i nomi di tabelle come costanti definite in un file .h comune e quindi chiamarle come costanti nel tuo codice effettivo in modo che ogni cambiamento debba essere fatto in un solo posto. Quindi se hai bisogno di un oggetto leggermente diverso per un client diverso, puoi ereditare le classi che hai già e apportare le modifiche necessarie.

Potresti anche mettere insieme una classe intermedia che gestisce le interazioni di database effettive, quindi se cambi lo schema o anche il tipo di database che stai usando, devi solo cambiare o modificare quella classe.

    
risposta data 26.09.2014 - 16:02
fonte
1

Raccomando di avere una classe per tabella e un campo per colonna. Questo pattern è ampiamente utilizzato da Object Relational Mappers (ORM) in molte lingue, e funziona molto bene. Queste classi formano il tuo modello di dominio. Un problema, come altri hanno notato, è che se si desidera modificare lo schema dei dati, è necessario modificare il codice dell'applicazione. Se questo è un problema per te, potresti prendere in considerazione dati semi-strutturati (ad esempio, colonne JSON o anche NoSQL).

Puoi mettere un po 'di logica nelle tue classi di dati, ma tendo a mantenerlo abbastanza leggero. E i metodi su una classe di dati dovrebbero funzionare solo su quella classe. Per una logica di business più coinvolta e qualsiasi cosa che coinvolga più di una classe, crea un livello di servizio. Il livello di servizio offre un'API per il resto dell'applicazione e dipende dal modello.

A proposito, è abbastanza inusuale scrivere questo tipo di software in C ++. Solitamente i linguaggi di livello superiore (C #, Java, Python, ecc.) Sono più adatti.

    
risposta data 25.11.2014 - 21:02
fonte
0

In primo luogo, per me il modo più naturale di approcciare progetti come questo è la prima progettazione del modello di dominio e solo dopo la progettazione di come quel modello è implementato nel linguaggio di programmazione selezionato o di come è memorizzato in un database relazionale.

In secondo luogo, poiché ogni cliente richiede modifiche, colonne aggiuntive e nomi di colonne personalizzati, dimenticherei l'idea di memorizzare ogni record su una singola riga e utilizzare invece valore di attributo di entità (EAV) model o anche considerare l'uso di un database orientato al documento invece di uno relazionale. Va notato tuttavia che alcune persone considerano il modello EAV come un anti-pattern perché causerà alcune complessità aggiuntive.

Infine, suppongo che tutti i record abbiano ancora un sottoinsieme condiviso di attributi principali uguali per tutti i clienti. Per me l'approccio più pulito sarebbe quello di separare completamente questa parte fondamentale da estensioni specifiche del cliente. Gli attributi principali che manterrei come membri dei dati nelle classi C ++ per facilità d'uso e progettano un meccanismo separato per le estensioni. Inoltre, se decidi di utilizzare qualcosa come Mi piace del modello EAV, manterrei comunque questi attributi principali in colonne dedicate invece di suddividerli nelle loro righe.

    
risposta data 26.10.2014 - 17:58
fonte
0

L'errore comune che molte persone fanno con la mappatura del database è che si concentrano sullo schema e sviluppano una rappresentazione strettamente accoppiata delle tabelle nelle classi di business logic. Questo non è il modo migliore - ovviamente rende il livello della business logic così strettamente collegato al DB da rendersi rapidamente conto di un errore e finisce per aggiungere un altro livello per cercare di separare la logica di business da DB, chiamandolo DAO o ORM o simili.

Quello che dovresti fare è guardare il tuo DB come un livello in sé, uno che fornisce un'API in cui vengono fatte le richieste di dati. Trovo il modo più semplice per concettualizzare ciò scrivendo tutto il tuo SQL come stored procedure e limitando tutto l'accesso alle tabelle sottostanti. (questo approccio ha anche il vantaggio di aumentare la sicurezza)

Una volta fatto questo, inizi a guardare i dati come una risorsa da consumare, la logica di business avrà classi scritte che mappano alle stored procedure e lavorano insieme - la logica nelle classi di business logic con i dati che sono operato su sourced dalla tua "API di dati". Significa anche che è possibile modificare lo schema senza alcuna modifica al livello della logica di business (sebbene, ovviamente, se si modifica l'API di processo memorizzata utilizzata, sarà necessario cambiare i chiamanti, ma è possibile aggiungere nuovi sproc dove necessario senza alcun impatto sul codice esistente).

Un altro vantaggio è che il DB e la logica aziendale sono quindi indipendenti e possono essere elaborati separatamente. l'utilizzo dell'API DB non sarebbe molto diverso dall'utilizzo di un'API di terze parti fornita tramite un servizio Web o altra origine dati.

    
risposta data 26.11.2014 - 10:21
fonte

Leggi altre domande sui tag