About the author

Steven Harmansteven harman :: makes sweet software with computers!

For recent posts and more about me, scroll to the bottom.

Subscribe

  • Subscribe to my feed. via RSS
  • Subscribe via email via email

News

Badges

  • Subtext Project
  • Support Subtext

Replace that Stinky Code with a Bitmask and the FlagsAttribute

Pretend that you’re building an application to do something like... oh I don’t know, track employee time. Applications like this exist in almost every company on the face of the earth. After all, time == money, duh!

Lets also pretend one requirement of your time tracker is to keep track of the employee’s regular work hours - meaning their start/end times and the days of the week they work. Again, seems like a pretty simple and intuitive requirement for a time tracking system.

So, here’s my question: how would you go about storing the days the employee works in your data store? Just to narrow the possible answers, assume that we’re using a database for persistence.

Seen in the wild

Case Sensitive Work Days, eww! Whatever you’re thinking, I hope you’re not thinking that storing it in a 7-character, ordered, case sensitive, nullable string character array is the right answer!

That’s right the string character array in the WorkDays column uses the first letter of the day of the week, going from Sunday to Saturday, left to right, as a quasi-data-mask to hold the possible values. A lower-case letter means that day is NOT selected, and a capital letter means the day IS selected.

Using that magic decoding logic the employee corresponding to the 2nd row of data work Sunday, Monday, Wednesday, and Friday. I don’t know about you, but I smell something awfully funky with that code. Yikes!

How would I do it?

Any developer worth anything knows that the only right answer* is to use a integer (representing a bitmask) in the database and then map that to an enum decorated with the FlagsAttribute in the code. Something like

DaysOfTheWeek emum

That’s what you would have done too, right?

Is the 1st way really that bad?

When I started writing this post I intended to show an example of some insane code du jour that I found in the wild. But then I realized that the case sensitive character array might not be a horrible solution under some very particular circumstances and assumptions.

However, the solutions quickly breaks down when some of those assumptions change. Like if you need to JOIN on that data field, or use it to filter your data in a SELECT statement. In cases like that you’re really going to want something like a bitmask to help keep your queries cleaner and easier to parse... parse by your eyes that is.

Unfortunately I’m working on an existing production system and they’re not going to let me change the field to a bitmask. But maybe you’ll have better luck! :)

* = Any time you see these words, you can disregard whatever else the speaker/writer has said as they were probably born yesterday. That is to say, there are often several right answers. :)

Technorati Tags: ,,,

What others are saying.

# re: Replace that Stinky Code with a Bitmask and the FlagsAttribute
Gravatar Steven Harman
Dec 10, 2007
I should have mentioned that there is a built in DayOfWeek enumeration in .net, but I chose not to use it for two reasons.

1) I wanted this example to be more generic and provide a solution that could be applied to other data values.

2) The System.DayOfWeek enum doesn't work as a bitmask b/c it's values go from 0-6 (Sunday to Saturday). But in our enum we want a value for None and we need the values to be powers of 2 in order for them to work as a bitmask that is stored as an integer in the backing data store.

:)
# re: Replace that Stinky Code with a Bitmask and the FlagsAttribute
Gravatar Dave Donaldson
Dec 10, 2007
Man, that first solution is tight! OK, maybe not. Pretty bad actually, and is so bad I can't even imagine being able to think of that as a solution in the first place. That alone is why we'll always be able to do consulting :-D
# re: Replace that Stinky Code with a Bitmask and the FlagsAttribute
Gravatar Anthony Stevens
Dec 11, 2007
Just be careful to check range values, especially when those values are coming from a database and could have incorrect data.

I found out the hard way that C# enums are not automatically checked for range safety, and in fact any integer will cast without throwing an exception. See http://xidey.wordpress.com/2007/12/10/c-enumparse-bug/ for what I found.
# Code smells also in SQL server system tables and StoredProcs
Gravatar CodeClimber
Jan 30, 2008
Code smells also in SQL server system tables and StoredProcs
Comments have been closed on this topic.