Search code examples
c#architecturesolid-principles

Adding a conditional logic without violating SOLID principles C#


I have and interface and Implementation as below. Where if a number is divisible by the devisor it will display the content called "Divisible". Now the new enhancement came where I need to change the text based on the time. If the number is divisible and the time is 12:00PM display "Divisible ***".If the time is not "12:PM" display the old value i:e "Divisible". I know it can be done,But condition is that we should not violate SOLID principle.Whether the design which I have done is wrong? Please suggest.

public interface IRule
{
    string GetResult(int number);
}

public class DivisibleRule : IRule
{

    private readonly int divisor;


    private readonly string contentToDisplay;


    private readonly string replacementContent;


    public DivisibleRule(int divisor, string contentToDisplay)
    {
        this.divisor = divisor;
        this.contentToDisplay = contentToDisplay;
    }

    /// <summary>
    /// Gets the result.
    /// </summary>
    /// <param name="input">The input.</param>
    /// <returns>Returns the content if divisible.</returns>
    public string GetResult(int input)
    {
        return input % this.divisor == 0
             ?  this.contentToDisplay
            : string.Empty;
    }
}

Solution

  • If you want to add this functionality without modifying the existing code (which is basically what Open/closed principle is about) then you can add a decorator which will apply the new conditional logic to result returned from already existing DivisibleRule. Then wherever it's appropriate you can use DivisibleRule decorated with your decorator.

    This decorator can look something like this:

    public class RuleTimeDecorator : IRule
    {
        private readonly IRule _decoratedRule;
    
        public RuleTimeDecorator(IRule decoratedRule)
        {
            _decoratedRule = decoratedRule;
        }
    
        public string GetResult(int input)
        {
            var result = _decoratedRule.GetResult(input);
    
            return IsMidnight()? $"{result} ***" : result;
        }
    
        private bool IsMidnight() => //here goes the code to check if current time meets criteria 
    }
    

    Nice thing is that this decorator can be used to decorate any other implantation of IRule (as long as it makes sens in your domain).

    BTW I'm using some C#6 features like string interpolation and expression bodied members but that's not required.