Quanta logica aziendale dovrebbe implementare il database?


107

Ho lavorato in alcuni progetti in cui la maggior parte della logica aziendale è stata implementata nel database (principalmente attraverso procedure memorizzate). Dall'altro lato, ho sentito da alcuni colleghi programmatori che questa è una cattiva pratica ("I database sono lì per archiviare i dati. Le applicazioni sono lì per fare il resto").

Quale di questi approcci è generalmente migliore?

I vantaggi dell'implementazione della logica di business nel DB che mi viene in mente sono:

  • Centralizzazione della logica aziendale;
  • Indipendenza del tipo di applicazione, linguaggio di programmazione, SO, ecc .;
  • I database sono meno inclini alla migrazione tecnologica o ai grandi refactoring (AFAIK);
  • Nessuna rilavorazione sulla migrazione della tecnologia delle applicazioni (ad es. .NET a Java, Perl a Python, ecc.).

I contro:

  • SQL è meno produttivo e più complesso per la programmazione della logica di business, a causa della mancanza di librerie e costrutti di linguaggio offerti dai linguaggi più orientati all'applicazione;
  • Riutilizzo del codice più difficile (se possibile) attraverso le librerie;
  • IDE meno produttivi.

Nota: i database di cui sto parlando sono database relazionali e popolari come SQL Server, Oracle, MySql ecc.

Grazie!


3
Potresti trovare utile la risposta a questa domanda .
Blrfl,

7
Questo argomento è già stato ampiamente discusso . Cos'altro potremmo aggiungere significativamente alla conversazione qui?
Robert Harvey,

2
@gnat: nemmeno vicino.
Robert Harvey,


7
Considera che il database sopravviverà di gran lunga ( molto ) alla tua applicazione. Il database potrebbe anche sopravvivono la lingua si scrive l'applicazione in. Il dato in sé di solito è il business, e il database deve essere in grado di proteggere l'integrità dei dati in esso contenuti. In tale ottica, ogni vincolo di chiave esterna è, francamente, l'implementazione di una regola aziendale. A meno che non ci si sbarazzi di tutti i vincoli relazionali nel proprio database relazionale, non è davvero possibile estrarre completamente la logica aziendale dal database.
Craig,

Risposte:


82

La logica aziendale non va nel database

Se parliamo di applicazioni multilivello, sembra abbastanza chiaro che la logica di business, il tipo di intelligenza che gestisce una determinata impresa, appartiene al livello di logica aziendale, non al livello di accesso ai dati.

I database fanno alcune cose davvero bene:

  1. Memorizzano e recuperano i dati
  2. Stabiliscono e applicano relazioni tra entità dati diverse
  3. Forniscono i mezzi per interrogare i dati per le risposte
  4. Forniscono ottimizzazioni delle prestazioni.
  5. Forniscono il controllo di accesso

Ora, naturalmente, è possibile codificare in un database tutti i tipi di cose relative alle preoccupazioni della propria azienda, ad esempio aliquote fiscali, sconti, codici operativi, categorie e così via. Ma l' azione aziendale che viene intrapresa su tali dati non è generalmente codificata nel database, per tutti i tipi di motivi già citati da altri, sebbene un'azione possa essere scelta nel database ed eseguita altrove.

E, naturalmente, potrebbero esserci delle cose che vengono eseguite in un database per prestazioni e altri motivi:

  1. Chiusura di un periodo contabile
  2. Scricchiolio dei numeri
  3. Processi batch notturni
  4. Fail-over

Naturalmente, nulla è inciso nella pietra. Le Stored procedure sono adatte per una vasta gamma di attività semplicemente perché vivono sul server di database e presentano alcuni punti di forza e vantaggi.

Stored procedure ovunque

C'è un certo fascino nel codificare tutte le attività di archiviazione, gestione e recupero dei dati nelle procedure memorizzate e nel semplice utilizzo dei servizi dati risultanti. Sicuramente trarrai vantaggio dalle massime prestazioni possibili e dalle ottimizzazioni di sicurezza che il server di database potrebbe fornire, e non è poco.

Ma cosa rischi?

  1. Blocco del fornitore
  2. La necessità di sviluppatori con set di abilità speciali
  3. Strumenti di programmazione spartana, nel complesso
  4. Accoppiamento software estremamente stretto
  5. Nessuna separazione delle preoccupazioni

E, naturalmente, se hai bisogno di un servizio web (che probabilmente è tutto qui, comunque), dovrai comunque costruirlo.

