Wednesday, October 24, 2007

Design by contract

Something that was bothering me for a while now was writing the following piece of code over and over again:

public void DoSomething(Request request) { if(null == request) { throw new ArgumentNullException("request"); } }

Last week, I decided to do something about it. In a previous post, I mentioned the concept of a fluent interface. So, I tried using it while finding a solution for writing this kind of boilerplate code. While I was half way through, I found this post from Sean Chambers (via DotNetKicks) that describes (almost) the same solution as I was developing using fluent interfaces. Although he beat me to it, his post confirmed that I was on the right track. Here goes ...  

Instead of writing the code above, I can now write this:

public void DoSomething(Request request) { // Throws ArgumentNullException Check.Argument(request, "request").IsNotNull(); }

I also created a couple of other checks:

Strings

public void DoSomethingElse(String request) { // Throws ArgumentException Check.Argument(emptyString, "request") .IsNotNullAndNotEmpty(); }

or

public void DoSomethingElse(String request) { // Throws ArgumentException Check.Argument(emptyString, "request") .IsNotNullAndNotEmptyAndNotWhiteSpace(); }

Collections

public void DoSomethingElse(ICollection requests) { // Throws ArgumentException Check.Argument(requests as ICollection, "requests") .IsNotNullAndNotEmpty(); }

or

public void DoSomethingElse(ICollection<String> requests) { // Throws ArgumentException Check.Argument(requests as ICollection<String>, "requests") .IsNotNullAndNotEmpty(); }

Enums

public void DoSomethingMore(DayOfWeek dayOfWeek) { // Throws InvalidEnumArgumentException Check.Argument(dayOfWeek as Enum, "dayOfWeek") .IsValidEnumValue(); }

Value types

public void DoSomethingMeaningfull(Int32 someNumber) { // Throws ArgumentOutOfRangeException Check.Argument(someNumber, "someNumber").IsNotNegative(); }

or

public void DoSomethingMeaningfull(Int32 someNumber) { // Throws ArgumentOutOfRangeException Check.Argument(someNumber, "someNumber").IsNotPositive(); }

or

public void DoSomethingMeaningfull(Int32 someNumber) { // Throws ArgumentOutOfRangeException Check.Argument(someNumber, "someNumber").IsNotZero(); }

You can download the code here. Please let me know what you think. I would love to hear your feedback. It's the only way I will ever learn how to become good programmer.

No comments: