I love FxCop. I really do. But I find it very disheartening that most developers don't use it. Heck, there's plenty that have never even heard of it. It does an amazing job of performing static code analysis on .NET assemblies, which helps keep your overall design in check.
Of its many rules, FxCop has a rule named DoNotExposeGenericLists, which is described as:
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.
David Kean from the MS Code Analysis team does a good job of expanding on why that rule is in place. His post provides a good example that hopefully drives the point home. Take a second to read it.
But my point is that I find it very frustrating to run FxCop on an assembly only to find that it raises tons of issues specific to this rule. My take on the reasons for this are either:
- The developer doesn't know FxCop exists OR
- The developer knows of FxCop but doesn't use it OR
- The developer uses it but ignores the rule OR
- The developer uses it but turns that rule off OR
- The developer uses it but never bothers to check why the issue is raised
I can't do much about #1. Someone doesn't know what they don't know. All I can try to do is expose developers to the tool and hope they see its benefit. #2 I attribute to laziness. If a developer knows about FxCop and understands its benefits, the only reason I can think of for *not running it* is laziness. My guess is that it's because more than likely FxCop is going to expose issues that a developer doesn't want to take the time to address or just plain doesn't want to know about in the first place. And that's just sad.
For #3, #4, and #5, which are basically the same thing, I believe it's a bit of laziness mixed with personal preference for how code is written. For example, look at these two method signatures:
public List<Customer> GetCustomersByState(string stateAbbreviation)
public Collection<Customer> GetCustomersByState(string stateAbbreviation)
Now look at these two snippets:
List<Customer> customers = new List<Customer>();
Collection<Customer> customers = new Collection<Customer>();
The difference is that using List<Customer> is *shorter* than using Collection<Customer>, thus giving the perception that code with List<T> is more concise. Also, with List<T> there are less characters to type, which is silly considering if you start typing Collection<T> Intellisense kicks in about the time you get to "Co". So I don't buy the "I have to type less" argument.
I also think there might be one other reason developers default to use List<T> instead of Collection<T>: it lives in the System.Collections.Generic namespace, which is where most developers look when dealing with generics. However, Collection<T> lives in the System.Collections.ObjectModel namespace, which frankly many developers don't know exist.
There are times when using List<T> makes sense, such as when you want an easy way to invoke Sort or Find. But those are going to be used as part of logic *inside* a method, which does satisfy the rule:
List<T> is meant to be used from implementation, not in object model API.
So let's try and get better at this going forward by not only using FxCop, but taking the time to actually understand what it's trying to tell us. Our code will be better off for it.
Print | posted on Wednesday, January 09, 2008 12:47 AM