Your browser is no longer supported. Please upgrade your browser to improve your experience.

In our blog post on quality in Lean-Agile software development, we discussed some elements of habitable software. For this post, we’re going to look in-depth at the habits you can encourage in your software developers to ensure that your software is habitable.

But what do we mean by habitable software?

Habitable, maintainable and scalable: the big three of Conceptual Integrity

Conceptual Integrity is at the core of all software. And it’s a key concept of Lean software development, as demonstrated by Mary and Tom Poppendieck. Consider it a way of understanding what quality means in software.

Imagine your software as a plant. The stalk and the leaves are Perceived Integrity, everything you can easily see and experience. But Conceptual Integrity are the parts that live under the soil, but without which the plant cannot exist.

Bluefruit Quality Tree

Conceptual Integrity is so important, so critical in being able to support all the features and experiences of software, it can lead to big problems down the road when it’s not championed. And it is from habitable software that you achieve software that is maintainable and scalable.

So, what is habitable software?

It’s software with source code that’s easy to work with. The structure is clear, and any developer can make changes with confidence. It’s easy to start working with and the accompanying documentation is clear and self-maintaining.

Take writing code for a conversion table for Celsius and Fahrenheit.

It means the difference between working with this:

#include <stdio.h>
int main(void){float f,c;int l,u,s;l=0;u=300;s=20;printf("C     F\n\n");c=u;while(c >= l){f=(9.0/5.0)*c+32.0;printf("%3.0f %6.1f\n",c,f);c=c-s;}return 0;}

Or this:

