Quanta logica di business dovrebbe implementare il database?

90

Ho lavorato in alcuni progetti in cui la maggior parte della logica aziendale è stata implementata nel database (principalmente attraverso stored procedure). 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 di implementare la logica di business nel DB che posso pensare sono:

  • Centralizzazione della logica aziendale;
  • Indipendenza dal tipo di applicazione, dal linguaggio di programmazione, dal sistema operativo, ecc.
  • I database sono meno inclini alla migrazione tecnologica o ai grandi refactor (AFAIK);
  • Nessuna rilavorazione sulla migrazione della tecnologia applicativa (ad es. da .NET a Java, da Perl a Python, ecc.)

Gli svantaggi:

  • SQL è meno produttivo e più complesso per la programmazione della business logic, a causa della mancanza di librerie e costrutti linguistici offerti dalla maggior parte dei linguaggi applicativi;
  • Più difficile (se possibile) riutilizzo del codice 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!

    
posta Raphael 09.04.2013 - 17:04
fonte

9 risposte

72

La logica aziendale non entra nel database

Se parliamo di applicazioni multilivello, sembra abbastanza chiaro che la logica aziendale, il tipo di intelligence che esegue una determinata azienda, appartiene al livello di logica aziendale, non nel livello di accesso ai dati.

I database fanno davvero un paio di cose:

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

Ora, naturalmente, puoi codificare tutti i tipi di cose in un database che riguardano le tue preoccupazioni aziendali, ad esempio aliquote fiscali, sconti, codici operativi, categorie e così via. Ma la azione commerciale che viene presa su quei dati non è generalmente codificata nel database, per tutti i tipi di ragioni già menzionate da altri, sebbene un'azione possa essere scelta nel database ed eseguito altrove.

E, naturalmente, ci possono essere cose che vengono eseguite in un database per prestazioni e altri motivi:

  1. Chiusura di un periodo contabile
  2. Numero di crunch
  3. Processi batch notturni
  4. Fail-over

Naturalmente, niente è inciso nella pietra. Le stored procedure sono adatte a un'ampia gamma di attività semplicemente perché vivono sul server di database e hanno determinati punti di forza e vantaggi.

Stored Procedure Ovunque

Esiste un certo fascino nel codificare tutte le attività di archiviazione, gestione e recupero dei dati nelle stored procedure e semplicemente nel consumare i servizi dati risultanti. Sicuramente trarrai vantaggio dalle massime prestazioni e ottimizzazioni di sicurezza che il server di database potrebbe fornire, e non è cosa da poco.

Ma cosa rischi?

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

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

Allora, qual è la pratica tipica?

Direi che un approccio tipico e moderno consiste nell'utilizzare un Object-Relational Mapper (come Entity Framework) per creare classi che modellano le tabelle. Puoi quindi parlare al tuo database attraverso un repository che restituisce collezioni di oggetti, una situazione che è molto familiare a qualsiasi sviluppatore di software competente. L'ORM genera dinamicamente SQL corrispondente al modello di dati e le informazioni richieste, che il server di database quindi elabora per restituire i risultati della query.

Quanto bene funziona? Molto bene, e molto più rapidamente rispetto alla scrittura di stored procedure e visualizzazioni. Questo in genere copre circa l'80% dei requisiti di accesso ai dati, principalmente CRUD. Cosa copre l'altro 20%? Avete indovinato: stored procedure, che tutte le 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.

    
risposta data 09.04.2013 - 17:55
fonte
15

Sono un strong sostenitore nel mantenere il business logic fuori dal database il più possibile. Tuttavia, in qualità di 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 affermano le persone.

Disputo i tuoi pro e contro.

Affermerai che centralizza la tua logica aziendale. Al contrario, penso che lo decentralizzi. In un prodotto al quale lavoro attualmente, usiamo stored procedure per molte delle nostre logiche di business. Molti dei nostri problemi di prestazioni provengono ripetutamente da funzioni di chiamata. Ad 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) costringe il database ad eseguire la funzione N volte, una volta per riga. A volte questa funzione è costosa. Alcuni database supportano indici di funzioni. Ma non puoi indicizzare ogni funzione possibile contro ogni possibile input. O puoi?

Una soluzione comune al problema precedente è estrarre la logica dalla funzione e unirla alla query. Ora hai interrotto l'incapsulamento e la logica duplicata.

Un altro problema che vedo è chiamare le stored procedure in un ciclo perché non c'è modo di unire o intersecare i set di risultati del proc memorizzato.

declare some_cursor
while some_cursor has rows
    exec some_other_proc
end

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

In generale, trovo che i database non funzionino correttamente:

  1. calcolo
  2. Iterazione (sono ottimizzati per le operazioni di set)
  3. Bilanciamento del carico
  4. Analisi

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 parsing di stringhe e mantenendole nel livello dell'app, è possibile ridimensionare orizzontalmente l'applicazione per ottenere prestazioni migliori. L'aggiunta di più server di app dietro un sistema di bilanciamento del carico è in genere molto più economica rispetto alla configurazione della replica del database.

Hai ragione, tuttavia, che disaccoppia la tua logica di business 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 gruppo di codice Java in stored procedure non cambia il fatto che tu disponga di un'app Java.

La mia preferenza è 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 stored procedure.

Definire cosa può essere fatto a un widget e le regole di business per la ricerca di widget appartengono all'applicazione.

    
risposta data 09.04.2013 - 18:00
fonte
10

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

