# Why is software so expensive?

> Writing code isn’t that hard; evolving it is. Readability, testability, modularity: the three pillars of software craftsmanship.

- Author: Mathieu Eveillard
- Published: 2022-06-29
- Updated: 2025-01-15
- Tags: CEO
- Canonical: https://www.mathieueveillard.com/articles/cout-du-logiciel/
- Translation (fr): https://www.mathieueveillard.com/fr/articles/cout-du-logiciel.md

![Why is software so expensive?](https://www.mathieueveillard.com/articles/2022-06-29-cout-du-logiciel/cout-du-logiciel.webp)

Because developers are overpaid? Nice try, but no. And besides, that’s not what we’re here to talk about.

**First and foremost, there’s this unfortunate tendency to develop things that nobody needs**. We think we know what users want without actually being users ourselves.

If cats could talk… 🐈

Hence the need for genuine user research, personas, and constant attention to user feedback. It seems obvious and simple, but the proliferation of organizational layers and the fragmentation of responsibilities mean that those who build the apps often no longer have any direct interaction with users.

> A user? Yeah, I saw one once. I remember it very well—it was July 12, 1990, a Thursday!

These foundational principles of User Experience (UX) were well understood by the founding fathers of Agile, who incorporated some of them and added considerations specific to development. At the heart of Agile, then, is the imperative to work in short cycles and deliver frequently to production in order to stay as closely aligned as possible with user needs. Adapting to change.

Unfortunately, we all know what Agile has become: “We do sprints of varying lengths.” Ouch. If you need help, don’t be embarrassed—I’ve created a training course to help you separate the wheat from the chaff. You’ll love the title: Agile with a Hammer.

All of this brings me to the topic I wanted to discuss with you: code. Writing code, at its core, isn’t that complicated. When it comes to business software, a few months of learning is enough to do simple things. Yes, you might have to fumble around a bit, but in the end, it works. No, **what’s complicated is the long term**. Let me explain.

The initial features are in place. A few months have passed, and now we need to add new ones, which means making minor changes to the code that’s already been written. The features already in use become special cases of broader concepts, so the main job is making the code more generic.

That’s where things get complicated:

```
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
```

Ah.

Do you understand how this regular expression works? It’s for email validation. Rest assured, no human can make sense of this, since these lines don’t convey anything about the developer’s intent. It’s therefore impossible to evolve this code, especially since no tests protect you against regressions. At the slightest need, you’ll have to start from scratch. Pure legacy code.

In theory, this is just as absurd as replacing a car because a turn signal isn’t working. Yet that’s exactly what happens. It’s not uncommon to see enterprise applications scrapped after just a year or a year and a half. The people who helped develop them have left, their code is incomprehensible, and the expertise has been lost.

Fortunately, Software Craftsmanship—or “Craft”—offers many solutions to avoid ending up in this kind of situation. We could categorize them as follows:

- **Readability**: ensuring that the code remains understandable to humans. This is primarily a matter of clean code, but also of Domain-Driven Design (for naming conventions), typing (for those who might be tempted to write pure JavaScript), and functional programming (for pure functions, which make it easier to understand a system);

- **Testability**: having a safety net to detect even the slightest regression, whether it crept into a single function (unit tests) or stems from faulty collaboration between multiple functions (integration tests). By extension, we can include typing, which serves the same purpose, and, while we’re at it, functional programming, in that it facilitates testing. But even more than that, tests can guide us in discovering requirements (Behavior-Driven Development) and in writing code (Test-Driven Development);

- **Modularity**: the problem arises when everything depends on everything else. You fix your car’s turn signal, and suddenly the air conditioning stops working. Strange, isn’t it? That’s when you need to draw on the entire body of knowledge of Domain-Driven Design to establish isolation zones, based on domain-specific considerations. This knowledge is essential for keeping your systems able to evolve.

In my view, these are the three pillars of **software craftsmanship**. When mastered, they help prevent the accumulation of too much technical debt… our next topic.

See you next week 👋!
