I've written a system that calculates discounts for a shopping cart based on a set of rules. Each rule is implemented with the following interface (C#):
interface IRule
{
bool IsActive();
bool IsApplicableTo(IShoppingCart cart);
decimal CalculateDiscount(IShoppingCart cart);
}
A concrete implementation might look something like this:
class Rule : IRule
{
bool IsActive() { return true; }
bool IsApplicableTo(IShoppingCart cart)
{
if (!IsActive())
return false;
return TestIfApplicable(cart);
}
decimal CalculateDiscount(IShoppingCart cart)
{
if (!IsApplicableTo(cart))
return 0m;
return CalculateStuff(cart);
}
}
Now I'm trying to introduce some logging to the system. To keep things clean, I don't want to jam it into the Rule class. So I thought I'd make a Decorator for IRule, which handles the logging:
class LoggingRule : IRule
{
IRule decoratedRule;
bool IsActive()
{
LogImportantThings();
return decoratedRule.IsActive();
}
//And so on.
}
The issue that I'm running into here, is that the Rule class actually calls the IsActive and IsApplicableTo methods itself. When that happens, the decorator is simply passed by, and nothing is being logged.
I suppose I could make the LoggingRule a subclass of Rule. It would mean that I would have to make a LoggingRule variant for every IRule implementation. That could potentially cause a lot of duplication.
I could also put the logging into a base class, and use the Null object pattern when I don't want to log anything. But then again, 99 out of 100 times I don't want to log anything. And when these methods are called many many times, is it worth the potential overhead?
So neither solution seems particularly elegant, and I'm struggling to find a better alternative... Any suggestions?