SOLID : Liskov Substitution Principle (Part 2)

In the first part of the post, we visited the core definition of Liskov Substitution principle and took time to understand the problem using an example. In this second part, we would take time to understand some of the governing rules of the principle.

The rules that needs to be followed for LSP compliance can be broadly categorized into mainly two categories.

  • Contract Rules
  • Variance Rules

Let us examine the Contract Rules first.

Contact Rules
The three contact rules are defined as follows.
* Preconditions cannot be strengthened in a subtype.
* Postconditions cannot be weakened in a subtype.
* Invariants—conditions that must remain true—of the supertype must be preserved in a subtype

Let us examine each of them breifly.

Preconditions cannot be strengthend in a subtype.

Preconditions are conditions that are necessary for a method to run reliably. For example, consider a method in a school application, which returns the count of students above specified age.

public virtual int GetStudentCount(int minAge)
{
if(minAge <=0)
throw new ArgumentOutOfRangeException("Invalid Age");
return default; // For demo purpose
}

As observed in the above method, a non-positive value for age needs to be flagged as an exception and method should stop executing. The method does this check as the first step before it executes any logic related to the funcationlity of the method and thereby preventing the method execution unless the parameters are valid. This is a typical example of preconditions. There are other ways to add preconditions, but that would be out of scope of the current context.

So what happens if the precondition is strengthed. Let us assume that the application for Kindergarden for the school derieves from the same class, but adds another precondition.

public override int GetStudentCount(int minAge)
{
if(minAge <=0) throw new ArgumentOutOfRangeException("Invalid Age"); if(minAge >=5)
throw new ArgumentOutOfRangeException("Invalid Age");
return default; // For demo purpose
}

This creates a conflict in the calling class. The caller was invoking the method from the base Class, it would not throw an exception if the value is greater then 5. However, if the caller was invoking the method from the Child Class, it would now throw an exception, thanks to the new precondition we have added. Let’s demonstrate the same using Unit Tests.

[Test]
[TestCaseSource(typeof(Preconditions), nameof(TestCases))]
public void GetStudentCount(School school,int age)
{
Assert.GreaterOrEqual(school.GetStudentCount(age), 0);
}

public static IEnumerable TestCases
{
get
{
yield return new TestCaseData(new School(), 7);
yield return new TestCaseData(new Kindergarden(), 7);
}
}
}

The Unit Tests show that the strengthening of Preconditions would now indirectly force the caller to violate the fact that it should not make any assumptions about the type it is acting on (and thereby violating Open Closed Principle).

Post Conditions cannot be weakend in a subtype

During the execution of the method, the state of the object is most likely to be mutated, opening the door of possiblity that the method might leave the object in an invalid state due to errors in the method. Post Conditions ensures that the state of the object is in a valid state when the method exits.

Much similiar to the Preconditions, the Post Conditions are commonly implemented using Guard clauses, which ensure the state is valid after the execution of logic (any code that might alter the state of the object) associated with the method. For the same reason, the Post Conditions are placed at the end of the method.

The behavior of Post Conditions in sub-classes is the complete opposite of what happens with Pre Conditions. The Post Conditions, if weakened, could l;ead to existing clients to behave incorrectly. Let us explore a scenario. We will write the Unit Tests first.

[Test]
[TestCaseSource(typeof(Postconditions), nameof(TestCases))]
public void TestLabFeeForSchool(School school, long studentId)
{
Assert.Greater(school.CalculateLabFees(studentId),0);
}

public static IEnumerable TestCases
{
get
{
yield return new TestCaseData(new School(), 7);
}
}

The above Test Case ensures that the CalculateLabFees method returns a positive and non-zero value as result. Let us assume that School.CalculateLabFees method was defined as following.

public class School
{
public virtual decimal CalculateLabFees(long studentId)
{
var labFee = MockMethodForCalculatingLabFees(studentId);

if (labFee <= 0)
return 1000;
return labFee;
}

private decimal MockMethodForCalculatingLabFees(long studentID)
{
return default;
}
}

