[Estimated Reading Time: 3 minutes]

I’m afraid I have been guilty of editorialising on StackOverflow. It was sheer laziness really. A question prompted me to respond by sharing a personal preference and instead of “context switching” to my blog I posted an answer that even at the time I acknowledged was not in fact an answer (though as transgression go I have to say I have seen far worse, but, that’s no excuse).

So, with (further) apologies to StackOverflow, I have withdrawn that answer and instead present that editorial here, a more appropriate forum.

The question involved how to cajole, coerce or otherwise convince the source formatting tools in RAD Studio to format a case statement in a manner pleasing to the OP. For illustration in the question they posted an example of how RAD Studio was currently formatting the statement (I hope they don’t mind me reproducing their examples here):

    case SomeEnum of
      seOne: begin

        end;
      seTwo: begin

        end;
      seThree:
        ;
      seFour:
        DoSomething;
    end;

And helpfully then illustrated how they would prefer to have it formatted:

    case SomeEnum of
      seOne: begin

      end;
      seTwo: begin

      end;
      seThree: ;
      seFour: DoSomething;
    end;

It just happens that case statements were among the last aspects of my own personal Delphi coding style to really settle down over the past mumble years. But in more recent years I felt I finally cracked it, having finally settled on a consistent formatting style (keyword: “style“, notsolution“) that once alighted upon has stood the test of time in a way that my previous efforts did not.

I may even have first come across this style – or something significantly similar – in someone else’s code, but if so I have long since forgotten. If you recognise this style and feel it has been appropriated without proper attribution, apologies. It is not intentional.

And so with too much ado already, here it is…

    case SomeEnum of

      seOne   : begin

                end;

      seTwo   : begin
 
                end;

      seThree : { NO-OP };

      seFour  : DoSomething;

      seFive,
      seSix   : DoSomethingElse;

    else
      // TODO: How to handle the unhandled.. ?
    end;

As you can see, I took the original code and added slightly to it, allowing me to illustrate how I deal with multiple cases having common behaviour (seFive and seSix) and (for this revised and extended blog post) an else statement.

Among the reasons this formatting finds favour with me are:

  1. The conditional statements have appropriately equal indentation with respect to each other, the single exception to this being any “else” case, where present.
  2. High visibility of the case values, often key to understanding such code when you come to read it months/years later.
  3. It’s clean and clear – highly readable (to me).

In addition to the case formatting I also demonstrate my practice of providing a specific comment to indicate a deliberate and explicit NO-OP as distinct from an equally explicit TODO (in the else). You could choose to be explicit about either one and interpret the absence of such any explicit indication as implying the other, but this leaves open the possibility that what is then interpreted as “implied” is in reality an oversight (is it a no-op or an unannotated to-do ? or vice-versa contrariwise).

In ay event, no amount of tweaking will convince RAD Studio to determine the difference, let alone add the appropriate comments for you (though some static analysis tools may draw attention to “null” statements and some may even be able to be configured to identify explicitly deliberately null statements, where commented as such).

But as for the case statement in general, I’m not presenting this as the or even a ideal or perfect approach, merely sharing my personal, individual preference that has evolved over the years.

At the end of the day, whatever works for you works for you. πŸ™‚

Footnote

Sertac Akyuz provided Jerry with the answer he was looking for. πŸ™‚

16 thoughts on “Formatting Case Statements”

  1.   case SomeEnum of
        seOne: // this is the way to do it
          begin
          end;
        seTwo: // your resistance is futile
          begin
          end;
        seThree:
          ; // NO-OP
        seFour:
          DoSomething;
        seFive,
        seSix:
          DoSomethingElse;
        else
          { TODO : How to handle the unhandled.. ? }
      end;
    
    1. Unfotunatzely indentation was cut off but you’ll get the point

      1. No worres – I fixed it for you. πŸ™‚

        For future ref you can syntax hi-lite in comments by wrapping code inside “delphi” tags. Like XML, but use square brackets instead of angle brackets on the tags. [delphi] …code… [/delphi]

    2. I usually don’t indent the begin/end (as I don’t do for their other occurrences either) and put the else on the same level as the case/end.

  2. For what it’s worth Jolyon, I’ve used the style you describe for X years myself. Same indenting of begin / end pairs, same specifying of all possibilities (even no op ones for the same reasons you note). On the “else” I will generally indent the statement there too so that it aligns with the pairings specified prior to it.

    Here’s a contentious one though… What about doing away with the “if” statement…. I’ve always suspected, though have not the slightest proof to back it up, that under the hood a compiler will reduce “if” and “case” statements to “roughly” equivalent code – in terms of execution speed. If that is credible, then the rest if style preference to my mind. So, as for style, I prefer to use “case” rather that “if”, always. To me a case statement (as you’ve shown, clearly allows ALL cases to be defined unambiguously. An “If” statement is far more ambiguous, or at least gives the impression of being so – the very keyword “if” is “unsure”, whereas “case” is “definitive”. I’ve been chided for this in the past, especially when using case for Boolean expressions, but live and let live… I also remember back in the day having a load of my mainframe COBOL code passed through a 4GL converter tool with the result that all of my nested “if” statements came out structured with GOTO’s. That was unpleasant…

  3. It takes a big man to admit his mistakes. I am proud of you. Keep up the good work.

    1. Thanks for the tips. However. I would replace all of your suggestions with one much simpler, vendor and tool independent one: Learn to type.

      I have all the code templates I need built right into my finger-tips and those don’t need to be tweaked, configured and customised on each machine I come to use. πŸ™‚

      1. And while you still type those using templates and auto completion already run their program πŸ˜‰

        1. I have to say that my experience is quite the opposite. I have yet to see anyone invoke and fill in a template more accurately or more quickly than I could type the same code. I’m not talking about project templates of course, only code templates. I do use auto-completion but configured to be summoned only on request, not automatically. It would be funny if it weren’t so painfully frustrating, to watch someone pausing for 1/4-1/2 second after every identifier waiting for auto-completion to type “more quickly” the word they could have typed 3 times over in the time that they were waiting for and choosing it from a suggestion list.

          And of course, when they slip up and pick the wrong thing from the suggestion list, their lack of proficiency on the keyboard becomes all the more apparent as they fumble to undo and redo. It constantly surprises and shocks me to realise the number of people that seem unfamiliar with ctrl + shift selection and who laboriously shift-select one character at a time (or worse, who reach for the mouse to double-click or select a word before over-typing it or even deleting it before typing a replacement instead of simply overtyping).

          If they only took the time to learn proper skills their productivity would be increased vastly more significantly than by any of these so called “productivity aids”.

          1. And when you combine proper keyboard skills with code completion you win. πŸ˜‰

            1. Yep, but code templates are not code completion.

              Although often lumped under “code completion” with other genuine productivity aids that do help complete your code (class completion, code insight etc) templates do not complete anything. They initiate/create partial code which, by definition, is not complete. πŸ˜‰

        2. It has been my observation that the fastest typists make very heavy use of the backspace key. Templates would reduce that.

          1. This I believe is what underpins the fallacy about the productivity of templates. Reducing the number of keys pressed or eliminating the use of certain keys is not a true measure of productivity. Neither even is accuracy of key entry. Actual time spent producing a particular piece of code is the only metric that counts if you are truly measuring productivity. πŸ˜‰

            Watching someone navigating through a template you will find that they use the tab key a lot more. Assuming even that you do use Backspace a lot, improve your keyboard skills further and you can reduce the number of Backspaces involved. The number of Tabs required by a template is however fixed. And if (when) you slip up in completing the template, navigating around it to correct those mistakes is far more cumbersome.

            But I would also repeat my point about the surprising lack of awareness of more sophisticated navigation techniques. A lot of people backspace through an entire symbol to correct an error in the first one or two characters and then re-typing almost the entire symbol again, rather than ctrl-lefting to reach the point requiring correction more correctly.

Comments are closed.