Monday, October 28, 2019

A software developer as a software user

In the first few years of my career, I had an opportunity to work on projects which included mechanical design. I studied mechatronics, so besides writing software, I was also involved in the design of mechanical components until later on, when I completely shifted my focus on programming and software design. During this period, I mainly worked on the development of vending and parking ticket machines. The company that I worked for, as a service provider, had the task of designing and developing prototypes that should be later on produced and distributed on the market.

To put things into context, let's assume that our task is to develop a prototype for a parking ticket machine. As always, the goal should be to provide value to the users. So, the first question should be: Who are the users of the parking ticket machine?

Before giving an answer, let's take a look at some definitions of a user:

"Someone who uses a product, machine, or service"

"A person who uses or operates something."

So, I guess the obvious answer is that users are persons who are buying parking tickets.

Unfortunately, this is not a complete answer.

The parking ticket machine needs maintenance:
- Collecting the money,
- Refilling the parking tickets,
- Repairing and replacing the mechanical parts.

So, in this context, a mechanic that will repair the machine is also a user. A person who is collecting the cash and refilling the parking tickets in the machine is also a user.

In order to provide a quality product, we need to think of all kinds of users. We need to design the machine in a way that a mechanic can access the mechanical components and repair or replace them. We need to make refilling the machine easy and efficient. My experience is that the team that was working on the design naturally started thinking about all of these aspects and after discussions with the client, all these aspects became the acceptance criteria for the prototype. 

I love the analogies between different engineering disciplines and I believe that there are a lot of similarities between them, even at the implementation level. Here's an example:


Figure 1.

In Figure 1. we can see a socket. When you search for an analogy in the software design, it's an interface. I can plug anything into the socket that respects "the contract" of it. The ability to change one part of the system without affecting the other one is the core idea of the loosely coupled systems. There are a lot of similar examples. 

In that sense, let's switch the context from the development of a parking ticket machine to the development of a web application and see how our existing analysis of the users applies. The ticket machine has a user interface, but as we saw, it also has internal components that need maintenance. The same can be said about the web application. Who is going to maintain the web application? A software developer, of course. So, if we apply the analogy with the ticket machine, a software developer is also a user. For me, this is even more important in software engineering because a mechanic will probably repair or replace some parts but in the context of software engineering maintainability, it is not just about repairing but also adding new or changing the existing features. One of the main reasons why the software was invented is to enable easier and cheaper changes to the systems. If we create software that is rigid and hard to change, we are defeating its initial purpose.

As already stated, our goal should always be to provide value to the users. In the context of the ticket machine, it includes users that are maintaining the machine. The same applies to the software. If we want to provide value for the users, we should pay attention to the internal quality (the quality of the codebase) of the software as well. Developers are users, too. The point that I'm trying to make is not about terminology. It's about the mindset. We should treat developers as users because that will lead to the investment of time in the maintainability, which should increase the internal quality of the product.

So, if this makes sense, why do we often have legacy codebases that are hard to maintain? Why are we still trying to convince managers that the internal quality of the software is an important asset? Why don't many developers believe that providing internal software quality is equally as important as providing business value? Why don't we treat developers as users?
The shortest answer is: It's complicated. Many factors can be treated as causes, but for me, the main cause is the lack of useful measurements. This is what separates software engineering from other engineering disciplines like civil engineering or mechanical engineering.
Lines of code, code coverage, and cyclomatic complexity are measurements that we often use as a tool to get feedback about our codebases but, from experience, we all know that this information is really context-dependent and that it hardly provides any useful value. Even so, this is no reason to give up. We know from the pioneers that came before us about the best practices, antipatterns and different approaches to achieving a good software design. Internal software quality IS achievable and should be treated equally as important as the external one.

If we do not treat developers as users and focus only on the external quality of the software, we will not have good results because the only constant thing in software development is that future changes are inevitable. The internal and external qualities of the software are not mutually exclusive. You need both in order to provide real value. 
Treating a developer as a user should provide more sense when it comes to investing time in the internal software quality.