Adding Implementation to Interfaces with Extension Methods

by jmorris 21. January 2011 22:58

One of the quirks of extension methods added to the .NET 3.5 release is that you can add them to interfaces;  seemingly adding implementation to interfaces. By definition, in the CLR (and most other languages or platforms) interfaces contain only the signatures of methods, delegates, properties or indexers. By implementing an interface in a class, the body of the method, delegate, property or indexer is added…the implementation is added.

For example:

image

Here I am extending the IMessage interface with a couple of methods for simplifying access to value pairs contained within a IPrimitiveMap (a hash map implementation).  A couple of unit tests illustrates the usage:

image

Truthfully, you are truly adding nothing the interface! No implementation is actually added…basically a static class is created with the extension methods and some compile time kung fu enables you to invoke the method off of the interface definition. Extension methods are not of the domain of the CLR, they are of the domain of the compiler via the System.Runtime.CompilerServices.ExtensionAttribute.

I would imagine this is old news for most seasoned .NET developers, but I just kind of stumbled upon it myself today and thought it was interesting with respect to interfaces and implementation :)

Tags: ,

C#

The Dilemma's of a Developer

by jmorris 12. January 2011 01:43

I ran across this today while refactoring/reviewing some code:

image

What in the heck I am I supposed to do with this? Delete it? Refactor it? Quickly close the file and pretend I never saw it? Mind you that it’s in code that’s in production and get’s run several times a day…and the code works as expected.

I chose to refactor it:

image

Unit tests pass:

image

Hold your breath!

Tags: , , , ,

Refactoring

.NET Framework 4 Client Profile: The Devil Itself!

by jmorris 7. January 2011 02:16

I am convinced that Microsoft’s decision to set the build profile of projects created with the Console Application template to “.NET 4 Client Profile” is a work of the devil itself! Why you might ask? Because it is set to this profile by default and because it will cause projects that should rightfully compile to fail, without an adequate explanation of why!

The reason this happens is because VS 2010 will allow you to reference projects and/or DLLs compiled under the “.NET 4 Framework” target, which may contain references to resources excluded by the “.NET 4 Client Profile” without complaining or warning the user. What a horrible, frustrating “feature”…

Here is a formal description from MSDN:

“The .NET Framework 4 Client Profile is a subset of the .NET Framework 4 that is optimized for client applications. It provides functionality for most client applications, including Windows Presentation Foundation (WPF), Windows Forms, Windows Communication Foundation (WCF), and ClickOnce features. This enables faster deployment and a smaller install package for applications that target the .NET Framework 4 Client Profile.”MSDN

Here is an example of a compile time error caused by this:

image 

The weird, confusing part is that while typing in the using statement for the namespace, intellisense will show you the namespaces and the object viewer will confirm that they exist. However, when you go to compile it will fail! Very frustrating!!!

This fix is very easy, simply right click on the project and select properties and then in the “Target Framework” dropdown, select “.NET 4 Framework” and your good to go. I am hoping that this will be fixed or changed in VS2010 SP1 that should be released soon.

Tags: , , , ,

rant | Visual Studio

OOP 101 – Understanding SOLID

by jmorris 5. January 2011 22:14

Background

SOLID is an acronym for several specific traits that are consistently found in well written, reusable, and extendable software. Specifically, there are five principals to follow when constructing object orientated systems: SRP, OCP, LSP, ISP, and DIP.

SRP– Single Responsibility Principle

SRP relates to class cohesion. In essence a class should have no more than one reason to change. A class violating this principle is likely doing too much and thus lacking cohesion. Classes that lack cohesion are brittle and difficult to maintain.

For example, here is a class does more than one thing or in other words has more than one purpose or responsibility:

image

