C# Design Guidelines

Principles 


Prefer explicit declarations to implicit declarations.  If you’re expecting something from a declaration, explicitly state it.


Never depend on implicit side-effects.


Never design cyclic dependancies, always design ascyclic dependancies.


Prefer readability over complexity.


Never optimize


Always prefer the


Prefer always implementing an empty constructor instead of no public constructor.


There is a side-effect to not implementing any constructors: you get a public general constructor for free.  The drawback to that is if you add a non-general constructor your interface changes.  If something is already constructing your class that will introduce a compile error.


Prefer internal on class declarations rather than no access.


Prefer public on member declarations rather than on access.


Prefer sealed on class declarations unless the class is designed to be derived from.

System.Collections classes are obsolete

Collection classes like ArrayList, SortedList, Stack and Hashtable will shortly be obsoleted (i.e. the ObsoleteAttribute will be applied to them in upcoming .NET Framework builds).  You can start to see this in the Silverlight Alpha (i.e. the Obsolete attribute), but they will be physically unavailable in the release version.


More details can be found in a recent Base Class Library Team blog entry Non-Generic Collections to be Removed from Silverlight.


Even if you don’t plan on writing Silverlight-compatible code you should avoid using the types detailed in the BCL Teams blog because they’ll be obsolete in other future versions of the .NET Framework.

Performance Implications of try/catch/finally

The accepted wisdom regarding performance of try/catch|finally in C# has normally been: try has no performance side-effects unless an exception is thrown.

A discussion I was involved in recently caused me to discover some performance implications of try/catch blocks. The discussion revolved around protecting the volatility of certain members and the cross-thread memory ordering rules during run-time and during just-in-time compilation.  As it turns out, Microsoft’s x86 .NET 2.0 just-in-time compiler disables optimizations that would affect the CIL order of read/writes in protected blocks (AKA “protected regions”, “guarded blocks”, or “try blocks”).  As a result no optimizations are performed in try blocks.

As it turns out, there are performance side-effects to try/catch even if no exceptions are thrown.  In the following academic example:

    int count = 1;
    SomeMethod();
    count++;
    SomeOtherMethod();
    count++;
    Console.WriteLine(count);

The x86 just-in-time compiler will effectively optimize this as follows:

    SomeMethod();
    SomeOtherMethod();
    Console.WriteLine(3);

The end-result is the same but the side-effects (that would normally be only visible in a debugger) are different (e.g. count never has the value 2).  The just-in-time compiler can do this because it knows no other code can see count when it has the value 2.


Now, wrapping this in a try block, as follows:

    int count = 1;
    try
    {
        SomeMethod();
        count++;
        SomeOtherMethod();
        count++;
    }
    finally
    {
        Console.WriteLine(count);
    }

…is not optimized.  count will be created, it will have the value 1, it will have the value 2 after the call to SomeMethod, it will have the value 3 after SomeOther method, and will have the value 3 when Console.WriteLine is called.  There are two increments that therefore must be performed that are a waste of cycles.


So, be careful how you write code in try blocks.

The Religion of Class Member Prefixing

The periodic identifier naming/prefixing/Hungarian-notation religious discussion reared its head recently on Eric Gunnerson’s blog


This particular discussion revolves around the Microsoft-based guideline/anti-guidance of prefixing class member names with “m_” to denote that they are members.  I’ve contributed to many of these discussions over the years and thought it about time to encapsulate my separate remarks to which I and others can refer to.


For the most part I accept this habit with my programmers for a variety of reasons: isn’t guaranteed to do any harm, it’s habit, refactoring tools make it easy to remove “m_”, etc.


When I switched from C++ to C#, I too brought along the “m_” prefix baggage where members can’t be scoped by “this” everywhere (see intializer lists).  I quickly realized it was unnecessary in C#, and haven’t turned back.


Kent Beck’s and Martin Fowler’s Refactoring principles brought us the concept of “Code Smell”.  Code smells are hints (I’m a pragmatist) that something might be wrong with code.  “m_” to me is a bad smell.


