The existence of these paradoxes doesn’t mean things are hopeless. I don’t point them out to frustrate or depress you. Every day, paradoxically, teams still build and ship working software.
I point them out to make sure we realize that they exist, that we need to accept them and deal with them, and hopefully avoid the pitfalls and potholes that they present. We can’t eliminate the strangeness and chaos, but we can anticipate them and deal with them. Our job is to ship despite them.
One last paradox might be that software is never really done. There is always one more feature that you can add. At least with a bridge, it is quite clear when the job is finished and that the product works as designed.
Civil engineers can rightfully claim that no
two bridges are exactly alike. However,
bridges share many known characteristics, and the materials they are built with
have known characteristics. What they do
has many known knowns and not as many unknown unknowns as one might think.
I am not a civil engineer and I have nothing but respect for the fine folks
that design and build our bridges, but I point this out to contrast it to
writing software. Writing good,
functioning software is hard. Every project undertaken by software development
teams has never been done before. There
are similarities amongst projects, sure, but any given project has nuances,
requirements, and a plentiful supply of unknown unknowns. Or, one might say, software development is
full of paradoxes that are challenging to deal with. Here are four:
No one knows how long anything
will take. Customers want and need to
know how long things will take.
This, frankly, is probably the biggest challenge that software development
organizations face. We simply
aren’t able to tell for sure how long any project will take. Sure, we can
estimate, but we are almost always wildly off — sometimes drastically
overestimating, but most often drastically underestimating how long something
will take. But for our customers, this is both a mystery
and a difficulty. Not understanding the
first part of the paradox, they don’t get why they can’t know for sure when
they will have a new piece of functionality and are of course frustrated when
it isn’t delivered as promised. We try story points and planning poker and all
kinds of other agile techniques to figure out when things will get done, but we
never quite seem to be able to get past Hofstadter’s Law: “It always takes longer than you expect, even when you take into
account Hofstadter’s Law.”
Brooks’ Law — Adding developers
to a late project makes it later.
This is the strangest of the paradoxes to the
casual observer.
Normally, if you realize that you aren’t going to make the deadline for filing
your monthly quota of filling toothpaste tubes, you can put more toothpaste
tube fillers on the job and make the date.
If you want to double the number of houses that you build in a given
year, you can usually double the inputs — labor and materials — and get twice
as many houses, give or take. However, as Fred Brooks showed in his book The Mythical Man Month, “adding manpower
to a late software project makes it later.”
That is a paradox, but it’s as close to a law in software development as
we will get. Brooks showed that because
new team members require training, time to learn the context of a complex
system and increase the communication overhead, they can’t contribute to the
project immediately, thus driving up costs.
The better you get at coding, the
less code you end up writing
It takes many years to gain experience as a
software developer. Learning the right
way to code, the right way to design, and all the small subtleties of writing
clean, maintainable software isn’t done overnight. But all too often, as you gain that
experience, you are put into leadership positions that actually reduce the
amount of code that you write. Instead,
you end up in design meetings, reviewing code written by others, and managing
people. And sometimes you get promoted
out of writing code all together. That is not to say that a senior developer’s
contribution decreases — that is usually not the case. The process of planning projects, mentoring
younger developers, enforcing coding standards, and realizing how important it
is for everyone to write good code — all contribute mightily to the success of
a project.
But you still end up writing less code.
Software development frameworks
and tooling keep getting better and more powerful, but our software still takes
just as long to develop and never seems to run any faster.
If you compare how we build web applications
today with React,
Astro, Next.js, and
other powerful advanced tools with thirty years ago when we processed data and
HTML using the Common Gateway Interface (CGI), you soon
realize that we’ve advanced lightyear from those early days. It always seems like a paradox to me that our
processors get faster and faster, but software development never seems to move
any faster. Work always seems to expand
to fill and exceed not only time budgets, but every single CPU cycle as well. Our sites look nicer, but are we really any
more productive? Do our sites run faster
and process data better? Sure, these new
frameworks and libraries abstract away many complexities (does anyone want to
write jQuery code anymore?) but at the
same time introduce new problems like long build pipelines, configuration
nightmares, and dependency bloat. The existence of these paradoxes doesn’t mean
things are hopeless. I don’t point them out to frustrate or depress you. And yet, every day, teams still build and
ship working software. I point them out to make sure we realize that
they exist, that we need to accept them and deal with them, and hopefully avoid
the pitfalls and potholes that they present. We can’t eliminate the strangeness
and chaos that they can present to us, but we can anticipate them and deal with
them. Our job is to ship despite them. One last paradox might be that software is
never really done. There is always one more feature that you can add. At least with a bridge, it is quite clear
when it is done and that it works as designed.