Quindi qual è la pratica tipica?

Direi che un approccio moderno e tipico consiste nell'utilizzare un Mappatore relazionale oggetti (come Entity Framework) per creare classi che modellano le tue tabelle. È quindi possibile parlare al database tramite un repository che restituisce raccolte di oggetti, una situazione molto familiare a qualsiasi sviluppatore di software competente. L'ORM genera dinamicamente SQL corrispondente al modello di dati e alle informazioni richieste, che il server di database elabora per restituire i risultati della query.

Quanto funziona bene? Molto bene e molto più rapidamente della scrittura di stored procedure e viste. In genere copre circa l'80% dei requisiti di accesso ai dati, principalmente CRUD. Cosa copre l'altro 20%? Hai indovinato: procedure memorizzate, che tutti i principali ORM supportano direttamente.

Puoi scrivere un generatore di codice che fa la stessa cosa di un ORM, ma con stored procedure? Certo che puoi. Ma gli ORM sono generalmente indipendenti dal fornitore, ben compresi da tutti e meglio supportati.


3
Grazie per l'ottima risposta, @Robert Harvey. Ma stavo pensando all'argomento "blocco del fornitore": non stai usando una particolare tecnologia (per esempio, lo stack .NET o Java) per creare un'applicazione anche un blocco del fornitore? O ci sono vantaggi di un lock-in di un fornitore di stack orientato all'app rispetto a un DB?
Raffaello,

3
@RobertHarvey, Ma la parte della logica dell'applicazione che è in .NET è ancora bloccata in .NET. Lo stesso vale per PHP e Java.
Pacerier,

2
@Pacerier: per blocco del fornitore, mi riferisco al fornitore del database. Nella pratica, il database (e lo stack di programmazione) vengono sostituiti raramente.
Robert Harvey,

2
@kai: Beh, non puoi averlo in entrambi i modi. O usi stub e beffe e vivi con il fatto che il test è artificiale, oppure scrivi un test realistico e vivi con un po 'di ritardo. Dubito però che il tuo compromesso sia di 10 minuti contro 30 secondi.
Robert Harvey,

3
Forse in ritardo, ma sono dell'opinione che le procedure memorizzate che implementano la logica aziendale appartengano al livello della logica aziendale, non al livello dati. Sono una specie di lang separato senza necessità di ORM.
Paralife,

16

Sono fermamente convinto a mantenere la logica di business fuori dal database il più possibile. Tuttavia, come sviluppatore di prestazioni della mia azienda, apprezzo che a volte sia necessario ottenere buone prestazioni. Ma penso che sia necessario molto meno spesso di quanto sostengano le persone.

Contesto i tuoi pro e contro.

Sostieni che centralizza la tua logica aziendale. Al contrario, penso che lo decentralizzi. In un prodotto su cui lavoro attualmente, utilizziamo la procedura memorizzata per gran parte della nostra logica aziendale. Molti dei nostri problemi di prestazioni provengono da funzioni di chiamata ripetute. Per esempio

select <whatever>
from group g
where fn_invoker_has_access_to_group(g.group_id)

Il problema con questo approccio è che generalmente (ci possono essere casi in cui questo è falso) forza il database a eseguire la funzione N volte, una volta per riga. A volte questa funzione è costosa. Alcuni database supportano gli indici delle funzioni. Ma non puoi indicizzare ogni possibile funzione rispetto a ogni possibile input. O puoi?

Una soluzione comune al problema sopra è estrarre la logica dalla funzione e unirla nella query. Ora hai incapsulato rotto e logica duplicata.

Un altro problema che vedo è la chiamata di stored procedure in un ciclo perché non è possibile unire o intersecare i set di risultati di proc memorizzati.

declare some_cursor
while some_cursor has rows
    exec some_other_proc
end

Se si estrae il codice dal proc annidato, si decentralizza nuovamente. Pertanto, sei costretto a scegliere tra incapsulamento e prestazioni.

In generale, trovo che i database non funzionino su:

  1. Calcolo
  2. Iterazione (sono ottimizzati per le operazioni impostate)
  3. Bilancio del carico
  4. parsing

I database sono bravi a:

  1. Blocco e sblocco
  2. Mantenimento dei dati e delle loro relazioni
  3. Garantire l'integrità

Effettuando operazioni costose come loop e analisi delle stringhe e mantenendole nel livello app, è possibile ridimensionare orizzontalmente l'applicazione per ottenere prestazioni migliori. L'aggiunta di più server app dietro un bilanciamento del carico è in genere molto più economica della configurazione della replica del database.