The Post Condition in the base class ensures that if the labFee is less than or equal to zero, a default value of 1000 is returned. The Test Case would pass successfully with the instance of class. The CalculateLabFees method would return a positive, non-zero value as expected by the Unit Test.

Now, let us assume the Kindergarden Implementation. The Kindergarden doesn’t have Lab Fees and hence, would return a default value 0 for the CalculateLabFee method.

public class Kindergarden : School
{
public override decimal CalculateLabFees(long studentId)
{
return 0;
}
}

As you can notice the Post Condition has been weakened in the Child Class. This would cause issues with client which would expect a positive response, as with the Unit Test Case. This highlights another instance where significance of honoring LSP is highlighted.

Invariants must be maintained

An invariant describes a condition of a process that remains true before the process begins and after the process ends, until ofcourse the object is out of scope.

Consider the following base class.

public class Student
{
public string Name{ get; set; }

public void CheckInvariants()
{
if (string.IsNullOrEmpty(Name))
Name = "Name Not Assigned";
}
public virtual void AssignName(string name)
{
CheckInvariants();
Name = name;
CheckInvariants();
}
}

The class requires the Name property to be always have a value. The CheckInvariants method assigns a default value if the clause is violated. Let us assume we have an sub class NurseryStudent.

public class NurseryStudent : Student
{
public override void AssignName(string name)
{
Name = name;
}

}

The author of NurseryStudent forgots to ensure the Invariants holds true after the AssignName exits. This is a violation of LSP as a client using the SuperClass would expect the Name to always have a value. Consider the following code.

[Test]
[TestCaseSource(typeof(Invariants), nameof(TestCases))]
public void TestInvariants(Student student,string name)
{
student.AssignName(name);
Assert.Greater(student.Name.Length, 0);
}

public static IEnumerable TestCases
{
get
{
yield return new TestCaseData(new Student(), string.Empty);
yield return new TestCaseData(new NurseryStudent(), string.Empty);
}
}

The Unit Test Case would fail

Let’s write the Unit Test Case before writing the example for sub class.

[Test]
[TestCaseSource(typeof(Invariants), nameof(TestCases))]
public void TestInvariants(Student student,string name)
{
student.AssignName(name);
Assert.Greater(student.Name.Length, 0);
}

public static IEnumerable TestCases
{
get
{
yield return new TestCaseData(new Student(), null);
yield return new TestCaseData(new NurseryStudent(), null);
}
}

The Test Case would fail when an instance of NurserStudent is passed to the method as the Name property would have an unexpected value of null when leaving the AssignName method. This would cause exceptions in all clients which expects the behavior of invariants are retained by any subclass of the Student.

In this post we explored the Contract Rules for LSP. In the part, we would explore the variance rules involved for conforming with LSP. All code samples given in the post are available in my Github

Conditional Serialization using NewtonSoft Json

One of the least explored feature of Newtonsoft Json is the ability serialize properties conditionally. Consider the hypothetical situation wherein you want to serialize a property in a class only if a condition is satisfied. For example,

public class User
{
public string Name {get;set;}
public string Department {get;set;}
public bool IsActive {get;set;}
}

If the requirement is that you need to include serialize the Department Property only if the User Is Active, then the easiest way to do it would be to use the Conditional Serialization functionality of Json.Net. All you need to do is include a method that
a) Returns a boolean indicating whether to serialize or not.
b) Should be named with Property named prefixed with ‘ShouldSerialize’

For example, for the Property Department, the method should be named ‘ShouldSerializeDepartment’. Example,

public bool ShouldSerializeDepartment()=> IsActive;

Complete Code

public class User
{
public string Name {get;set;}
public string Department{get;set;}
public bool IsActive {get;set;}
public bool ShouldSerializeDepartment()=> IsActive;
}

Client Code

var user = new User{ Name = "Anu Viswan", IsActive = false} ;
var result = JsonConvert.SerializeObject(user);

