mercredi 21 décembre 2016

C# LSP Constructor Parameters and Guard Clauses

I've been reading about the Liskov Substitution Principle (LSP) and I'm a little confused on how you adhere to it correctly. Especially when interfaces and subclasses are being used.

For example, if I have a base class:

public abstract class AccountBase
{
    private string primaryAccountHolder;

    public string PrimaryAccountHolder 
    { 
        get { return this.primaryAccountHolder; } 
        set
        {
            if (value == null) throw ArgumentNullException("value");
            this.primaryAccountHolder = value;
        }
    }

    public string SecondaryAccountHolder { get; set; }

    protected AccountBase(string primary)
    {
        if (primary == null) throw new ArgumentNullException("primary");
        this.primaryAccountHolder = primary;
    }
}

Now let's say I have two accounts that inherit from the base class. One that REQUIRES the SecondaryAccountHolder. Adding a null guard to the sub-class is a violation of LSP, correct? So how would I design my classes in such a way that they don't violate LSP but one of my sub-classes requires a secondary account holder and one does not?

Compound the question with the fact that there could be tons of different types of accounts and they'll need to be generated through a factory or factory that returns a builder or something.

And I have the same question with interfaces. If I have an interface:

public interface IPrintsSomething
{
    void PrintSomething(string text);
}

Wouldn't it be a violation of LSP to add a null guard clause for text on any class that implements IPrintsSomething? How do you protect your invariants? That is the correct word right? :p

Aucun commentaire:

Enregistrer un commentaire