Friday, August 25, 2006

Attribute Design

Krzysztof Cwalina is running a little poll attribute design on his blog. I made a comment, but I thought I'd post my thoughts here too.

The question is: is it better to have (i) lots of different attributes, or (ii) fewer attribute but use enumerations in the constructor? Naturally, this dichotomy is limited to those attributes that don't have any other arguments, i.e. only "marker" attributes.

  1. Attributes
    • [Foo]
    • [Bar]
    • [Baz]
  2. Enumeration
    • [Foo(Kind.Foo)]
    • [Foo(Kind.Bar)]
    • [Foo(Kind.Baz)]

In many ways, it seems to me to be analogous to writing several methods versus one method with parameters. It depends! How related are the attributes? Enums are quite discoverable - all the options pop up when you type in the enum name. With multiple methods / attributes, it's harder to find the related group.

If the different attributes / methods aren't closely related, then it would be wrong to conflate them into an enum.

What about user extensibility? With methods / attributes, one can define new classes / descendants and add new methods / classes that look just like the old ones. With the enums, they're baked in. This can be both good and bad - it's more encapsulated etc, less risk of confusion.

Another aspect: types for a purpose versus flexible types. Sometimes, people who are beginners to a problem look for something which is the perfect solution. Trouble is, most people's problems are diverse. This can lead to a large number of "simple" types for solving each particular class of problem, but the overall result is that the solution space is *more* complex because there's more of it. Beginners and experts alike become frustrated; the first daunted, the other feeling the clutter. In this light, fewer types that are configurable sounds better - leading to the attributes with enum arguments approach. But then - only if it makes sense!

A rule of thumb: if the attributes would probably start or end with a common prefix or suffix, then it would probably make more sense to use an enum instead.

No comments: