embedded software boot camp

Simplify, then add lightness

Saturday, December 31st, 2011 by Nigel Jones

As 2011 draws to a close I have reason to be thinking about things automotive. As part of my musings, I was reminded of the famous mantra espoused by the late Colin Chapman of Lotus Cars – ‘Simplify, then add lightness’. I have always liked this aphorism for its idea of ‘adding lightness’ rather than ‘subtracting weight’.

So what’s this got to do with embedded systems you ask? Well, when it comes to embedded systems programming, I think Chapman’s concept is spot on. While most people would probably agree that simplifying an embedded system is a good thing, I wonder though how many actively work so as to achieve this? In my case I regularly hold conversations with my clients which can be summarized as: Yes I can do that, but it comes at the expense of complexity – and complexity leads to bugs – and bugs are very expensive. I have found that clients are quite appreciative of this as it forces them to evaluate what is truly important about the product. Incidentally, when I first started in the consulting business, I thought that it was my job to give the client whatever it was they asked for. The fact that in doing so I was often giving them a serious disservice was quite a revelation when the penny finally dropped.

So what about the ‘adding lightness’ directive? Well clearly this is an interesting concept when it comes to firmware. I take it to mean that the code should be simple, easy to read, and fast in execution – in other words not unlike a Lotus sports car. If I have cause to re-read the code many months or years later and I find that the code has stood the test of time and is a pleasure to read, then I think I have achieved the required lightness. If by contrast the code is out of date and ugly to read then I know I have failed. In short it’s the difference between designing a Lotus Elan and an AMC Pacer.

 

 

8 Responses to “Simplify, then add lightness”

  1. Ashleigh says:

    I like to look at code and think “this is like reading an engaging novel… a well executed piece of art”. If I come away with that impression, it was well done. Anything else means it has something between grating irritation and just plain horrible. Too much code, sadly, is horrible.

    There are a lot of little things that lead to an impression of horrible, some I have seen include

    – badly written state machines (burying your state transition logic inside 6 layers of ugliness does not convey that you were clever, it conveys that you did not know what you were doing)

    – poor use of module (static) variable names – if there are several with a related function, put them in a structure, or at least name them using a convention where the similarity relationship is easily conveys

    – no comments (I don’t want to wade through the code reverse engineering the flow of logic and extracting the intent… TELL ME WHAT IT IS and then have the code that does this, so that I can work out if the code and comments and intent are suitable)

    – placing excessive code, or non-exported variables in header files (especially common amongst C++ programmers who try and turn their hand at embedded C)

    – use of forward declared functions, when in practice this should be needed about 1% of the time. Almost all code can be written the Pascal way where forward declarations are not needed. (Yes I know Pascal supports forward declaration.) Forward declarations are evil because any change requires updates in 2 places.

    – not using system header files, re-declaration of the prototypes in the source code. (This assumes that the systems memcpy, strcpy, or whatever else you use has EXACTLY the same prototype you used so that the linker can do its job. Not using supplied headers is a sign of laziness or stupidity.)

    – poor use of whitespace. (Some programmers think that whitespace is some kind of spawn of the devil, to be abolished at all costs. In fact, whitspace is like the mount on a painting (look it up) – it helps to visually draw your eye to what matters.

    – reliance on operator precedence by not using brackets. (Assuming all operators have equal precedence, and further that they are like other car drivers, intent on killing you, means that you use brackets everywhere. They might be superfluous, but the INTENT is suddenly very clear, the code is easier to change later, and you get less strange faults that need you to go looking at the generated assembly code)

    I could go on forever…

    • Tim says:

      I’m interested in further developing the novel analog. I wonder if others move through the source files differently than I…

      Main() and public methods seem to me comparable to the novel’s overall narrative or a play’s acts, respectively, with local methods serving as acts or characters in the story. If so, I think the use of forward declarations is consistent, maybe not with a novel, but at least with a traditional play: the cast of characters is revealed at the the outset, then details are provided once the narrative has been established.

      I suppose early character development, similar to definition before use of functions, does make a story more engaging… but maybe my misunderstanding is more fundamental.

      Am I mistaken in associating the chronology of the novel with the top-to-bottom order of the source file? I tend to scan through the declarations, then start reading at the first function definition; is this atypical?

  2. Anonymous says:

    thanks nigel – a timely reminder indeed

  3. david collier says:

    Ashleigh,

    “Forward declarations are evil because any change requires updates in 2 places” Hooray, I thought it was just me.

    “no comments ” – yes, but worse is

    /* return true */
    return true;

    • tarkalak says:

      nope.
      “no comments” is worste.

      /* return true */
      return true;

      comments are probably not gonna double(triple, quadriple) the time you need to understand the algorhitm.

  4. david collier says:

    Nigel – a timely reminder – less is more.

    though when I survey a couple of pages of getter and setter routines for my java class, I do begin to wonder…

  5. david collier says:

    “no comments ” – mmm.

    I get a lot of stick here becasue I would rather see

    sizeOfWidget = 7

    than

    /* set size of widget */
    s = 7

    In other words use the variable names first, and comment them if that doesn’t suffice.

    That does lead on to long variable names, which my colleagues don’t like. They’s prefer pithy ones and the use of hovering to bring up the Javadoc or Doxygen comments. They didn’t have those in my young day!!

    My colleage also insists on the virtue of

    for ( i = 0 ; i < numberOfWidgets -1 ; i++ )
    {
    setWidgetDepth(i)
    }

    whereas I'd always go for

    for ( widget= 0 ; widget < numberOfWidgets -1 ; widgeti+ )
    {
    setDWidgetDepth(widget)
    }

    Obviuiousy the distinction is more significant in a 100-line for loop, or 3-level nesting with i,j and k

    I think he's wrong, but he's got control of the company programming standard 🙂

    • Ashleigh says:

      He’s wrong!

      Reliance on an IDE to hover and bring up comments is simply intellectual laziness. You should be able to print out the code and sit on a bus reading it, and know what it does without needing to cross reference something else.

      As for comments, this is the kind of thing I mean… blocks of comments before a piece of code which explains what it is going to do and begs forgiveness for any known sins:

      /*
      ** Loop over the ABs in the currently active table, and for each where
      ** the bit pattern is set to ALLOCATED, copy those bits.
      **
      ** this means any pair of bits “01” gets copied, any other pattern,
      ** though, is not copied, it must become “11”.
      **
      ** No doubt there is a very clever way to do this efficiently, however,
      ** the reclaim is done so infrequently, and the erase of the underlying
      ** data sectors is slow. So inefficient code is not really a big deal.
      */
      for (i_sector = 0;
      i_sector < M_NUM_DATA_SECTORS;
      i_sector++)
      {

Leave a Reply