Monday, 29 August 2011

Implicit Categories

A seemingly simple task such as putting items in categories can take more effort than you would think. I would like to share a really simple pattern that makes this a lot easier, but is only suitable for simple cases. Luckily, this covers a lot!

Like The Iterative Reference Model, this "pattern" is something that I discovered while programming. It made my life a lot easier on many occasions.

Normally, when you have an entity, say "BlogPost" and you want to group BlogPosts into "Categories", you would define a class named "BlogPost" and a class named "Category". Each Category then holds a list of BlogPosts. This is a perfectly good design, but in some cases it can be done a lot simpler.

Suppose that we know that each BlogPost will be in only one Category and that Categories do not contain other Categories. Then, instead of a class Category, we could simply give each BlogPost a String property that holds the name of the Category that this BlogPost is in. We don't have Category objects, just this String for each BlogPost. Then, the user interface can group the BlogPosts in Categories, while the server stays really simple. In fact, it doesn't even know about Categories. For the server, it's just a String property of BlogPost.

Of course, you don't want to type the Category for each BlogPost every time, because more often than not, you want to put a BlogPost in an existing Category. This is no problem. You can get a list of all Categories by doing a "SELECT DISTINCT BlogPost.category" on the database. This way, you can give the user a drop-down box with existing categories and a textfield for when he wants to specify a new one.

When applying this approach, it saves you a lot of CRUD functionality on Categories. In fact, when a Category is "empty", it will "automatically" disappear! You can write some smart SQL statements that take into account the category column for when you want to do things such as selecting or deleting all BlogPosts in a certain category.

Obviously, this approach is only suitable for simple cases, but even in the most complex applications, there will always be simple scenarios among the complex ones. This approach is not suitable if:

  • Items need to be in multiple categories. This is because you cannot store a list of Strings in a database row. You need a separate table for this and if you need a separate table anyway, you might as well opt for the fully fledged Category class.

  • Categories need metadata. Maybe a Category needs a creation date? In this case, the implicit category pattern will not help.

  • Categories need to be able to contain other categories (Container / Component pattern). This too, cannot be achieved with this approach.
So yeah, this is only for simple cases, but when you encounter ony of those, it makes your life a lot easier! Also, it is very easy to migrate this data to a fully fledged Category table at a later time.