I wrote a post yesterday about attaching implementation to interfaces and was asked about the best way to organize extension methods by Kevin Hazzard.
Do you recommend putting all your extension methods in a single class, a single assembly? What's the best way to manage a large number of extension methods, in your experience?
Here was my response:
I recommend treating a class full of exension methods like a helper class, since it can be used as such anyhow (e.g. I can call EnumerableClientExtensions.Save(clients, "clients.txt")). Grouping all extension methods together would lead to coincidental cohesion. Making the helper class operate solely on one piece of information will necessarily lead to a higher order of cohesion, and the goal should be functional cohesion. Therefore, I recommend grouping extension methods by the class/interface you're extending, and by the namespace.
I'm not afraid of having, say, multiple StringExtensions in a large project. Although it makes sense to be able to someString.HtmlEncode() in my web project, I certainly don't want that extension or that reference in the business layer.
I’m not sure if you caught it, but there is a bad mistake in my wording: “I'm not afraid of having, say, multiple StringExtensions in a large project.” I really should have stated solution there. This led to Francisco Velázquez to respond.
IMHO i think is better doesn´t have a common library for all projects. Although you have this centralized project. I think you should include those classes to model.
He then posted a link to Ayende’s decision to burn the Rhino Commons. I completely agree.
Before I begin this rant, I will state that I am guilty of this too. The MyProject.Common is too easy of a project to make. The problem is that it’s too easy of a project to make. If you create the Common project, you are not doing your job as a class library designer to determine where the classes belong. The Common project has the exact same problem a coincidental cohesion in that it is a dumping ground.
If a class is truly common, then it belongs in your root namespace. However, if you give me the class name, I can probably determine something about it’s functionality that indicates which namespace it really belongs in. Looking over Ayende’s list of functionality provided by the Rhino Commons, I see many things that could be commonly used throughout an organization. That’s not the problem. The problem is the disparate amount of functionality contained within that one library. If you really want to provide common functionality across your organize, properly organize it and release a framework or set of class libraries to your organization. Do not dump the classes into one project.
In a response to Ayende, Jordan Terrel writes “I would argue that Common/Utility are not dead, but rather that is something that is difficult to do well and requires practice and disciple.” I don’t think that Common/Utility libraries are dead either, just as I don’t believe Common/Utility classes are dead. They should be, but people will continue to use them. When properly designed, the classes that typically make up common and utility libraries become part of the general framework. Utility classes become more focused so that they exhibit higher cohesion, and in the .NET 3.5 era they extend the classes or interfaces to which the functionality truly belongs.