Il mio suggerimento personale sarebbe quello di utilizzare stored procedure quando il tempo di esecuzione è importante (prestazioni). Poiché la stored procedure viene compilata, se si dispone di una logica complessa per interrogare i dati, è meglio conservarli sul database stesso. Inoltre, invierà solo i dati finali al tuo programma alla fine.

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

Quindi usa la stored procedure con cautela, quando è necessario.

    
risposta data 09.04.2013 - 17:20
fonte
9

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

Come hai notato, T-SQL (o il suo equivalente in altri popolari RDBMS) non è esattamente il posto migliore per codificare una complessa logica di business.

Cerco di creare 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 utilizzare 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 record di zillion sul filo quando non ne hai bisogno.

    
risposta data 09.04.2013 - 17:17
fonte
8

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

link

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

Anche se queste non sono regole dure e veloci, è un buon punto di partenza.

    
risposta data 09.04.2013 - 17:29
fonte
5

Non c'è una risposta giusta a questo. Dipende da cosa usi il database. In un'applicazione ENterprise è possibile eseguire il thelogin nel database tramite chiavi esterne, vincoli e trigger, ecc. Perché è l'unico posto in cui tutte le applicazioni possibili condividono il codice. Inoltre, inserire la logica richiesta nel codice generalmente significa che il database è incoerente e che i dati sono di scarsa qualità. Ciò può sembrare banale a un applicativo non compatibile con il funzionamento della GUI, ma vi assicuro che le persone che cercano di utilizzare i dati nei report di conformità 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 regolamentato quando non ti interessi tanto sull'intero set di record e solo una o due app su questo database, forse puoi farla franca mantenendo tutto nell'applicazione.

    
risposta data 09.04.2013 - 23:25
fonte
3

Dopo alcuni anni, la domanda è ancora importante ...

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

Evita i DB di scarico del cestino

I tentativi di collocare davvero tutta la logica aziendale nel codice dell'applicazione probabilmente degenereranno il database (relazionale) in un dump della spazzatura, dove la progettazione relazionale è per lo più completamente omessa, dove i dati possono avere uno stato incoerente e la normalizzazione è mancante (spesso XML, JSON, CSV ecc. Colonne trashbin).

Questo tipo di logica solo per applicazione è probabilmente una delle ragioni principali per l'aumento di NoSQL - ovviamente con lo svantaggio che l'applicazione deve prendersi cura di tutta la logica stessa, ciò che è stato incorporato nel DB relazionale per decenni . Tuttavia, i database NoSQL sono più adatti a questo tipo di gestione dei dati, ad esempio, i documenti di dati mantengono una "integrità relazionale" implicita all'interno di se stessi. Per i DB relazionali, è semplicemente un abuso, causando sempre più problemi.

Espressioni (basate su set) anziché codice procedurale

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

Utilizza i meccanismi di integrità dei dati DB

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

Procedure memorizzate?

Le stored procedure sono raramente necessarie al giorno d'oggi, dal momento che i database mantengono piani di esecuzione compilati per SQL e li riutilizzano quando viene restituita la stessa query, solo con parametri diversi. Quindi l'argomento di precompilazione per SP non è più valido. È possibile memorizzare o generare automaticamente query SQL nell'applicazione o nell'ORM, che troveranno per la maggior parte del tempo piani di query precompilati. SQL è un linguaggio di espressione, 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 applicazione, incluso l'ORM generato, SQL, non è più all'interno del database, a differenza delle stored procedure, lo considero comunque come codice del database. Perché richiede ancora la conoscenza di SQL e database (tranne il più semplice CRUD) e, se applicato correttamente, funziona in modo molto diverso rispetto al codice procedurale solitamente creato con linguaggi di programmazione come C # o Java.

    
risposta data 01.10.2016 - 15:06
fonte
2

Dipende molto dal business, dalla sua cultura e dal suo patrimonio. Considerazioni tecniche a parte (queste sono state trattate da entrambe le parti), le risposte fornite ti dicono che si tratta di dove vengono le persone. In alcune organizzazioni, i dati sono re e il DBA è una figura potente. Questo è il tuo tipico ambiente centralizzato, un centro dati con una serie di terminali ad esso 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 in mezzo.

L'altra estremità dello spettro è la pura architettura a 3 livelli. O forse multi-livello in un business orientato al web. Probabilmente sentirai un'altra storia qui. L'amministratore di database, se presente, sarà solo un assistente che svolge alcune attività amministrative.

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

Ci sono spesso così tanti fattori legati all'ambiente non tecnici coinvolti, non c'è una risposta generale a questa domanda.

    
risposta data 01.10.2016 - 19:40
fonte
2

Il termine logica aziendale è aperto all'interpretazione. Durante la creazione di sistemi, vogliamo garantire l'integrità del database e dei suoi contenuti. Come primo passo dovrebbero esserci diverse sovvenzioni per l'accesso degli utenti. Come esempio molto semplice, consideriamo un'applicazione ATM.

Per ottenere il saldo dell'account, fare una selezione su una vista appropriata dovrebbe andare bene. Ma per trasferire fondi, vorrai che la transazione venga incapsulata da una stored procedure. La logica aziendale non dovrebbe essere autorizzata ad aggiornare direttamente le tabelle per gli importi di credito e di 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 aziendale, in questo esempio, dovrebbe verificare preventivamente che siano disponibili fondi sufficienti e che l'account di destinazione esiste e solo successivamente richiamare i fondi di trasferimento. Se si verifica un altro debito tra i passaggi iniziali e la chiamata del proc memorizzato, solo allora verrà restituito un errore.

    
risposta data 15.03.2017 - 01:30
fonte