The Rockface blog aims to help embedded software engineers go faster, and is brought to you by Rockface — a service that enables automated hardware-in-the-loop testing of your embedded system.
You can subscribe to this blog via RSS.
When we talk about software, we’re fundamentally talking about long strings of bits. We throw those strings of bits into machines, with the aim of getting those machines to do the things we want.
Flipping the bits is trivial. The challenge we face in software engineering is ensuring that the machine behaves, and continues to behave, in a way that meets our expectations. That’s the tricky part: changing the bits in just the right way.
Not only is this trickiness the reason why our industry exists at the scale that it does, but it’s also the reason that working within this industry can be so interesting, rewarding, and frustrating!
In this article we’re going to explore what our high-level goals are when engineering software. We’re briefly going to get a bit philosophical, but with good reason. We need to understand the roots of why we are doing what we are doing.
Before we go any further with our thinking about software engineering, we have to accept something. Something that doesn’t always seem to be at the forefront of our minds, especially because we spend a lot of our time just driving computers: We’re building things that matter to people.
While to some this may seem overly sentimental or reductive, it is ultimately the driver of all of our work. Someone somewhere needs what we are building in some way.
It matters to them that the product works.
It matters to them that the product continues to work.
Therefore these things matter to us too: we care that the product works, and we care that it continues to work. We also care that we can make changes without putting broken products in the hands of our users.
So, our highest-level goal is to get working software into the hands of our users.
This, combined with some facts of our physical reality, leads to us to realise that we are trying to ship useful software reliably, quickly and cheaply:
Useful: We’re trying to ship something that our users actually need. If we ship something else, then it’s really just a waste of resources – we’re just flipping bits with no purpose.
Reliably: Stuff needs to work every time someone comes to use it. Otherwise we’re just flipping bits into the wind again. We want zero defects in production.
Quickly: Our users have needs right now – in the present. We want to get our work into their hands as soon as possible. We need the delay between making a change and getting that change to our users to be as small as possible. We need to be able add the features they need, and fix the issues they’re experiencing, as soon as possible.
Cheaply: We are always resource constrained. If we’re going to meet our goals, then we need to use those resources carefully.
That set of goals wasn’t quite complicated enough – there’s just one more thing… We can never really be quite sure that the thing we are building is what people actually needed. We’re always in a state of product research and development. New requirements will arise on an ongoing basis, and we will need to be able to introduce those changes quickly and cheaply into our work, all-the-while keeping it useful and reliable.
So we’ve got a vast sea of bits to navigate. We’ve got some goals, which give us some idea of the direction we need to go in. In order to have half a chance of arriving at a useful place, we’re going to need to put some processes in place and follow them with rigour.
So, product and engineering teams need to sit down and really think carefully about the processes that they are going to follow. Often they don’t bother and end up with a random grab-bag of practices. Sometimes they end up with none at all, and that just leads to… well, it doesn’t really lead anywhere particularly useful. Things will look like they’re working for a bit, but will grind to a halt eventually.
After some thorough consideration of our goals, we’re quite often faced with having to change some really fundamental aspects of the way that we work. The way we think about the product has to change. The way we talk about the product with our colleagues and its users has to change. The way we design the product has to change. The way we change the product has to change! These can be really difficult things to come to terms with – change is hard. It takes work.
The work in making those changes is worth it. The pursuit of quality software can be worthwhile and fruitful, but only if we fully engage with it. Ultimately it’s essential in order to stay competitive, relevant and find meaning.
This article has covered our aims at a very high level – establishing the direction and vision of where we want to go. With this grounding, we can start exploring questions like “How do we work out what our software is supposed to do?”, “Does our software actually do those things?”, and “What sort of tools and practices are the most effective?”. We’ll be exploring these things in future blog posts!