The number of times that I encountered a piece of code like the following is quite alarming:
Transaction transaction = TransactionFactory.CreateTransaction( true, true, false, true);
What do those true, true, false, true mean? We’ll need to view the method signature each time we need to understand what those four booleans represent! This means that anyone trying to skim through your code will have a bad time. Sidenote: if you’re writing method calls with such parameters, you seriously need to consider re-thinking such calls.
Let’s try to improve the readability of that code by a bit
Transaction transaction = TransactionFactory.CreateTransaction( true /* postInSage */, true /* isPaidInFull */, false /* recurringTransaction */, true /* sendEmailReceipt */);
What did we do here? We added some comments next to each boolean so that when reading the code, the reader can quickly identify what each boolean signifies. Neat, we’ve improved the readability by a lot! Microsoft developers seem to like doing it this way; a quick look at .NET Framework Source will show you some good examples, such as here, here and here.
But, what happens in case the order of the booleans change? Apart from breaking functionality, the comments will not update to reflect the new API call. As they say, comments lie, code never does.
Instead of opting to document the parameter names with comments, C# offers the facility of naming your parameters. This means that you can choose to ignore the order of the parameters, but affix the name of the parameter before the actual value. Let’s apply it to our example.
Transaction transaction = TransactionFactory.CreateTransaction( postInSage: true, isPaidInFull: true, recurringTransaction: false, sendEmailReceipt: true);
That’s looking great! We can even improve a bit by defaulting all boolean arguments to false, thus we’ll only pass those booleans which should be true.
Now, the method signature will look like this:
CreateTransaction( bool postInSage = false, bool isPaidInFull = false, bool recurringTransaction = false, bool sendEmailReceipt = false)
The method call with look like this
Transaction transaction = TransactionFactory.CreateTransaction( postInSage: true, isPaidInFull: true, sendEmailReceipt: true);
We can also take a totally different approach and eliminate the use of boolean parameters and introduce Enums, specifically Enum flags. This means that when we call the CreateTransaction method, we’ll simply pass the required flags. In case you forgot, here’s a quick refresher on how it works. It will look something of the sort:
Transaction transaction = TransactionFactory.CreateTransaction( TransactionFlags.PostInSage | TransactionFlags.IsPaidInFull | TransactionFlags.SendEmailReceipt);
Not bad! When you read that piece of code, you can easily identify any properties that should be taken into consideration when creating the transaction. We ended up eliminating the need of booleans, in favour of flags.
Does this means that booleans should never be used when dealing with parameters? Of course not. I just wanted to shed some light on the fact that there are better approaches than just writing and consuming APIs in a more readable fashion.