#include <stdio.h>
/*This code produces a table of Celsius v
Fahrenheit temperatures from 0C to 300C*/
int main(void){
  float f, c;
  int l, u, s;

  l = 0;
  u = 300;
  s = 20;

  printf("C     F\n\n");
  c = u;
  while(c >= l)
  {
    f = (9.0/5.0) * c + 32.0;
    printf("%3.0f %6.1f\n", c, f;
    c = c - s;
  }
  return 0;
}

And having this instead:

#include <stdio.h>
void PrintCelsiusVsFahrenheit(int lowerCelsius, int upperCelsius, int step)
{
  float fahrenheit, celsius;
  printf("C     F\n\n");
  celsius = upperCelsius;
  while(celsius >= lowerCelsius)
  {
    fahrenheit = (9.0/5.0) * celsius + 32.0;
    printf("%3.0f %6.1f\n", celsius, fahrenheit);
    celsius = celsius - step;
  }
}
int main(void)
{
  const int LowerCelsius = 0;
  const int UpperCelsius = 300;
  const int Step = 20;
  PrintCelsiusVsFahrenheit(LowerCelsius, UpperCelsius, Step);
  return 0;
}

Note that all three code examples create the expected outcome:

C     F

300  572.0
280  536.0
260  500.0
240  464.0
220  428.0
200  392.0
180  356.0
160  320.0
140  284.0
120  248.0
100  212.0
 80  176.0
 60  140.0
 40  104.0
 20   68.0
  0   32.0

And it’s clear which one would be easier to work with.

Poor habitability has real world consequences

It’s also important to remember that the outcomes for code with poor habitability and generally low conceptual integrity can lead to real safety and security issues down the line. You can find out more about that in our Lean-Agile post on quality.

If you’re still not sure, try imaging a more complex program with far more code and programming involved. It has a thousand lines or even more. Say it’s code that’s important in the embedded systems for acceleration and deceleration of a car, or the software for the administration of insulin in an automated insulin pump. You would not want code that follows the form of our two bad examples.

Why does habitable software matter to development?

Over the lifetime of a product, many different software engineers may peer into the depths of the product’s source code and work with it. From initial development to post-release features or cybersecurity fixes: different people, of different experience levels at different times and in different companies could be handling your source code.

A product might even have legacy software that’s been untouched for years, but as it’s still a core product for your company, and there could be a need to maintain or update the product, requiring you to make changes to the software. One example is when a key hardware component is no longer being manufactured and the source code needs to be adjusted to work with a different component.

The time it takes for a developer to explore and refactor the code is worsened when the software has low to no habitability. And aside from affecting how easy it is to maintain the code for testing or being able to scale it, there’s another issue low habitability in code can cause.

Low habitability and bad habits

If poorly written code, as in the examples above, is not refactored and improved, then it can encourage sloppy coding by other developers. This goes on to undermine how habitable a piece of software is, leading to an increased chance of errors and general issues in quality.

Developers of all levels have seen this, but the evidence isn’t just anecdotal. To understand this phenomenon, we need to step back from software for a moment and talk about two cars.

Two cars and bad behaviour in code

In 1969, social psychologist Philip Zimbardo conducted an experiment involving two cars at two different locations (link goes to PDF).

Zimbardo placed a car, that had been partially tampered with to make it look abandoned, outside the Bronx Campus of New York University. Zimbardo observed the car being subsequently further vandalised, in daylight, by other passers-by.

He repeated the car experiment in Palo-Alto, near Stanford University. After further damage had been done to the car by Zimbardo and his students, other people passing by in the area deemed it acceptable to start vandalising the car.

Zimbardo’s research and that of others has shown that people enact lower standards of behaviour when their surroundings suggest this is okay.

And in software development this means developers will often write un-habitable code when presented with it and not encouraged towards good programming habits.

The path to habitable code

So, how do you encourage your developers towards improving conceptual integrity?

Questions for your software developers

Talk with your developers and ask them to think objectively about their code. Have them consider:

  • How easy is it for them to come back to?
  • How easy is it for others to work with their code?
  • How easy is it to follow?
  • How easy is it to understand at a quick glance?

If the answers suggest that it’s not easy to do these things, then your developers should consider measures to improve the habitability of their code.

Don’t be unnecessarily complex

Overly complex code doesn’t make for habitable code. Because it will confuse and mystify people, delaying the time it takes them to understand what they’re dealing with. It’s also often a waste of time using overly complicated solutions to optimise code, because modern compilers will be working hard to optimise it anyway. It also has an impact on debugging, as Brian Kernighan puts it:

“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.”

So, what’s the clever thing for engineers and developers to do? As, Justin Etheredge of Simple Thread explains:

“We get credit for making our code simple and easy to understand. We get credit for loose coupling, for testability, for shallow hierarchies, for good exception handling, for fluid interfaces, for not giving our co-workers headaches, essentially for all around good design. We get credit for being good software engineers.”

Here’s the alternative to overly complicated code.

Be clear and simple

The final steps towards habitable code are reasonable and straightforward. It’s a case of encouraging and coaching developers to:

  • Stick to agreed conventions. Consistency helps make it easier to work in the code—ensure developers have access to a coding style document and are provided coaching on style (you can enforce this with regular code reviews).
  • Use clear names of variables and functions. The name of the variable or the function should describe what the variable or the function is or does.
  • To be verbose and not be afraid of it (especially with function names). If developers are finding that they have long, sprawling function names, for instance, this is a good indicator that something isn’t right and that the function may be attempting to do too much.
  • Aim to write code that can be understood without any comments. If code manages with the previous three points, this will happen naturally. Comments add a maintenance burden to software, as they will need to be reviewed with each iteration.
  • … But if a comment would make something clearer then add a comment. If there is a genuine chance something in the code is going to be misunderstood, regardless of the other steps taken: add a comment.
  • Use test names that explain what is actually being tested. This makes it easier to investigate why a test is failing. Not only does it give a clearer indication of the test that’s failing, but it also shows what behaviour is meant to be happening in the first place. So, it helps cut down the time taken to investigate a failing test.
  • Write so a novice programmer could understand what is happening. Development teams typically have people of different experience levels on them, from junior to senior. Code written in a clear way that’s accessible to different ability levels helps to make it easier for different developers to look at code and take part in pair programming or mobbing.

Notice how we didn’t say, “Aim to write it so a non-coder could have a vague understanding of what is happening”? That’s because it’s not possible. Aside from something like pseudo-code, someone viewing code needs to have a basic understanding of how code tends to be structured and concepts like variables and functions.

Habitable code helps you to future proof your software, reducing technical debt

An important aim with being clear and simple in writing code is that habitability is supported, which supports maintainability and scalability.

This all also helps you to reduce your overall technical debt in your embedded system over time. Essentially making it possible for nearly anyone with the right level of knowledge and experience to work with source code. No matter where they are in place or time.

Thanks to Denzil, whose training inspired this post.

Quality software for safety-critical spaces

Looking for embedded software engineers and testers? Over the past 20 years, Bluefruit Software has delivered quality software to a range of sectors, including medtech, industrial and scientific.

Let’s set up a call

Did you know that we have a monthly newsletter?

If you’d like insights into software development, Lean-Agile practices, advances in technology and more to your inbox once a month—sign up today!

Find out more