I found a problem recently that basically was this: a system needs every last day of the month to show the option for the user to generate the next month's tickets and need every first day of the month to show the option for the user to generate the advance marked invoices.
To solve this I thought about generalizing a little to reuse the code. My idea is based on this code:
public interface IPeriodicTask
{
bool ShouldExecute();
void Execute();
}
public class PeriodicTaskCondition
{
public int Day { get; private set; }
public PeriodicTaskCondition(int day)
{
if (day < 0 || day > 31) throw new ArgumentOutOfRangeException(nameof(day));
this.Day = day;
}
public bool IsMetToday()
{
var today = DateTime.Today;
bool isLastDayOfMonth = today.AddDays(1).Month > today.Month;
return (isLastDayOfMonth && this.Day >= today.Day) || this.Day == today.Day;
}
}
public class PeriodicBilletGeneration : IPeriodicTask
{
public PeriodicTaskCondition Condition { get; set; }
public PeriodicBilletGeneration(PeriodicTaskCondition condition)
{
if (condition == null) throw new ArgumentNullException(nameof(condition));
this.Condition = condition;
}
public bool ShouldExecute() { return this.Condition.IsMetToday(); }
public void Execute() { // gera boletos }
}
And a similar code for invoices. This is flexible and seems to obey the open / closed principle, because if one of these requirements comes up, just create another implementation and incorporate it.
My problem, which is the purpose of the question, is this: This PeriodicTaskCondition
essentially corresponds in a 1-1 way to the classes that implement IPeriodicTask
.
That is, for each class I have to have a snapshot.
But there are several points that draw my attention:
This type does not look like an entity, it actually looks like a value type. It does not make much sense at first to have a repository aimed at persevering it. Besides, I should only have one instance per class for my initial thinking. It could be argued that "the execution day is a business rule and should be straight into the code" and that does. In this question I am making this flexible, thinking that the user wants to configure it, because I want to see how it would be done.
The biggest problem is how to associate a persistent private instance in a database with a class. The problem is that when instantiating the class PeriodicBilletGeneration
or InvoicePeriodicGeneration
, it is necessary to pass the instance of PeriodicTaskCondition
. How will I make the system know which class corresponds to each instance? Only the class as it is does not know. And a class has no ID so I can not make an association by ID. The point is that PeriodicBilletGeneration
and PeriodicInvoiceGeneration
are not entities but rather classes that encapsulate a feature.
How can I solve this problem of "associating an instance that somehow contains parameters that say how a class should operate" with the correct class, and can these objects be used for other similar classes? This has to be done and would it be a valid approach, or my whole wrong approach?