Output

{"Name":"Anu Viswan","IsActive":false}

Serializing/Deserializing Dictionaries with Tuple as Key

Sometimes you run into things that might look trivial but it just do not work as expected. One such example is when you attempt to serialize/Deserialize a Dictionary with Tuples as the key. For example

var dictionary = new Dictionary<(string, string), int>
{
[("firstName1", "lastName1")] = 5,
[("firstName2", "lastName2")] = 5
};

var json = JsonConvert.SerializeObject(dictionary);
var result = JsonConvert.DeserializeObject<Dictionary<(string, string), string>>(json);

The above code would trow an JsonSerializationException when deserializing. But the good part is, the exception tells you exactly what needs to be done. You need to use an TypeConverter here.

Let’s define our required TypeConverter

public class TupleConverter<T1, T2> : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}

public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var elements = Convert.ToString(value).Trim('(').Trim(')').Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
return (elements.First(), elements.Last());
}
}

And now, you can alter the above code as

TypeDescriptor.AddAttributes(typeof((string, string)), new TypeConverterAttribute(typeof(TupleConverter<string, string>)));
var json = JsonConvert.SerializeObject(dictionary);
var result = JsonConvert.DeserializeObject<Dictionary<(string, string), string>>(json);

With the magic portion of TypeConverter in place, your code would now work fine. Happy Coding.

Evil Code #010 : Extension Methods

Back with Evil Code Series again. What would be the output of the following.

void Main()
{
PrintToString("SampleText");
PrintToDescription("SampleText");
PrintToString(null);
PrintToDescription(null);
}
public void PrintToString(string valueToPrint)
{
Console.WriteLine($"Printing From {nameof(PrintToString)} : {valueToPrint.ToString()}");
}

public void PrintToDescription(string valueToPrint)
{
Console.WriteLine($"Printing From {nameof(PrintToDescription)} : {valueToPrint.ToDescription()}");
}

public static class Extensions
{
public static string ToDescription(this string source)
{
return $"Description = {source??"Null"}";
}
}

The code attempts to prints 2 set of data, “SampleText” and Null Value. The PrintToString method, prints the output from the inbuild ToString() method, while the second method PrintToDescription, prints the output from an extension method.

The extension method, as such, doesn’t do anything fancy. It merely adds a prefix to the string (if not null or prints null).

It would be natural to expect the firs two method calls to print normally and then the last two calls, with null as paramter, to throw exceptions. But this is where things to change and expose the functioning of Extension methods.

While the extension methods work quite similiar to instance method, there is one fundamental difference. It has ability to execute even if the source instance if null.

In our given code, in the final call to PrintToDescription, even with a null paramter, the extension method is invoked, while the PrintToString would throw an exception as soon as null.ToString is encountered.

The output of the above code would be as following.

1. Printing From PrintToString : SampleText
2. Printing From PrintToDescription : Description = SampleText
3. // Throws Exception
4. Printing From PrintToDescription : Description = Null

Json Recipies – Part 2

Continuing with our earlier post on Json Recipies, let’s explore couple of quick reference recipes using the famous NewtonSoft.Json.

Recipe 04: Deserialize to Anonymous Type

One of the least explored feature in NewtonSoft is the ability to deserialize a Json to anonymous type. For example,

var json = @"{'Name':'anu viswan','Location':'india'}";
var anonymousType = new {Name = string.Empty, Location = string.Empty};

var result = JsonConvert.DeserializeAnonymousType(json, anonymousType);
Console.WriteLine($"Name : {result.Name}, Location:{result.Location}");

This would produce an output as

Name : anu viswan, Location:india

Isn’t that quite useful. You can now deserialize json directly to anonymous types, avoiding the need to declare a type for the purpose or going through tedious task of exploring the JObject. I believe this functionality is quite underused.

Recipe 05: Formatting Json as camelCase.

What if you come across a situation wherein, you want to format the Json with keys in camelCase. For example, consider the following json.

