Explained: A class or interface should have a single purpose

Aviva C# Coding Guidelines is an awesome reference for best practices while coding in C#.

In this blog we will study a sample of how to and not to write coding conforming to the rule – A class or interface should have a single purpose.

By definition, rule AV1000 says,

A class or interface should have a single purpose within the system it participates in. In general, a class is either representing a primitive type like an email or ISBN number, an abstraction of some business concept, a plain data structure or responsible for orchestrating the interaction between other classes. It is never a combination of those. This rule is widely known as the Single Responsibility Principle, one of the SOLID principles.
Tip A class with the word And in it is an obvious violation of this rule.
Tip Use Design Patterns to communicate the intent of a class. If you can’t assign a single design pattern to a class, chances are that it is doing more than one thing.
Note If you create a class representing a primitive type you can greatly simplify it usage by making it immutable.

Sample of how to mix purposes in a single class

public class Shape
{
   public int GetAreaForRectangle(int length, int height)
   {
      return length * height;
   }
   public int GetAreaForCircle(int radius)
   {
      return 3.14 * (radius * radius);
    }
    public int GetAreaForSquare(int side)
   {
      return side * side;
    }
}

Sample of how to have single purpose classes for the same functionality

public interface IShape
{
      int CalculateArea();
}
public class Rectangle: IShape
{
   private int length;
   private int height;
   public Rectangle(int length, int height)
   {
      this.length = length;
      this.height = height;
   }
   public int CalculateArea()
   {
      return length * height;
   }
}
public class Circle: IShape
{
   private int pie;
   private int radius;
   public Rectangle(int radius)
   {
      this.radius = radius;
   }
   public int CalculateArea()
   {
      return pie * radius;
   }
}
public class Square: IShape
{
   private int side;
   public Rectangle(int side)
   {
      this.side = side;
   }
   public int CalculateArea()
   {
      return side * side;
   }
}
Advertisements

Why FxCop is right – Enums should have zero value

Per FxCop – CA1008: Enums should have zero value

I ran a quick check on http://msdn.microsoft.com/en-us/library/ms182149.aspx.

An excerpt below:

The default value of an un-initialized enumeration, like other value types, is zero. An enumeration should define a member with the value of zero so that the default value is a valid value of the enumeration. If appropriate, name the member ‘None’. Otherwise, assign zero to the most commonly used member. Note that if the value of the first enumeration member is not set in the declaration, its value is zero by default.

Is it really worthwhile? I ran a quick check with the code below:

public enum TraceLevel
{
    Off = 0,
    Error = 1,
    Warning = 2,
    Info = 3,
    Verbose = 4
}

class Program
{
    static void Main(string[] args)
    {
        TraceLevel traceLevelOptions;
        Console.WriteLine(traceLevelOptions.ToString());
        Console.ReadLine();
    }
}

I thought FxCop missed something because I always got a compiler error when trying to use the default value of the enum without explicitly setting it to something first.

I couldn’t believe that FxCop could have a redundant rule. I quickly posted a question on Stackoverflow. Thanks to a quick response, I got the following answer to my question:

For example, you declare an enum field in a class or struct and do not initialize it, it will have the default value of zero. If there is no member of the enum with a zero value, you will in that (fairly common) situation have a enum field containing an invalid value.

There are also other instances where you can end up with a default-initialized enum field (e.g. during deserialization). You want to avoid a default-initialized enum field having an invalid value, hence the rule.

I then ran the following code and found it was indeed correct!

public class SerializeMe
{
    public int Id { get; set; }
    public TraceLevel MyTrace { get; set; }
}

public enum TraceLevel
{
    Off = 0,
    Error = 1,
    Warning = 2,
    Info = 3,
    Verbose = 4
}

class Program
{
    static void Main(string[] args)
    {
        SerializeMe serializeMe = new SerializeMe();
        Console.WriteLine(serializeMe.MyTrace.ToString());
        Console.ReadLine();
    }
}

Conclusion

If your enum does not have a zero value and you are not explicitly setting it to a specific value in your classes, using those classes for deserialization / serialization or json conversion or just accessing the property can lead to invalid values being used or accessed.