When I ask a programmer why “m_” is used the practical answer is invariably “well, the code is too hard to understand without it” (the non-practical answers are usually “Because of the coding guidelines”, or “It’s just habit”, but those don’t answer the “But, why?”).  And this, to me, is a bad code smell.


How complex does a class need to be in order for “m_” to make a difference?  Clearly too complex.  Is the class cohesive?  Does the class and it’s methods follow generally accepted cohesiveness design principles like Law of Demeter or Single Responsibility Principle?  Is the class in inappropriately coupled to other classes?  Have the meaningful-names guidelines been followed?  I’ve never seen a class implementation where a member needed to be so complex (without violating one of the previously mentioned principles) to warrant the need for “m_”.  Occasionally the need to scope a member with “this.” is required; but that’s usually very infrequent, much less frequent than having to type “m_” on every member.


If a class is simple, why should complexity idioms be forced upon it?  “m_” only works if you use it everywhere; if you don’t use it in some places it makes it pointless.  If I’m not sure the programmer just didn’t forget “m_”, and I still have to refer to the class–the task that “m_” is supposed to ensure isn’t needed.  Similar in principle to using const-correctness, something missing from C# programming for the lack of enforcing it consistently.


The topic of consistency is one of the main reasons why I’m not a proponent of “m_”.  There’s no way to enforce use of “m_”, which leaves it up to the programmer.  I’ve dealt with thousands of lines of code from hundreds of other programmers, more often than not inconsistent use of “m_” actually cuased “m_” to make the code much harder to read.  Even the birthplace of “m_” has inconsistent usage of the idiom.  Abram’s and Cwalina’s Framework Design Guidelines (the tome by which all Microsoft code is supposed to abide), as enforced by FxCop and Code Analysis (CA), suggests not using underscore or prefixes (other than “I” for interfaces); yet Eric is a proponent of “m_”.  Much code that comes out of Microsoft (including the .NET Framework) occasionally uses “m_”, often inconsistently.  Using “m_” can cause as many as 4 CA different warnings if the complex rules of “m_” are not followed.  Porting code is a great source for that.


I call it a religious discussion because those who religiously follow the “m_” habit will not be swayed by logic or reason and invariably counter with some edge/corner case that could have made “m_” equally as useful as “this.”, or some logical fallacy, or an appeal to authority they’ve convinced themselves proves their case.


“m_” is less typing than “this.” is a great logical fallacy.  This is a fallacy because it’s only true in that sentence.  Yes, if you have to type “m_” once instead of typing “this.” once, you’ve saved 3 keystrokes (at my typing speed that works out to saving about 300ms).  With the “m_” prefix, that’s now part of the name of the identifier, you must type it every time you type the name of that identifier.  With “this.”, its necessity is based on context, or scope, so its use is optional in most cases and mandatory in some (backed-up with a compiler error, to which you should all agree compile-time checks should be used whenever possible).  An identifier’s un-obviousness of being a member doesn’t occur with every instance of it.  With an effective IDE it can infer the context in which you are typing and suggest what you’re likely typing (Intellisense in Visual Studio).  When using the “m_” prefix you must type at least 3 characters for every single private member of a class  (assuming that’s the guideline) for the suggested completion to be useful.  In cases where “this.” isn’t necessary, you only need to type one character for it to be equally useful.  If you took the average class and analyzed how many keystrokes would be required for “m_” compared to no prefix and “this.” when needed, you’d find that using “m_” is actually more typing.  Ironically, any time that could have been saved using or not using “m_” has been far less than the time spent discussing it.


Other reasons why “m_” isn’t a solution every time it’s used:


  • It’s English-centric.  As such, it becomes more and more arbitrary with speakers of other languages.
  • It’s typically C++-based.  VB programmers have a whole different set of prefixing rules.
  • It’s usage ends up being very contextual.  In C++ “m_” could be mandated all member fields, in C# it could be mandated on only private instance members that aren’t const (and I’ve never seen a clear description of the mandate for example Juval Lowy’s IDesign C# Coding standard is seeminly contradictory: “Use Pascal Case for … constants” providing a example of a private member const named DefaultSize and “prefix private member variables with m_“. 
    Yes, it’s clear that DefaultSize is not variable in nature but the junior programmers to which these guidelines are directed usually don’t pick up on that nuance).

