Rappresentare le regole aziendali con eccezioni


16

So che è costoso ma (IMO) credo che sia un'ottima pratica. Sto parlando di regole come dire, non puoi salvare una fattura se non sei un addetto alle vendite ... quindi in quel caso lanciare un'eccezione che dice "non sei autorizzato" o simili ...

Un altro approccio sarebbe avere oggetti con uno status o qualcosa del genere

C'è qualche altro approccio? come ti senti a riguardo?

Risposte:


15

Se intendi rappresentare i controlli delle singole regole aziendali con eccezioni, non credo sia una buona idea. Molte volte devi segnalare più di una condizione non riuscita e non fermarti alla prima.

D'altra parte, credo che verificare tutte le regole e poi lanciare un'eccezione con il riepilogo sia una buona pratica.


1
È esattamente come lo gestisco nelle mie app. Usando FluentValidation per semplificarmi la vita e il metodo ValidateAndThrow mi salva la giornata.
Matteo Mosca,

In un'app UI sono completamente d'accordo, ma in un'app di livello di servizio genererei un'eccezione se mi passasse un oggetto non conforme alle regole aziendali. Se si usano i due in combinazione, a volte si aggiunge una funzione di convalida o un errore complesso, come descritto da Matiasha nell'ultima frase.
Bill

8
Genera un'eccezione specifica del dominio . Questo ti consente di separare tra il nostro e il non-nostro più in alto.

@ Thorbjørn Ravn Andersen +1 "aggiunta specifica al dominio" grande aggiunta
Justin Ohms,

1
@JamesPoulson potrebbe essere sufficiente creare JamesPoulsonExceptionuna sottoclasse di RuntimeExceptione quindi fornire l'eccezione originale come cause. Puoi quindi semplicemente dire if (exception instanceof JamesPoulsonException)... di differenziare. Utilizzare il getCause()metodo per raggiungere l'eccezione originale.

9

Nell'esempio che ci hai fornito penso che sollevare un'eccezione sia una cattiva idea. Se sai che l'utente non è autorizzato prima di iniziare a lavorare e permetti ancora loro di svolgere alcune funzioni e poi di schiacciarli con un messaggio DOPO che hanno già completato l'attività, è solo una cattiva progettazione.

L'uso delle eccezioni per far rispettare le regole aziendali non è un buon progetto.


Quello che capisco di quello che hai detto è che non sei d'accordo con l'interfaccia utente. Sto bene con quello. Sono d'accordo con te sul fatto che un'interfaccia utente molto più amichevole non ti permetterebbe di provare ad aggiornare qualcosa che non ti è permesso. Ciò non significa che la verifica della convalida e delle eccezioni nel core business non sia necessaria. Al contrario, credo che siano un must. È necessario per garantire che un'interfaccia utente mal programmata non consenta un uso improprio BL.
Fede,

8
@Fede: è una questione di separazione delle preoccupazioni. L'interfaccia utente è responsabile della raccolta delle intenzioni dell'utente e della segnalazione del feedback dal livello aziendale. Il lavoro del livello aziendale consiste nell'analizzare le informazioni raccolte dall'IU, analizzandole e riportandole all'interfaccia utente e / o chiedendo al livello dati di conservare alcuni dati. Ci dovrebbe essere solo un accoppiamento lento tra questi strati. Le eccezioni sono un approccio scarso e scarso all'accoppiamento libero. Non significa solo condividere le classi effettive tra i livelli, ma invoca anche un meccanismo che ha lo scopo di gestire guasti imprevisti.
Adam Crossland,

@Adam - Ben detto e esattamente sul punto.
Walter,

1
@Adam - Non seguirti con la separazione dei problemi. Non mi aspetto che nessuno nell'interfaccia utente gestisca un CustomerNameInLowercaseException (per favore, spero anche che non esista nemmeno un'eccezione!). Puoi semplicemente gestire una ValidationException generica. Inoltre, sono al 100% con te che l'interfaccia utente dovrebbe solo raccogliere informazioni e tutto il resto. Quello che ho detto prima è che, indipendentemente da ciò che fai nell'interfaccia utente, il BL non dovrebbe presumere che ogni input sia ok. È solo una programmazione difensiva.
Fede,

@Fede: è compito del Business Layer assicurare che ogni input sia OK. Se l'interfaccia utente lo sta facendo, sta implementando la logica aziendale. Ora, se è il caso che un campo di input è limitato a cifre e il BL vede alfa caratteri, per tutti i mezzi lanciano un un'eccezione . Ogni volta che un componente riceve input non validi da un altro componente, generare un'eccezione è logico e corretto. L'interfaccia è stata interrotta e il sistema è danneggiato. Tuttavia, la convalida degli input è molto diversa dall'esecuzione della logica aziendale. Due cose molto diverse.
Adam Crossland,

5

Non vedo quale valore abbia un'eccezione nel creare una buona logica aziendale. Esistono decine di approcci alla gestione della logica aziendale che non implicano l'utilizzo di un sistema destinato a far fronte a condizioni impreviste nel funzionamento di un sistema.

Si prevede che nella logica aziendale non saranno soddisfatte le condizioni; questo è il motivo per averlo in primo luogo, e non si desidera spostare sulle spalle lo stesso meccanismo che gestisce errori I / O imprevisti, errori di memoria insufficiente e riferimenti null. Questi sono guasti del sistema, ma il rilevamento di condizioni commerciali non soddisfatte è il buon funzionamento del sistema.

Inoltre, è un sistema maturo per conseguenze non intenzionali. Poiché un'eccezione deve essere rilevata ad un certo punto, si corre il rischio che una nuova eccezione delle regole aziendali venga catturata da qualche parte che non è prevista o si ha la possibilità che il codice che cerchi le regole aziendali rilevi eccezioni che non sono effettivamente intese per questo. Sì, queste condizioni possono essere spiegate con buone pratiche di codifica, ma in qualsiasi sistema non banale su cui sta lavorando più di uno sviluppatore, si verificheranno degli errori e devi solo sperare che non siano costosi errori.


1
Sono d'accordo, le eccezioni sono chiamate eccezioni perché non dovrebbero accadere. D'altro canto, l'applicazione di regole aziendali nel livello di servizio con un'eccezione non è necessariamente errata. Non ti aspetti che venga utilizzato, ti aspetti che il cliente invochi solo operazioni e invii solo dati che soddisfano condizioni valide; ma vuoi creare un livello di protezione perché sai che possono verificarsi errori anche nella codifica client. In un certo senso è come usare i vincoli di chiave esterna in un database: ci si aspetta che le persone inseriscano e aggiornino i dati correttamente ma sappiano che potrebbero fallire a causa di un errore di programmazione.
Jeremy,

2

esprimere regole commerciali è una cosa, implementarle è un'altra

pensare all'esperienza dell'utente; se l'utente non è un venditore, perché dare loro un pulsante che dice 'creare fattura' a tutti ?


1
Solo perché non dai un pulsante, ciò non significa che non ti invieranno comunque il messaggio di fare qualcosa. Pensa a come sarebbero facili le regole di sicurezza se fosse
bastato

Se l'utente non è autorizzato a fare X, non dare loro un pulsante che dice "Do X". La migliore sicurezza è l'ignoranza - non dire all'utente cose che non possono fare;)
Steven A. Lowe,

1

Dipende interamente da ciò che viene fatto.

Innanzitutto, qual è il comportamento effettivo che desideri? Se qualcuno sta inserendo le proprie informazioni, allora un rifiuto e una finestra di dialogo che dicono, essenzialmente, "Non puoi farlo" è probabilmente corretto. Se si tratta di una persona che inserisce i dati, che lavora da una pila di moduli, probabilmente è utile anche una finestra di dialogo e la persona che inserisce i dati può mettere i moduli non validi in una pila speciale. Se stai eseguendo l'elaborazione in batch, non vuoi fermare le cose, ma contrassegnale e passa a quella successiva.

Una volta che hai il comportamento, devi decidere come implementarlo. Avere un correttore di regole aziendali che genera un'eccezione è probabilmente una buona idea. Restituire un codice di ritorno e averlo passato è qualcos'altro che può andare storto, e certamente non vuoi che le voci errate vengano ulteriormente.

Non preoccuparti delle spese per le prestazioni. Nel caso di un individuo che inserisce dati, è banale rispetto alle altre volte coinvolte. In genere, l'umano impiegherà più tempo in quel sistema. Nel caso di un processo batch, se le eccezioni sono un problema di prestazioni, si stanno inserendo troppi record errati e in realtà la gestione e il reinserimento di tutti questi sarà più un problema delle eccezioni.


0

Avere un'API di eccezione solida e ben progettata che sia coerente è molto appropriato. L'uso di questo per far rispettare le regole di business può anche essere appropriato. Infatti, nella mia esperienza, più complicata è la regola aziendale, più è probabile che finirà per essere gestita in questo modo. Spesso è altrettanto semplice se non più semplice scrivere un sistema in cui sono previste eccezioni piuttosto che scrivere una logica di ramificazione autorevole.

Questo per dire che le semplici regole che possono essere descritte in una sola frase generalmente dovrebbero essere implementate in modo preventivo o autorevole a seconda di quale sia. Tuttavia, se si dispone di una regola multidimensionale e richiede più di tre o quattro fattori (soprattutto se la selezione di questi fattori si basa su uno o più degli altri fattori), la codifica delle eccezioni potrebbe essere più mantenibile. Spesso in questi casi il percorso logico avrà molte eccezioni precursori che devono essere lanciate (verifica il motivo per cui l'azione non può essere eseguita), quindi (o viceversa) si verifica una caduta nella sicurezza (per verificare che l'azione sia autorizzata ), a volte ci sarà una logica di accumulazione autorevole che deve essere verificata (disponibilità di discendenti / antenati, precursore afferma che gli oggetti devono essere inseriti, ecc.

Un vantaggio che deriva da questo tipo di lancio di eccezioni è che consente di separare e riutilizzare le eccezioni del precursore in più aree del progetto. (Questa è l'essenza della programmazione orientata all'aspetto.) In questo modo si incapsula un aspetto particolare delle regole generali di business in un componente autonomo e gestibile. In generale questi componenti corrisponderanno a 1-1 con i messaggi di errore generati. (Anche se a volte avrai un componente che genera diverse eccezioni, non dovresti quasi mai avere la stessa eccezione generata da più componenti.)

A mio avviso, è più difficile progettare sistemi basati sulle eccezioni e il tempo di sviluppo iniziale è più lungo poiché è necessario costruire il processo di eccezione su tutti i livelli N. Tuttavia, questi sistemi generalmente risultano molto più stabili. Mentre non è mai possibile progettare un sistema che "non fallirà", il vantaggio della progettazione basata su eccezioni è che si sta sempre anticipando il fallimento. Per la maggior parte delle persone il processo può essere contro-intuitivo. È come chiedere indicazioni e avere qualcuno che ti dica tutte le strade che non dovresti accendere.

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.