Bookmark and Share

C# Ninjitsu

by KodefuGuru 5. June 2010 18:29

C# Ninjitsu is a presentation I’ve given at conferences in cities from Cairo, Egypt to Pensacola, FL. I am providing the slide deck and the demo files I use in the presentation. These resources may not be helpful unless you’ve seen the talk, so I may post videos of each segment in the near future. Until that time, why not visit me at DevLink or another conference?

Synopsis: C# is no longer a purely object-oriented language. It is no longer just an imperative, class-based, component oriented discipline. It is also a generic, declarative, functional discipline. I will introduce new principles in the context of the classic object-oriented and SOLID principles and show you how to master the C# language to be more declarative, more fluent, and more functionally cohesive.

Download Demo Files

Bookmark and Share

A Tale of Two Principle Violations

by KodefuGuru 24. January 2010 23:57

When I decided to write the With statement in Fluent.NET, I never imagined that I would encounter a common bug and school myself in principles that I happen to present on. But that is what occurred, and I want to share it so others can avoid the same mistakes I made.

With is a Fluent version of Add, only it returns the object or interface it is acting upon rather than void. This allows you to chain methods together in a fluid manner. Instead of calling strings.Add(“Hello”); strings.Add(“World”);, you can call strings = strings.With(“Hello”).With(“World”);. Since you should write tests first, I will post my test that I expected to work.

[TestMethod]
public void With()
{
    var strings = new[] { "This", "is", "a" } .AsEnumerable();
    strings = strings.With("test");

    Assert.IsTrue(strings.Contains("test"));
}

With is cool because it even works with arrays! In fact, the point of it was that it would work with any IEnumerable<T>. Here was my initial attempt at an implementation.

public static IEnumerable<T> With<T>(this IEnumerable<T> source, T item)
{
    var collection = source as ICollection<T> ?? source.ToList();
    
    collection.Add(item);

    return collection;
}

I cast source to an ICollection<T> to get to that more specific interface. If it doesn’t implement ICollection<T> the null coalescing operator is used and source is convert to List<T>. In subsequent calls to With, source would be a List<T> so the casting would work. This violates the Liskov Substitution Principle because I’m operating on an ICollection or converting to one no matter what. I decided that I would knowingly do so because I wanted to extend IEnumerable and optimize for a type that it could convert to itself.

This code is buggy. It compiled, but my unit test failed.

Here’s another example of the same bug.

public static void AddFail(IList<string> strings)
{
    strings.Add("Fail");
}

If you haven’t figured it out, don’t feel bad. 40 people over 2 of my sessions haven’t answered it (out loud anyway) either. I’m certain I’ve seen this failure in many methods over the years as well.

The problem is that arrays implement ICollection<T> and IList<T>. However, arrays are a fixed size. Here’s the error I received when running my test: “System.NotSupportedException: Collection was of a fixed size.”

If you’re performing operations that would modify a collection, you must check the IsReadOnly property of that collection. This fixed the bug and is what I checked into CodePlex… but don’t use it, because it’s still wrong.

public static IEnumerable<T> With<T>(this IEnumerable<T> source, T item)
{
    var collection = source as ICollection<T> ?? source.ToList();

    if (collection.IsReadOnly)
    {
        collection = collection.ToList();
    }
    
    collection.Add(item);

    return collection;
}

It works like a charm, but some things were bugging me about the code. I was talking with some of the guys after the Alabama Code Camp, and I lamented that I was violating the Liskov Substition Principle. We came to the agreement that it’s okay to violate principles if you do so purposefully with full understanding of why you are doing so. But something kept nagging me after I left there and continued the 8 hour drive back home to Columbia. It was more than one principle that I was breaking.

After I spent the night at a motel and was leaving, it suddenly dawned on me that I was truly violating a functional principle from my own C# Ninjitsu talk: Avoid Side Effects. What happens if you already have a list. It’s possible to have unintentional consequences in your code.

[TestMethod]
public void WithShouldNotHaveSideEffects()
{
    var strings = new List<string> { "This", "is", "a" };
    var strings2 = strings.With("test");
    Assert.IsTrue(strings2.Contains("test"));
    Assert.IsFalse(strings.Contains("test"));
}