In this case we have a class that mixes both database activities (responsibility #1) and the abstraction of the real world entity that the class represents (responsibility #2). Classes like this can be refactored into more cohesive pieces by using a well defined pattern such as Data Transfer Objects and Data Access Objects (DTO/DAO):

image

By separating the purpose into separate classes, it becomes clearer what the intended purpose of each class is, increases maintainability and promotes code reuse.

OCP – Open/Closed Principle

The OCP principle states that objects (and other software artifacts) should be open for extension, but closed for modification. What this means is that you should be able to extend a classes behavior without modifying it internally and potentially breaking any other usages or users of the class or artifact.

The OCP principle is typically enforced via inheritance and abstract or virtual classes and methods. Re-using our example we introduced in SRP let’s make up the following scenario: assume that we not only want to persist our objects to the database, but we also want to now persist the XML representation of the file to disk. We could chose to modify the existing PersonDAO class by adding a new methods for writing the xml to disk, reading the xml off disk and deleting the file from disk :

image

This of course would/could potentially break any clients using the DAO. A better way to accomplish this is to create a base class or interface that provides the signatures of the methods and/or a base implementation and then have specific derived classes provide specific implementations:

image 

In nutshell, OCP deals with increasing the maintainability and reusability of code, which is achieved by extending existing code by introducing new subtypes as opposed to modifying older already working code when new behavior or features are required.

LSP – Liskov Substitution Principle

LSP is another principle related to class structure and states that any derived classes must be substitutable for their base classes.  What this means is that the base class must be able to use references of derived classes, without knowing that it is. Like OCP is closely related to inheritance and polymorphism and mutability of the objects state leading to a violation of one the classes invariants.

The classic example is as follows: a square that derives from a rectangle with getter and setter methods or properties for height and width. Because the height and width can be changed independently, it’s possible to violate the fact that a square has sides of equal length.

image

Can violate the LSP easily:

image 

However, by refactoring the class to ensure that each property is not modified independently, we can preserve the class invariant (a square is a rectangle with equal sides):

image

image

LSP defines a several behavioral conditions that subtypes must adhere to, namely:

  • Invariants of the base types must be preserved in subtypes
  • Post conditions cannot be weakened in a subtype
  • Pre conditions cannot be strengthened by a subtype

ISP – Interface Segregation Principle

ISP largely relates to class cohesiveness. Classes with high cohesion tend to do less, but do it much better and easier to reuse and maintain. Classes with low cohesiveness will tend to lots of things resulting in unwarranted dependencies, which reduce maintainability,  reliability, testability, and understandability.

Historically ISP has dealt with the of “fat interfaces” leading to “fat classes” that are not very cohesive. “Fat interfaces” is a term for interfaces with many methods that can and should be broken into smaller, more fine grained interfaces. In situations where “fat interfaces” are required, abstract base classes that implement the more cohesive fines grained interfaces should be used. The major theme here is that clients should not be required to depend upon interfaces that they do not need [Uncle Bob].

For an example of an ISP violation, we do not have to look far in the .NET world (note that this is my opinion and my opinion only) to find one: System.Xml.Serialization.IXmlSerializable. For those not familiar with this interface it provides a means of implementing  custom XML serialization. It’s a very simple interface in that it only provides three method signatures to implement: ReadXml, WriteXml, and GetSchema.

image

It’s also very useful, in that the .NET framework provides a corresponding class for serializing and de-serializing objects marked with the IXmlSerializable interface: XmlSerializer. However, what happens if you only need serialization or de-serialization and not both? What if schema validation is an overkill, and is in fact a reserved method that should not be used? You end up with GetSchema and either ReadXml or WriteXml throwing a NotImplementedException!

image

The ISP violation in the Person class can be refactored by providing an abstract class that implements IXmlSerializable and then choosing the methods you wish and then overriding the methods you wish to implement.

image

Now, you are no longer forcing clients to implement parts of the interface that are not of concern to them.

DIP – Dependency Inversion Principle

DIP is concerned with the structural relationship between classes and the effect that dependencies have on the quality and maintainability of software. Formally, it is the concept that you should depend upon abstractions and not upon concretions [wiki]. DIP is associated with Dependency Injection (DI) and the Invocation of Control (IoC) containers that are commonly used as means of abstracting the construction of objects from their use. It’s sounds confusing, but it’s really not.

The two major tenets of DIP are as follows:

  1. High level models should not depend upon low level modules; both should depend upon abstractions
  2. Abstractions should not depend upon details; details should depend upon abstractions

What this means is that systems should be comprised of a series of layers, from the abstract and generic to the concrete and specific.  Changes in lower level modules should not effect or cause higher level modules to change; the opposite should be true. The references that are used should be made by using abstract class or interfaces and not concrete representations.

Here is an example of a DIP violation:

image

Note that the PersonDAO class depends upon the concrete SqlConnection implementation. Now this is fine and dandy if you are working in environment where you are always using a SQL Server specific provider, however what happens if you want reuse this code in an environment that is using a MySql provider? In that case, you really can’t without adding some horrible dependencies.

Here is a better example of the same code refactored so that it uses the abstraction (DbConnection) instead of a concrete representation (SqlConnection):

image

Notice that the refactored object model is using two forms of Dependency Injection: constructor injection and method injection.

image

Dependency Injection provides a means of injecting dependencies into an object as opposed to hard coding the dependencies within  the object itself. Classes designed in this matter lend themselves to both unit testing via mocking or stubbing and construction by way of IoC containers.

References

Tags: , , , , , , ,

Patterns

Jeff Morris

Tag cloud

Month List

Page List