Some discussions on the topic often sway between the “m_” prefix and just an underscore (“_”) prefix.  Some argue that “m_” stands out more than “_”.  Another great logical fallacy because a “Member” suffix should be preferred because it stands out even more.


Regardless of whether prefixing is used, most guidelines mandate that identifiers have meaningful names.  If meaningful names are used, it’s highly unlikely that it will be unclear in the code that a particular identifier is or is not a member of the class.  More meaningful names help in more areas that just distinquishing members from non-members.


For me, my general idioms are: use meaningful identifier names, prefer suffixes to prefixes, don’t use underscores, use Camel Case for field members, and Pascal Case for non-field members (methods, types, constants, namespaces, etc.).  Easy to understand, easy to follow, easy to qualify and enforce…

Software Design Priniples and Terminology

Principles 


  • Single Responsibility Principle An entity should have one, and only one, responsibility.
  • Agile Software Development A methodology that espouses producing software by iteratively publishing subsets of functionality in working deliverables, acceptance of change throughout the development life-cycle, personal interaction with team members and stakeholders, and implements continuous improvement.
  • Interface-oriented Design
  • Object-oriented Design
  • Aspect-oriented Design
  • Law of Demeter A principle that improves quality by reducing coupling and increasing cohesiveness by mandating that the body of a method should only access argurments and their direct members, local variables and their direct members, and members of the containing class.  Sometimes referred to “only talk to your friends”.

Terminology


  • Cohesion, cohesiveness
  • Coupling
  • Concern, concerns
  • Aspect, aspects
  • Cyclomatic Complexity A means by judging complexity of a method, class, module, or system by counting the number of conditional statements.
  • Lack of Cohesion of Methods
  • Coupling Between Objects
  • Abstraction, Data Abastraction
  • Polymorphism A concept of OO
  • Inheritance A concept of OO
  • Encapsulation A concept of OO
  • Modularity A concept of OO
  • Class  A concept of OO
  • Object  A concept of OO
  • Method  A concept of OO
  • Message Passing A concept of OO
  • Information Hiding A generalization
  • Code Smell
  • Duck Typing A means of matching a class interface, a method interface, or property interface based upon it’s signature not by its inheritance.  e.g. Rather than requiring a type to implement an interface with a known method, duck typing to simply check the object for a method that matches and executes it.
  • Critical Region a.k.a. mutex, binary semaphore.
  • Counting Semaphore A semaphore whose count is more than 1.
  • Binary Semaphore A semaphore whose count is 1, so possible values are 0 and 1: binary.
  • Explict Threading Threading by explicictly creating threads.  See Windows Threading, Joe Duffy
  • Opqaue Value
  • Quantum
  •  

DateTime.ToUniversalTime *Should* Throw Exceptinos.

A recent .NET Base Class Library blog post points out that DateTime.ToUniversalTime does not throw an exception for overflow values.


This circumvents different Microsoft-sanctioned guidelines about using exceptions for exceptional situations, error reporting guidelines, not using return codes to communicate errors (which essentially what this is), the Method/TryMethod pattern, allowing the error to propagate to a level that knows how to deal with it, etc.


I would recommend having overflows handled as exceptions and the addition of a TryToUniversalTime.  If the Method/TryMethod pattern is the favoured approach to providing two methods that result in the same thing–one without exceptions–this is impossible if the Method doesn’t throw exceptions.  i.e. you can’t use Method/TryMethod pattern and therefore if you provided another method to convert to universal time that did throw exceptions, you’d be forced to implement a completely different pattern.


The argument will be that ToUniversalTime can’t change because there’s code that assumes it doesn’t throw an exception.  I would argue that this isn’t a realistic case and that code that uses ToUniversalTime simply does no error checking because it can’t: MinValue and MaxValue are valid values you can’t use them to decide whether an error has occurred. 


The argument to not change a defective method because something may depend on that defect is just wrong and is used too much as a crutch to avoid not having to deal with redesigning a proper method and dealing with the consequences.


This would apply equally to TimeZone.ToUniversalTime.