The Case for Case
At Extensitech, we focus a lot on extensibility. If we didn’t, perhaps we wouldn’t be saddled with a company name that requires spelling over the phone[1].
That focus means there are quite a number of things we do somewhat differently. Some of those things are harder than others to quickly explain. In many of our blog posts, we have a lot to say about extensibility, and various methods we use to ensure our software solutions are ready for changes, growth and new opportunities. For now, though, I’d like to go over a very simple, uncontroversial way to develop with unforeseen changes in mind: the Case function.
Case has been a function in FileMaker for quite a long time, so I would imagine that nearly all readers who have done any FileMaker development have run across it before. The basic format is Case(test1;result1{;test2;result2;…;defaultResult}).
For example, imagine a basic invoicing system, where you have a calculated field called “Age” which is how many days past due the invoice is (the current date minus the due date). You need a calculated text field to tell you what group the invoice should be in on an aging report:
Case ( Age > 90 ; “91+” ; Age > 60 ; “61 – 90” ; Age > 30 ; “31 – 60” ; Age > 0 ; “1 – 30” ; “Current” )Compare this to an If function: If(test;result1;result2). Pretty similar, right? If this, then that, otherwise this other thing. The “if/then” pattern is one you can find in just about any programming language, so it fits like an old pair of jeans (unless you’re reading this right after Thanksgiving, when I’m writing this).
When I first started using FileMaker in the mid-nineties, I found this function right away. I had only done some Basic in high school (and not much, at that), but it was pretty easy to figure out how it worked. The way I remember it, Case wasn’t around, at least in version 2.1 when I started, but truth is, I’m not sure. Maybe I just didn’t notice it.
So here’s the thing. I never, and I mean never, use “If”. When I’m looking at other developers’ work, I’m always amazed to run across it, and can’t understand why anyone would use it at all, or why it’s even still in FileMaker.
Anywhere I would use If, I could use Case. Highlight the word “If”, change it to “Case”, and the function works exactly the same.
So if they’re the same, why stop using If? If I know I have only one test, If will work just fine, right?
Yes and no. Yes, if you’re 100% sure there will never be another condition to test for. “No,” because even when I think I’m 100% sure, I’ve so often found out later that I was wrong. When I find out I need to add another condition to my function, changing from If to Case is just one more unnecessary step.
And please (Oh, please!) tell me no one is still doing this:
If ( Age >90 ; “90+” ; If ( Age >= 60 ; “60 – 90” ; If ( Age >= 30 ; “30 60” ; If ( Age >= 0 ; “0 – 30” ; “Current” ) ) ) )If you’ve never encountered this before, thank goodness! Usually, the original author isn’t nice enough to indent for you, either. (I only did it because I have a gag reflex.) More than likely, if you have seen something like this before, it ended with “)))))”.
Neatness isn’t the only reason we don’t use If, though. Overall, as long as you don’t have some mass of nested Ifs like the mess above, and really, even if you do, it’s not a huge deal. (I reserve the right to make dramatic faces at you, though.)
The reason we use Case consistently is a part of our overall approach to development. It’s evidence of an understanding that things change. Processes change, companies expand into other areas, opportunities come up. While what we’re developing at the moment is addressing the current need, we’re always aware that other needs will inevitably come up.
When you want to add a condition to a Case statement, you can usually copy and paste one of the other conditions and “tweak” it. (The indenting and spacing helps, too. More on that in a future pose, perhaps.) Chances are, the new condition is referencing the same field or fields as another condition. If, for example, that aging category originally started out just “Late” or “Current”, I could quickly copy and paste the condition and the result to create the other categories.
Like I said, this is pretty uncontroversial, even if you’ve never really thought about it before. If you’ve already done away with If in your own development, I hope I didn’t bore you too much, and that you’re still with me. I have a variation on this for scripting that you may not have thought of.
In scripting, we have steps for If and Else If. Thank goodness for Else If. Prior to that (which was a long time ago) the End Ifs piled up just like those close parentheses that I assaulted you with earlier. We don’t have a script step called Case, but with Else If, we can do pretty much the same thing, so end of discussion, right?
For the most part, sure, except for this: Although it’s not a big deal to change the “If” function to a “Case” function when you need to add conditions, it’s just easier to use Case in the first place. I can just copy and paste and move on. Depending on how you write your If script steps, this isn’t quite so easy.
Imagine a simple (though unrealistic) example like the one above, where on an invoice, you want to click a button and have a dialog show you whether you’re late or not. Your script might look something like this:
If [ Age > 0 ] Show Custom Dialog [“Age”;”Late!”] Else Show Custom Dialog [“Age”;”Current”] End IfNow I want to add more specific examples, like “Current”, “0-30”, “30-60”, etc. I have a duplicate button to duplicate script steps (pause for a moment to appreciate that, because it was a pain when we didn’t). However, I don’t want to duplicate the If. I want to add an Else If.
Again, this isn’t that big a deal. Like with the Case, though, it’d be nice to acknowledge up front that change happens, and develop with that in mind. We can, and here’s how our original script looks when we do:
If [] Else If [ Age > 0 ] Show Custom Dialog [“Age”;”Late!”] Else Show Custom Dialog [“Age”;”Current”] End IfThat’s right. The If is blank. As a blank, it never evaluates to true, so FileMaker moves on to the (first) Else If. (If you haven’t done this before, you may want to test this. Go ahead, I’ll wait…. You back? OK, good.)
It works exactly the same. So why bother? Because when the inevitable “tweak” comes along, I can highlight the Else If and the Show Custom Dialog, hit the Duplicate button, and then I can adjust the copy to create the new condition.
I started doing this much more recently than when I threw the If function overboard. I confess that I don’t do this as consistently as I use the Case function, but I do it more often than not now, and try to do it all the time.
Again, this isn’t an enormous time saver, and in fact it’s an extra keystroke or two in the short term. Like using the Case function, though, it’s not just about neatness or even efficiency. It’s about understanding, up front, that no matter how well your solution suits the current business problem, the future brings new opportunities and challenges that are going to require changes.
Developing our solutions so that they’re easy to “tweak”, easy to update, easy to improve upon and, well, “extensible” is just part of how we do things.
Tags: Chris Cain, xBase Development
Other posts by Chris Cain+
Leave a Reply