How to obey the Open/Closed principle in this situation?

Asked

Viewed 51 times

2

I have a situation where the solution that I have clearly identified violates the Open/Closed principle and I would like to find a better solution that does not violate that principle. Obviously my concern is not simply to "obey the principle", but to build a code that is easier to maintain later.

The scenario is basically the following: we have a program encoded 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 in a given day presents a window to the user asking if he wants to do or not, giving even the possibility to postpone to the next time he opens the system.

The solution I found, even being the simplest, was to create an enumeration EPeriodicTasks that contains a list of tasks that the system implements. I also thought of creating an enumeration EPeriodicTaskStatus with values Completed, Delayed and Canceled. After that, then create a class: PeriodicTaskLog that records the information of executions. It simply has properties PeriodicTask of the kind EPeriodicTasks, DateExecution of the kind DateTime, ExecutionStatus of the kind EPeriodicTaskStatus.

Finally, I implement a service PeriodicTaskService which contain a method: RunPeriodicTasks that is executed whenever the program starts.

This class then has for each PeriodicTask two methods: a verification method, which implements the criterion to see if that day needs to perform this task. Among other things, this method checks whether it was already carried out that day by consulting the PeriodicTaskLogs. The second method is execution itself, which can simply open another program window, or simply do something in the background.

The problem with this solution is, It clearly violates the Open/Closed principle, brings a lot of responsibility to the class PeriodicTaskService and makes maintenance difficult. To add a PeriodicTask it is necessary to go there and change this class, and if many are created as the program evolves according to the requirements, this class will become intractable.

This all has an obvious and very good solution: each Periodic task has its own class, encapsulating the verification logic itself must run, and along with the verification the logic itself.

The problem with this is this: each Periodic task needs to be related to a single enumeration value, in order to be able to identify which is which. I can associate an enumeration value to an object, but not to a class, since the class is only the object model, having no proper values. I could even implement a static member for this, but it seems to gambiarra.

How can I improve my solution to obey the Open/Closed principle and also the Single Responsability Principle? How can I solve this impasse and improve this modeling?

1 answer

1

Good afternoon Leonardo, recommend you solve your problem using the Rules Pattern.

With this, you will have a unique responsibility for each type of task you will do and also respect the Open/Closed.

Have an example of how to use Rules Pattern:

public class Rulesdiscountcalculator : Idiscountcalculator { List _Rules = new List();

public RulesDiscountCalculator()
{
    _rules.Add(new BirthdayDiscountRule());
    _rules.Add(new SeniorDiscountRule());
    _rules.Add(new VeteranDiscountRule());
    _rules.Add(new LoyalCustomerRule(1, 0.10m));
    _rules.Add(new LoyalCustomerRule(5, 0.12m));
    _rules.Add(new LoyalCustomerRule(10, 0.20m));
    _rules.Add(new NewCustomerRule());
}

public decimal CalculateDiscountPercentage(Customer customer)
{
    decimal discount = 0;

    foreach (var rule in _rules)
    {
        discount = Math.Max(rule.CalculateCustomerDiscount(customer), discount);
    }

    return discount;
}

}

For explanation of the example see:

http://www.michael-whelan.net/rules-design-pattern/

Abc!

  • While this link may answer the question, it is best to include the essential parts of the answer here and provide the link for reference. Replies per link only can be invalidated if the page with the link is changed. - Of Revision

  • I made the correction as suggested. Grateful.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.