Bookmark and Share

Death to the Common Namespace

by KodefuGuru 6. December 2009 18:02

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.

Bookmark and Share

One Public Type Per File

by KodefuGuru 30. June 2009 17:52

I remember when I started working on this particular project a few months ago. When I looked over the code for the first time, I noticed something funny about the cs files. Each cs file contained multiple public types. In the extreme cases, there were dozens of public classes in one file.

I brought it up with my new teammates, and one person claimed that he liked to keep related classes in a single file. I mentioned that I find it more difficult to find what I’m looking for in the solution tree, but he shrugged it off by suggesting I use the search feature.

Having never seen this type of code structure before, and with the knowledge that you group related classes by namespace, I decided to research why I felt so strongly that public types deserve their own file. I referred to the Framework Design Guidelines book by Krysztof Kwalina and Brad Abrahams (which is a great reference, btw). The first rule under A.4 File Organization is “DO NOT have more than one public type in a source file.” It then lists a few exceptions (number of generic parameters, nested, etc.).

Today I received yet another reminder of why this type of file structure is bad. I pulled down the latest code, then I retrieved a shelveset I was working on last week. I knew I might have to merge a few files, but I didn’t expect this.

DefinedMoreThanOnce

Ignoring the misspelled class name, someone had moved the type from a file I was working on to another. This kind of silliness wouldn’t happen if the class had its own file. I wasn’t even working on that particular class. As it turned out, the class in question was used by a few xaml pages, and a developer thought it fit better with a different xaml page than its original home.

My rule is one public type per file, using namespaces and project folders to group related types. This reduces the amount of potential editing conflicts and makes it easier to find the type in the Solution Explorer. If you have types with the same name but a different number of generic parameters, name the file by the class name with `(# generic parameters) at the end. For example, List<T> would be List`1.cs.

Tags:

Kodefu

Bookmark and Share

Exposing a Generic List

by KodefuGuru 30. September 2008 18:35

You're writing a Customer class, and the Customer class contains a collection of Account objects. Because you want to add and remove accounts with ease, you implement this collection as a List<T>.

    public class Customer
    {
        
private List<Account> accounts = new List<Account>();

        
public List<Account> Accounts
        {
            
get { return accounts; }
        }
    }

Life is good. Your tests iterate through the accounts, add new accounts, and remove accounts. However, when you run FxCop, it complains that you shouldn't expose generic lists.

Do not expose List<T> in object models. Use Collection<T>, ReadOnlyCollection<T> or KeyedCollection<K,V> instead. List<T> is meant to be used from implementation, not in object model API. List<T> is optimized for performance at the cost of long term versioning. For example, if you return List<T> to the client code, you will not ever be able to receive notifications when client code modifies the collection.

FxCop is correct in its assessment as it becomes more difficult to later add underlying functionality. But I feel that it leaves out an important point. You shouldn't expose too much about your implementation, and this relays to the world that Customer uses a List<T>. Consumers of the Employee class don't care that you've implemented List<T>, they only care about the interface. Expose the public property as the interface the consumer should be using. In this example, our consumers want to utilize the interface IList<T>. Refactoring this is pretty easy: modify the property to be IList<Account>.

    public class Customer
    {
        
private List<Account> accounts = new List<Account>();

        
public IList<Account> Accounts
        {
            
get { return accounts; }
        }
    }

In other cases, the consumers may only want to iterate the collection without making modifications. In that situation, expose the list as IEnumerable<T>. The point is to take into account the interface that consumers want to utilize, then hide your implementation.

You shouldn't do it this way if the collection needs to be serialized. In that case, stick with one of the concrete classes such as Collection<T> like FxCop suggested.

Bookmark and Share

Usability Nightmares

by KodefuGuru 2. October 2007 19:29

Smashing Magazine has a great article called 10 Usability Nightmares You Should Be Aware Of.

The author goes over ten design faux pas you should avoid when designing your website. Many of them are horrible, yet I know I come across them all the time.

  1. Hidden log-in link.
  2. Pop-ups for content presentation.
  3. Dragging instead of vertical navigation.
  4. Invisible links.
  5. Visual noise.
  6. Dead end.
  7. Content blocks layering upon each other.
  8. Dynamic navigation.
  9. Drop-Down Menus.
  10. Blinking images.

There is a list of things you should do at the end of the article:

  1. You don’t use pop-ups.
  2. You don’t change users’ window size.
  3. You don’t use too small font sizes.
  4. You don’t have unclear link text.
  5. You don’t have dead links.
  6. You have at most one animation per page.
  7. You make it easy to contact you.
  8. Your links open in the same window.

I disagree with the last one. I think it is perfectly okay to open external links in a new window, although I would agree with that point for internal links. In the era of tabbed browsing, using new windows (tabs) for external links makes it easier for users to return to the site at the point they were reading.

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