I love this one. I don’t know the name of the pattern, but i love using it.
Imagine your system uses strings to represent the value of a status field. potential values of this field are:
- New
- Requested
- Open
- Closed
- Deferred
- In Progress
- More Information Required
…and you want to write a method (or webservice) called UpdateStatus, which takes in one of these values.
Standard signature would look something like this:
public void UpdateStatus(string newStatus)
The use of “string” for the static type has the problem that someone could pass through a rubbish value as a string, and the UpdateStatus method is now responsible for domain validation of the input.
However, following the pattern below, you’re able to statically define your domain (if known at design-time) and enforce the stronger type in subsequent method calls.
public class IssueStatus { void IssueStatus(string description) { this.description = description; } readonly string description; public static IssueStatus New = new IssueStatus("New"); public static IssueStatus Requested = new IssueStatus("Requested"); public static IssueStatus Open = new IssueStatus("Open"); }
and you can then use the strong IssueStatus type in your signatures:
public SaveButton_Clicked(object sender, EventArgs e) { bo.UpdateStatus(IssueStatus.New); } public void UpdateStatus(IssueStatus newStatus) { if (newStatus == IssueStatus.New) { // do something here } }
I learnt this one on the job a few years back, and think it’s fantastic.
We found a related refactoring to this recently which I thought was really cool.
Say you want to add a new status called Imported for issues which are newly added, but came from some other database instead of being added by hand.
So you change your code from:
if (newStatus == IssueStatus.New)
{
// send a “new issue created” email
}
To:
if (newStatus == IssueStatus.New || newStatus == IssueStatus.Imported)
{
// send a “new issue created” email
}
Then you find some other place in the code that also needs to change:
if (newStatus == IssueStatus.New)
{
// create a record in the issue billing system
}
…becomes:
if (newStatus == IssueStatus.New || newStatus == IssueStatus.Imported)
{
// create a record in the issue billing system
}
That conditional expression for the if statements is duplicate code!
So if you’ve used a strong type IssueStatus, instead of a string, you can easily add a property to your IssueStatus class:
public bool IsNewlyCreated { get; }
// make it true for New and Imported, false otherwise
Then refactor to:
if (newStatus.IsNewlyCreated)
{
// whatever
}
Suddenly your if statements become much more expressive about _why_ the code block should be run. If we choose the property names well, then the code is not just saying “if status is X or Y”, it’s telling you the business meaning behind it. And if we choose the property names well, we should be able to come along in future and add a new status called Z, set its properties appropriately, and existing code will already understand it.