This test fails because it’s not expected that the original sequence will be modified. It certainly isn’t modified when an array is passed in, why should it work any different with a list?

I knew I was in violation of two different principles: one agile, one functional. The code had to be refactored, so I started thinking about where I went wrong. I decided it wasn’t being enough like LINQ. There is a design guideline, and I’m not sure if it’s written down anywhere: if you return an IEnumerable<T>, Consider Yield. I thought about how I would solve the same problem using yield, and it turn out to be quite simple.

public static IEnumerable<T> With<T>(this IEnumerable<T> source, T item)
{
    foreach (T t in source)
    {
        yield return t;
    }

    yield return item;
}
I’m amazed that I found one common bug and violated two design principles in what started as a three line method. It is rather embarrassing, but I hope by sharing this that you will avoid this bug and apply the Liskov Substitution Principle and Avoid Side Effects in your own code.
Bookmark and Share

Coincidental Cohesion

by KodefuGuru 5. October 2009 18:19

In response to my post, Strive for Functional Cohesion, VisualKnight wrote the following:

We noramally [sic] most functional methods to the domain object class in this case your Address class. However, if the method is more general in nature I would add it to an Utility class so other team developers can find it easier. We have an Utility class that is available in both the web and app side.

Let me start off by saying that I am guilty of using the utility class at least as far back as when I programmed in Delphi. The reason I did so was quite simple: I came from a Turbo Pascal background, and many of my development practices had evolved from procedural programming. As I learned object oriented patterns and practices, the utility class was lost from my tool belt as a relic from ages past. However, I am glad VisualKnight brings it up, because the utility class is an excellent example of coincidental cohesion!

Coincidental cohesion is the lowest form of cohesion found in object oriented software development. Methods within a class that has coincidental cohesion will appear to have been placed there randomly or without consideration of the proper concern of the method. This type of class necessarily leads to tight coupling as its varied functionality is used in a myriad of places.

A utility class is a perfect example of coincidental cohesion. Do not confuse this class with the so-called “utility pattern” (which is just a static class in c#). It is true that static classes are often called helper classes, and those are also often called utility classes, but this is just a creational pattern. Many static classes have higher orders of cohesion than coincidental.

For a quick example of coincidental cohesion, let’s take a look at the C# example of the Utility pattern on Wikipedia.

// The utility class
public static class Utils
{
    /// <summary>
    /// A utility method that helps out with error logging.
    /// </summary>
    public static void LogError(String msg)
    {
        MyLogger logger = new MyLogger();  // Create instance of logger class
        logger.LogIt(msg);
    }

    /// <summary>
    /// A utility method that displays a message to the user.
    /// </summary>
    public static void ShowMsg(String msg)
    {
        MessageBox.Show(msg);
    }
}

This static class only contains two methods, but they have no relationship to each other. Now, any class that wants to log errors will need to use the Utils class, and any class that needs to show messages will need to use the Utils class. The Utils class does not have a clear concern defined within the system; it is a garbage heap on which to throw methods.

If you have a need to use static methods, you should at the very least group them logically. But I do stand by my principle of Strive for Function Cohesion. There should never be a Utility class which is used as a general bucket. Every method in your system means something, it belongs somewhere. If you’re having trouble deciding where it belongs, it may need to be broken down to operate on smaller components within the system. The one caveat to that is that orchestration may operate on multiple objects, but they generally belong in workflow anyway.

If you disagree and want to make a case for the Utility class, leave a comment. Be sure to back it up with a sample method and ask me how I would organize it.

Bookmark and Share

Presenting at Raleigh Code Camp

by KodefuGuru 15. November 2008 10:19
I am speaking at the Raleigh Code Camp during the lunch session. I was told it would be made into a webcast for INETA. If that's the case, I'll post a link up to it when I receive it. The topic is Design Principles, and the slide deck is available.

KodefuGuru.GetInfo()

Chris Eargle
LinkedIn Twitter Technorati Facebook

Chris Eargle
C# MVP, INETA Community Champion


MVP - Visual C#

 

INETA Community Champions
Friend of RedGate
Telerik .NET Ninja
Community blogs & blog posts

I am a #52er

I have joined Anti-IF Campaign


World Map

Tag cloud

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010