Recentemente ho ricevuto il seguente requisito, che è piuttosto difficile da implementare. Il sistema è un sistema finanziario Windows Form e il requisito è il seguente:
When the system is opened in the last day of the month, it should ask whether or not an admin user wants to generate the next months billets.
Si scopre che esiste un altro requisito del genere:
When the system is opened in the first day of the month, it should ask whether or not an admin user wants to generate the antecipated invoices for that month.
Il sistema ha già funzionalità sviluppate che consentono la generazione di billette e fatture, quindi non è questo il problema.
Il problema qui è: dato che è un certo giorno dei mesi e alcune regole specifiche sono soddisfatte, il sistema deve consentire di chiamare una funzionalità specifica.
Nel caso di billette, il giorno è l'ultimo giorno del mese, la regola da rispettare è che le billette da generare sono per tutte le spese da pagare nel mese successivo, e la funzionalità è la generazione di queste billette.
Nel caso delle fatture il giorno è il primo giorno del mese, la regola da rispettare è che le fatture debbano essere contrassegnate come antecipate e la funzionalità è la generazione di queste fatture.
La mia unica idea era di fare una leggera generalizzazione e affrontare il problema nel modo seguente:
Create one
IPeriodicTask
with two methods:ShouldExecute
andExcute
. The first tells whether or not today is a day to run that functionality andExecute
runs it. Second, create onePeriodicTaskCondition
which encapsulates one integer representing the day of the month. This class has oneIsMetToday
method which returns true if today is the said day of the month and false otherwise.Then implement
PeriodicBilletGeneration
for the first task andPeriodicInvoiceGeneration
both implementingIPeriodicTask
. They hold one reference toPeriodicTaskCondition
.Then in the first form which opens when the app is run, I implement a sort of dashboard which will list all tasks that should be done today. Each of them has a description of the task and a button to run it.
I create then one
PeriodicTaskExecuted
event which signals the task was executed in a certain month. Then to make this list in the dashboard, I check for all concrete implementations ofIPeriodicTask
these events to see which still have to be run, and if there is any, I show them there.
Gli unici problemi che ho incontrato durante il tentativo di implementare questo sono stati: (i) come gestire il fatto che l'utente dovrà modificare e persistere il PeriodicTaskConfiguration
per ogni attività e (ii) gestire questi eventi correttamente.
Il problema più grande è la persistenza. La persistenza di solito è delta con l'utilizzo di repository per gli aggregati. Il problema qui è che dobbiamo solo mantenere una istanza di PeriodicTaskConfiguration
per classe. Quindi abbiamo bisogno di un modo per dire che "questa particolare istanza" corrisponde a " PeriodicBilletGeneration
" e "quella particolare istanza" corrisponde a " PeriodicInvoiceGeneration
". Io davvero non so come farlo.
Questo mi ricorda un po 'di CQRS: sembra che sto solo creando comandi e aggiungendo supporto per verificare con regole personalizzate che questi comandi debbano essere eseguiti in date specifiche. L'esecuzione quindi solleva e salva gli eventi.
Ad ogni modo, la mia domanda qui è duplice:
-
Il mio approccio è ragionevole? Non lo so, mi sembra di "inventare troppo qui". Non so se questo è il modo giusto di fare design orientato agli oggetti. Intendo che questa idea è venuta fuori dal nulla, non da un processo specifico di analisi dei requisiti o di qualsiasi altra cosa. È solo un'astrazione che mi è sembrata corretta. La mia soluzione è valida e il mio modo di pensare è corretto?
-
C'è un modo migliore per affrontare questo particolare problema? Se c'è, come potrei aver pensato, invece di seguire questa strada?