Hai ragione, tuttavia, che separa la tua logica aziendale dal linguaggio di programmazione della tua applicazione, ma non vedo perché questo sia un vantaggio. Se hai un'app Java, allora hai un'app Java. La conversione di un sacco di codice Java in stored procedure non cambia il fatto che si dispone di un'app Java.

La mia preferenza è quella di mantenere il codice del database focalizzato sulla persistenza. Come si crea un nuovo widget? È necessario inserire in 3 tabelle e devono essere in una transazione. Questo appartiene a una procedura memorizzata.

La definizione di cosa si può fare per un widget e le regole aziendali per la ricerca di widget appartiene alla propria applicazione.


8
Nel server SQL solo gli sps scritti male devono essere chiamati in un ciclo, è possibile inviare insiemi di dati in un parametro ed eseguire un processo basato su insiemi.
HLGEM,

2
SQL Server genererà un piano di query non ottimale ogni volta che c'è una UDF in una clausola WHERE.
Jim G.

7
Sembra che il tuo problema di prestazioni non sia colpa della logica nel database vs app .. è solo mal scritto e progettato. Questo problema ti seguirà nello stesso mondo ORM. Gli ORM possono essere un vero mal di testa al di fuori delle operazioni CRUD. Se il tuo sistema è pieno di dati, segnala il tipo di sistema, fai attenzione.
sam yi,

Questo è vero. La maggior parte dei nostri problemi di prestazioni sono semplicemente dovuti a codice scritto male e architettura troppo complessa. Ma credo ancora che abbiamo inserito il tipo sbagliato di lavoro nei nostri database. La codifica il più possibile nel database ci ha portato a fare cose in cui un database non è bravo.
Brandon,

1
Questo esempio è persino un argomento per collocare parti fondamentali della logica biz nel DB: per evitare un approccio iterativo (cicli di codice o cursore anziché espressioni basate su set) come la peste. I programmatori tendono a trattare insiemi di oggetti in modo iterativo (loop, traverse), portando probabilmente a carichi inutili o al problema SELECT N + 1 di molti roundtrip a query singola. Utilizzando le espressioni SQL o basate sul linguaggio (ad esempio LINQ), saranno costretti a utilizzare un approccio basato su set, quando possibile.
Erik Hart,

10

Ho lavorato in 2 diverse aziende che avevano una visione diversa sull'argomento.

Il mio suggerimento personale sarebbe quello di utilizzare le Stored Procedure quando i tempi di esecuzione sono importanti (performance). Poiché le Stored procedure sono compilate, se si dispone di una logica complessa per eseguire query sui dati, è meglio conservarli nel database stesso. Inoltre, alla fine invierà i dati finali al tuo programma.

Altrimenti, penso che la logica di un programma dovrebbe essere sempre nel software stesso. Perché? Perché un programma deve essere testabile e non credo che ci sia un modo semplice per testare le procedure memorizzate. Non dimenticare, un programma che non è stato testato è un cattivo programma.

Quindi usa la Stored Procedure con cautela, quando è necessario.


3
Le procedure memorizzate sono testabili in unità. Vedi qui per alcune tecniche.
Robert Harvey,

4
afaik, un test unitario non usa mai database o file. Quindi tecnicamente, il "test unitario" di una procedura memorizzata non è test unitario e sarà lento come l'inferno. Una suite di unit test dovrebbe essere eseguita in pochi secondi (o forse minuti con un'applicazione molto grande) in qualsiasi momento durante lo sviluppo.
Jean-François Côté,

1
L'OP parlava di "logica aziendale" e la logica aziendale doveva essere testata in unità. Inserendolo in una procedura memorizzata, lo si mescola con la query del database che rallenta l'intero processo. Come ho detto, è possibile utilizzare la Stored Procedure (non è un crimine) ma sfocerà il confine tra la logica aziendale e il livello del database, il che è negativo. Usalo con cura :)
Jean-François Côté,

1
Se si creano il db e gli oggetti necessari, lo sp, il test e quindi lo si abbassa in seguito, si tratta di un test unitario. Verifica un'unità di lavoro.
Tony Hopkinson,

2
I miglioramenti delle prestazioni con il mito delle procedure memorizzate non sono stati ridimensionati?
JeffO,

9

C'è una via di mezzo che devi trovare. Ho visto progetti spaventosi in cui i programmatori usano il database come nient'altro che un archivio di valori / chiavi troppo costoso. Ho visto altri in cui i programmatori non riescono a usare chiavi e indici esterni. Dall'altra parte dello spettro, ho visto progetti in cui la maggior parte, se non tutta, della logica aziendale è implementata nel codice del database.