{'FirstName':'Anu','LastName':'Viswan','Age':35}

You would like to format the json such that the keys are rewritten as firstName,lastName and age. This is where CamelCasePropertyNamesContractResolver comes into picture. You could set the ContractResolver to CamelCasePropertyNamesContractResolver using the following.

var json = @"{'FirstName':'Anu','LastName':'Viswan','Age':35}";
var student = JsonConvert.DeserializeObject(json);
var camelSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
var result = JsonConvert.SerializeObject(student,camelSettings);

Where Student is defined as

public class Student
{
public string FirstName{get;set;}
public string LastName{get;set;}
public int Age{get;set;}
}

This would format the json string with all keys in camelCase.

So far, we have examined a simple json. Let’s expand the example for a complex nested version that happens to have a property of Type object, which encapsulate the nested json part. For example, what if the json in question is as follows

{"FirstName":"Anu","LastName":"Viswan","age":35,"SkillSet":{"ProgrammingLanguages":"C#,Dart","Database":"Sql Server,MySql,MongoDb"}}

This is where things get interesting. If you were to define a Property of Type Object in the Student Class, you could be suprised that the inner object wasn’t camelCased. Let’s check by adding a Property called SkillSet of Type object in Student.

public class Student
{
public string FirstName{get;set;}
public string LastName{get;set;}
public int Age{get;set;}
public object SkillSet{get;set;}
}

If we were to run the client code using CamelCasePropertyNamesContractResolver as described above, the output would be as following.

{"firstName":"Anu","lastName":"Viswan","age":35,"skillSet":{"ProgrammingLanguages":"C#,Dart","Database":"Sql Server,MySql,MongoDb"}}

As you can observe, the inner Object didn’t have its keys formatted with CamelCase.

The trick lies in most unexpected corner. Infact, you do not even need the Student Class. All you need is the ExpandoObject. Let’s rewrite the client code using ExpandoObject.

var json = @"{'FirstName':'Anu','LastName':'Viswan','Age':35, SkillSet:{ProgrammingLanguages:'C#,Dart',Database:'Sql Server,MySql,MongoDb'}}";
var student = JsonConvert.DeserializeObject(json);

var camelSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
var result = JsonConvert.SerializeObject(student,camelSettings);

That’s all the magic you needed. Now the formatting for inner Object is magically fixed.

{"firstName":"Anu","lastName":"Viswan","age":35,"skillSet":{"programmingLanguages":"C#,Dart","database":"Sql Server,MySql,MongoDb"}}

Recipe 06: Search and Replace using JObject.

There might be situations which forces you to use JObject for parsing json. Yes, it is inconvenient way of doing it, but sometimes you need to walk the hard path ( or should I say, sometimes JObject is the most convenient option).

How could you search and replace a token in JObject, especially if you do not know the names of parent node. For example, let us consider the following two json strings.

{'Fields' : { 'CA' : 'P' , 'MA' : { 'COLL': 'Q'} } }
{'Item' : { 'PA' : 'P' , 'VA' : { 'COLL': 'D'} } }

You are supposed to update the Value of COLL. However, as you can observe from the two Jsons available, the parents nodes are different.

Updating COLL would have been tough task. But there are few interesting methods in JObject makes our life easier.

To Select the COL token in either of the Json, you could use the SelectToken method

jobject.SelectToken("$..COLL");

For updating the value, you could use the Replace method. For example,

jobject.SelectToken("$..COLL").Replace(1);

That would give use the output we require. The output of above given samples would be as follows.

// Example 1
{
"Fields": {
"CA": "P",
"MA": {
"COLL": 1
}
}
}

// Example 2
{
"Item": {
"PA": "P",
"VA": {
"COLL": 1
}
}
}

Non-Blinking Caret in WPF Textbox

A recent question I came across recently was “How could one stop the caret in a WPF Textbox from blinking ?“.

My first instinct drove me in the direction of HideCaret method, but quickly realized WPF applications doesn’t allow you to get the Handle for individual controls. It only provides handles for Windows. This was quite unlike WinForm applications and ruled out usage of HideCaret API as it requires Handle for the control to disable the Caret.

The next solution I came up with ( and am still sticking on to it until i get a better one) was to emulate the behavior. What if it was possible to disable the original caret and mock the behavior using something else. The first part of the challenge was pretty easy, you could set the CaretBursh property to a Transparent color and the original Caret is hidden.

<TextBox x:Name="txtName" CaretBrush="Transparent" />

But the more important question was how to mock the caret. The solution lies in using a Canvas and Border overlaying the Textbox to emulate the caret. Let’s update our XAML first.

<Grid>
<TextBox x:Name="txtName" CaretBrush="Transparent" />
<Canvas>
<Border x:Name="Caret" Visibility="Collapsed" Canvas.Left="0" Canvas.Top="0" Width="1" Height="15" Background="Black"/>
</Canvas>
</Grid>

The final act of the trick involves writing a bit of code-behind logic.

txtName.SelectionChanged += (sender, e) => MoveCustomCaret();
txtName.LostFocus += (sender, e) => Caret.Visibility = Visibility.Collapsed;
txtName.GotFocus += (sender, e) => Caret.Visibility = Visibility.Visible;

Where the MoveCustomCaret is defined as

private void MoveCustomCaret()
{
var caretLocation = txtName.GetRectFromCharacterIndex(txtName.CaretIndex).Location;

if (!double.IsInfinity(caretLocation.X))
{
Canvas.SetLeft(Caret, caretLocation.X);
}

if (!double.IsInfinity(caretLocation.Y))
{
Canvas.SetTop(Caret, caretLocation.Y);
}
}

And now you have your non-blinking caret in textbox ready. Here is a screenshot of the control.

sample1

If you have a better solution, please let me know. That would be interesting to learn.

Type Argument Inference during Type Initialization

One of the least discussed topics about compiler and Generic Methods is its ability to infer the Type Arguments. For example, consider the following code.

public void Display<T>(T value)
{
Console.WriteLine(value);
}

A typical invocation of the code might look like following.

var value = 45;
Display<int>(value);

However, in some scenarios as above, the compiler is smart enough to allow you to skip the type argument from the generic method. For example, you could call the method as the following.

var value = 45;
Display(value);

This is because the compiler realizes you have passed an integer value as argument and it infers the type argument T as Int32.

This is great feature to have and allows you to do away with a lot of ceremony. However, the type inference is limited to Methods and doesn’t quite help you in Type Initialization. For example,

public class MyClass<T>
{

}

For initializing the above class, you would have to explicitly mention the Type Argument.

var instance = new MyClass<int>();

However, having said that, there is a easy-to-use pattern to work around the issue. If you were to inspect the Tuple static class, you might find some interesting methods there.

For example,

public static Tuple<T1> Create<T1>(T1 item1)
{
return new Tuple<T1>(item1);
}
public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
{
return new Tuple<T1, T2>(item1, item2);
}

In the first glance, you might be temped to question the intend of the methods. What would one create a static method to create instances, when you could call the constructor directly. However, when closely examined, this is a great example of how to make type inference possible during initialization.

For example, for initializing a Tuple<int,int> using the constructor, you would have to pass the type arguments.

var instance = new Tuple<int,int>(3,4);
var instance = new Tuple(3,4); // This doesn't compile

However, the presence of static methods allows you to create the instance without passing the type arguments.

var instance = Tuple.Create(3,4);

This is a easy-to-use pattern if you ever want to support Type inference during initialization. Looking back at our sample class, we could now create helper methods as following.

public static class MyClass
{
public static MyClass<T> Create<T>(T value)
{
return new MyClass<T>();
}
}

The initialization code could now skip the type arguments, just like with the Tuples.

var instance = MyClass.Create(4);

C# over the years has reduced ceremony and boiler plate code and type inference is one yet another way to achieve the same.