0

Recently I've received the following requirement which is being quite hard to implement. The system is a Windows Forms financial system and the requirement is as follows:

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.

It turns out there is another requirement like that:

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.

The system already has functionality developed that allows the generation of billets and invoices, so that is not the issue.

The issue here is: given that it is a certain day of the months and certain specific rules are met, the system must allow for a specific functionality to be called.

In the case of billets, the day is the last day of the month, the rule to be met is that the billets to be generated are for all charges to be paid in the next month, and the functionality is the generation of these billets.

In the case of invoices the day is the first day of the month, the rule to be met is that the invoices should be marked as antecipated and the functionality is the generation of these invoices.

My only idea was to make a slight generalization and approach the problem in the following way:

Create one IPeriodicTask with two methods: ShouldExecute and Excute. The first tells whether or not today is a day to run that functionality and Execute runs it. Second, create one PeriodicTaskCondition which encapsulates one integer representing the day of the month. This class has one IsMetToday method which returns true if today is the said day of the month and false otherwise.

Then implement PeriodicBilletGeneration for the first task and PeriodicInvoiceGeneration both implementing IPeriodicTask. They hold one reference to PeriodicTaskCondition.

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 of IPeriodicTask these events to see which still have to be run, and if there is any, I show them there.

The only issues I've come accross when trying to implement this were: (i) how to manage the fact that the user will need to edit and persist the PeriodicTaskConfiguration for each task and (ii) deal with these events correctly.

The bigger problem is persistence. Persistence is usually delt with using repositories for aggregates. The problem here is that we just need to persist one instance of PeriodicTaskConfiguration per class. So we need a way to say that "this particular instance" corresponds to "PeriodicBilletGeneration" and "that particular instance" corresponds to "PeriodicInvoiceGeneration". I really don't know how to do this.

This reminds me a little bit of CQRS: it seems I'm just creating commands and adding support to check with custom rules that these commands should be ran on specific dates. The execution then raises and saves events.

Anyway, my question here is twofold:

  1. Is my approach reasonable? I don't know, I feel like I'm "inventing too much here". I don't know if this is the right way to do object oriented design. I mean this idea came out of thin air, not by any specific process of analysizng the requirements or whatever. It is just one abstraction that seemed correct to me. Is my solution valid and my way of thinking correct?

  2. Is there any better way to approach this particular problem? If there is, how could I have thought of it, instead of following this route?

  • Is your "user" the person looking at the UI, or the person coding the service calls? What does your overall architecture look like? Is this a coding problem, a design problem or simply a "strategy" problem? – Robert Harvey May 13 '17 at 13:45
  • The user in the requirements is the person looking at the UI which has administrator access to the system. The overall architecture is like this (trying to simplify the most possible) - the app is one WinForms app, which has one Core business logic assembly and one AppService assembly. The AppService holds code to orchestrate the relation between UI and the Core, so that there is no business logic whatsoever on the forms. Simplifying, AooServices translates ViewModels to Domain Models and triggers domain logic, or translates Domain Models to ViewModels to be presented in the views. – user1620696 May 13 '17 at 13:59
  • In the Core layer I have the classes and logic necessary to generate billets and invoices. The issue is that I need to check certain businees rules to decide if the view must ask the user to generate billets/invoices. I also need to keep track whether the user already did so, to not show anymore. I believe it is more of a strategy and object oriented design problem at this stage. UI design doesn't seem to be the issue. – user1620696 May 13 '17 at 14:00
  • Are you using a database of some sort? Your Domain Logic needs to check the business rules (one of which is "has this happened yet"), and then write the fact that it's already happened for this month into the database. – Robert Harvey May 13 '17 at 14:08
  • Yes, I'm using MySQL. The system is a reasonably big, there are many tables for the entities and everything is using MySQL right now. That's what I thought when I imagined creating that PeriodicTaskExecuted event. My idea was to check for the event. But do you think it is best to have one general event like this for these tasks with a property to decide which task it is, or one specific event class for each task? – user1620696 May 13 '17 at 14:14
1

If the requirement was "the button should be red on thursdays" would you create a list of tasks one per thursday, or would you just check the day when the form loads?

  • Checking directly on the form was my first thought, but then I would be mixing up business logic into the UI code (the check is not just for the day, but also if there are any billets/invoices under the needed conditions to be generated), right? That is why I thought on this other approach, which I recognize isn't ideal yet. – user1620696 May 13 '17 at 14:14
  • you can separate the ui from the bl by raising an event. It sounds to me like you have a structure for tasks and are trying to apply it to what really is just a Visibility setting on a button – Ewan May 13 '17 at 14:50
  • So your point is: (i) create two methods on the domain layer to verify if it is the day to generate billets and invoices, (ii) on the UI trigger a visibility setting depending on these methods to show a message informing it is the day to do the operation with a button to call the logic, (iii) create two more methods on the domain layer, each to do each action and finaly (iv) wire these buttons with controled visibility to call the corresponding method in the domain layer. I got it right? – user1620696 May 13 '17 at 16:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.