Come hai notato, T-SQL (o il suo equivalente in altri RDBMS popolari) non è esattamente il posto migliore per codificare logiche aziendali complesse.

Cerco di costruire un modello di dati ragionevolmente decente, utilizzare le funzionalità del database per proteggere le mie ipotesi su quel modello (ad esempio, FK e vincoli) e usare il codice del database con parsimonia. Il codice del database è utile quando hai bisogno di qualcosa (cioè una somma) che il database è molto bravo a fare e può risparmiarti dallo spostare un milione di record sul filo quando non ne hai bisogno.


2
L'uso del database come archivio di chiavi / valori "troppo costoso" è una tecnica perfettamente valida, come attestano le legioni di professionisti NoSQL.
Robert Harvey,

1
@RobertHarvey Hai ovviamente ragione, ma in qualche modo il mio istinto continua a insistere sul fatto che ci deve essere una soluzione più semplice / economica / più veloce di un database se tutto ciò di cui hai bisogno è un archivio chiave / valore. Devo saperne di più su NoSQL.
Dan Pichelman,

2
Non vedo l'uso di stored procedure come cura per un database mal progettato.
JeffO,

2
@RobertHarvey, ho letto letteralmente "archivio chiave / valore troppo caro". Abbinare una licenza Oracle o SQL Server per qualcosa del genere, quando ci sono opzioni come MongoDB disponibili gratuitamente, sembra sprecare soldi.
Raffaello,

@Raphael O potresti usare PostgreSQL 😉
Demi

9

Se la tua logica aziendale prevede operazioni di set, molto probabilmente un buon posto è nel database perché i sistemi di database sono davvero bravi a eseguire operazioni di set.

http://en.wikipedia.org/wiki/Set_operations_(SQL)

Se la logica aziendale implica una sorta di calcolo, probabilmente appartiene al di fuori della procedura di database / archivio poiché i database non sono realmente progettati per il ciclo e il calcolo.

Sebbene queste non siano regole rigide e veloci, è un buon punto di partenza.


6

Non esiste una risposta corretta a questo. Dipende da cosa si utilizza il database. In un'applicazione enterprise, è necessaria la logica nel database tramite chiavi esterne, vincoli, trigger, ecc. Perché è l'unico posto in cui tutte le possibili applicazioni condividono il codice. Inoltre, inserire la logica richiesta nel codice significa generalmente che il database è incoerente e che i dati sono di scarsa qualità. Ciò può sembrare banale per uno sviluppatore di applicazioni che è solo d'accordo con il funzionamento della GUI, ma ti assicuro che le persone che cercano di utilizzare i dati nei report di conformità lo trovano molto fastidioso e costoso quando ricevono multe da miliardi di dollari per avere dati che non hanno seguire le regole correttamente.

In un ambiente non normativo quando non ti interessa tanto l'intero set di record e solo una o due applicazioni colpiscono il database, forse puoi cavartela mantenendo tutto nell'applicazione.


3

Dopo qualche anno, la domanda è ancora importante ...

Semplice regola empirica per me: se si tratta di un vincolo logico o di un'espressione onnipresente (singola istruzione), inseriscilo nel database (sì, anche le chiavi esterne e i vincoli di controllo sono una logica aziendale!). Se è procedurale, contenendo loop e rami condizionali (e davvero non può essere modificato in un'espressione), inseriscilo in codice.

Evitare i DB di dump del cestino

I tentativi di inserire davvero tutta la logica aziendale nel codice dell'applicazione probabilmente degenereranno il database (relazionale) in una discarica, in cui la progettazione relazionale deve essere quasi completamente omessa, dove i dati possono avere uno stato incoerente e manca la normalizzazione (spesso principalmente XML, JSON , CSV ecc. Colonne cestino).

Questo tipo di logica solo per l'applicazione è probabilmente uno dei motivi principali per l'ascesa di NoSQL - ovviamente con il rovescio della medaglia che l'applicazione deve occuparsi di tutta la logica stessa, ciò che è stato incorporato nel database relazionale per decenni. Tuttavia, i database NoSQL sono più adatti a questo tipo di gestione dei dati, ad esempio i documenti di dati mantengono in sé implicita "integrità relazionale". Per i DB relazionali, è semplicemente un abuso, che causa sempre più problemi.

Espressioni (basate su set) anziché codice procedurale

