I have a situation where the solution I identified clearly violates the Open / Closed principle and I would like to find a better solution that does not violate this principle. Obviously my concern is not simply to "obey the principle" but rather to build a code that is easier to maintain later.
The scenario is basically the following: we have a program coded in Windows Forms and we need to implement the execution of periodic tasks. The meaning of this is basically the following: we want to produce the ability that according to a criterion of each task, the system on a given day presents a window to the user asking if he wants to do it or not, the ability to delay the next time you open the system.
The solution I found, including the simplest one was: create a EPeriodicTasks
enumeration that contains a list of the tasks that the system implements. I also thought about creating a EPeriodicTaskStatus
enumeration with Completed
, Delayed
and Canceled
values. After that, then create a class: PeriodicTaskLog
that records the execution information. It simply has PeriodicTask
properties of type EPeriodicTasks
, DateExecution
type DateTime
, ExecutionStatus
type EPeriodicTaskStatus
.
Finally, I implement a PeriodicTaskService
service that contains a method: RunPeriodicTasks
that runs every time the program starts.
This class then has two methods for each PeriodicTask
: a verification method, which implements the criterion to see if that day needs to perform this task. Among other things, this method checks to see if it was already done on that day by querying the PeriodicTaskLogs
. The second method is the execution itself, which can simply open another window of the program, or simply do something in the background.
The problem with this solution is that it clearly violates the Open / Closed principle, joins a lot of responsibility in the PeriodicTaskService
class, and makes maintenance difficult. To add a PeriodicTask
you need to go there and change that class, and if many are created as the program evolves according to requirements, this class will get intractable.
This all has an obvious and very good solution: every periodic task has its own class, encapsulating the verification logic if it should run, and along with checking the logic itself.
The problem is this: each periodic task needs to be related to a single enumeration value, to be able in the log to identify which is which. I can associate an enumeration value to an object, but not to a u class, since the class is only the object model, not having its own values. I could even implement a static member for this, but it seems gambiarra.
How can I improve my solution to comply with the Open / Closed principle and also the Single Responsability Principle? How can I resolve this deadlock and improve this modeling?