Nel migliore dei casi, ogni query o operazione di dati dovrebbe essere codificata come espressione, piuttosto che come codice procedurale. Un ottimo supporto per questo è quando i linguaggi di programmazione supportano espressioni, come LINQ nel mondo .NET (sfortunatamente, al momento solo query, nessuna manipolazione). Dal punto di vista del DB relazionale, è stato insegnato per molto tempo a preferire espressioni di istruzioni SQL rispetto ai loop procedurali del cursore. In questo modo il DB può ottimizzare, eseguire l'operazione in parallelo o qualunque cosa possa essere utile.

Utilizzare meccanismi di integrità dei dati DB

Quando si tratta di RDBMS con vincoli di chiave esterna e verifica, colonne calcolate, possibilmente trigger e viste, questo è il posto in cui archiviare la logica aziendale di base nel database. Una corretta normalizzazione aiuta a mantenere l'integrità dei dati, a garantire un'istanza univoca e distinta dei dati. Anche se devi duplicarlo in codice e DB, questi meccanismi di base per l'integrità dei dati non dovrebbero essere omessi!

Procedura di archiviazione?

Oggigiorno le procedure memorizzate sono raramente necessarie, poiché i database mantengono i piani di esecuzione compilati per SQL e li riutilizzano quando viene ripetuta la stessa query, solo con parametri diversi. Quindi l'argomento precompilato per SP non è più valido. È possibile archiviare o generare automaticamente query SQL nell'applicazione o ORM, che troveranno piani di query precompilati per la maggior parte del tempo. SQL è un linguaggio di espressioni, purché non si utilizzino esplicitamente elementi procedurali. Quindi, nel migliore dei casi, usi espressioni di codice che possono essere tradotte in SQL.

Mentre il lato dell'applicazione, incluso SQL generato da ORM, non è più all'interno del database, a differenza delle Stored Procedure, lo considero ancora come codice del database. Perché richiede ancora conoscenza di SQL e database (tranne il CRUD più semplice) e, se applicato correttamente, funziona in modo molto diverso dal codice procedurale normalmente creato con linguaggi di programmazione come C # o Java.


2

Dipende davvero dall'azienda, dalla sua cultura e dal suo retaggio. Considerazioni tecniche a parte (queste sono state trattate da entrambe le parti), le risposte fornite ti dicono che dipende da dove provengono le persone. In alcune organizzazioni, i dati sono il re e il DBA è una figura potente. Questo è il tipico ambiente centralizzato, un data center con un gruppo di terminali collegati. La preferenza in questo tipo di ambiente è chiara. Il desktop potrebbe cambiare radicalmente molte volte prima che qualcosa cambi nel data center e ci sarà poco nel mezzo.

L'altra estremità dello spettro è la pura architettura a 3 livelli. O forse a più livelli in un'azienda orientata al web. Probabilmente sentirai qui una storia diversa. Il DBA, se presente, sarà solo un assistente che esegue alcune attività amministrative.

Uno sviluppatore di applicazioni dei tempi moderni avrà più affinità con il secondo modello. Se sei cresciuto con un grande sistema client-server, probabilmente ti troverai nell'altro campo.

Ci sono spesso molti fattori non tecnici legati all'ambiente coinvolti qui, non esiste una risposta generale a questa domanda.


2

Il termine logica aziendale è aperto all'interpretazione. Quando si creano sistemi, vogliamo garantire l'integrità del database e dei suoi contenuti. Come primo passo dovrebbero essere presenti diverse concessioni di accesso per gli utenti. A titolo di esempio molto semplice, consideriamo un'applicazione ATM.

Per ottenere il saldo del conto, fare una selezione su una vista appropriata dovrebbe andare bene. Ma per trasferire fondi, si desidera che la transazione sia incapsulata da una procedura memorizzata. La logica aziendale non dovrebbe essere autorizzata ad aggiornare direttamente le tabelle per gli importi di credito e debito.

In questo esempio, la logica aziendale potrebbe controllare il saldo prima di richiedere il trasferimento o semplicemente invocare il proc memorizzato per il trasferimento e segnalare l'errore. IMHO, la logica di business, in questo esempio, dovrebbe verificare preventivamente che siano disponibili fondi sufficienti e che esista l'account di destinazione e solo successivamente invocare i fondi di trasferimento. Se si verifica un altro addebito tra i passaggi iniziali e la chiamata al proc memorizzata, solo allora verrà restituito un errore.


Bel esempio e spiegazione.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.