More than 10 years have passed since I wrote my first lines of code. In those days, we had less than half of the resources (hardware) we have today.
In other words, today, we have a lot more of everything: RAM, solid state discs (SSD), and processors with multi cores, and this has become really normal. You know that by looking at the smartphones we use to do tasks like scrolling Facebook’s timeline, seeing pictures, watching videos, WhatsApp (or Telegram), Gmail and Google searches.
Just take a look at the hardware specifications of my smartphone:
Processor Quad Core 2.5 GHz.
GPU Adreno 330, which you can get 26 frames per second.
Memory of 32 GB and 2 GB of RAM.
High resolution, 1080 x 1920 pixels.
Download speed of 150 Mbps.
Oh man!! Believe me: that’s a lot compared to what we had 15 years ago, when I dreamed about a desktop (PC) with a processor with more than 300 Mhz and 1 GB of RAM.
Did you know that computer resources have increased ~10,000 times since the first modern computers - around 1936?
So I keep thinking, what if we could travel back in time when a computer like RAMAC was the bleeding edge and 512 Kb of memory RAM was a dream, and ask a developer at that time, “what do you imagine programing would be like in a future where computers can be carried around in your pocket with 10,000 times more resources?”
Well, I bet his answer could be a different future of programming than what I see now in terms of quality issues in the software we use and develop today.
Let’s face it, you’ve been there: you download the software and to your surprise, it didn’t work like you expected, and when you start using, it a bug explodes in your face, so you talk with a friend and he gives you the famous:
Later, you “google it” (because you are a smart guy), and you find someone with the exact same problem and you feel relief because there’s the solution too! It’s your lucky day! Or not…
Most likely, you’ll keep trying things randomly until something happens and the software starts to work.
“Why?” you ask. Well, maybe no one will ever know, but it’s probably because of a bad handle / control of the application’s state.
I have been there, I’ve heard about these kinds of stories more than you think, and it’s not limited to users; it happens to software developers as well.
In my opinion, nowadays, softwares (the majority of them) are too complex and expensive, the developer experience just sucks, the architecture is huge and fragile, and any small change in the code causes things to fall apart.
So, I think… Why do we continue to develop software that tends toward bugs and is more complex and more expensive to maintain despite having 10,000 times the resources we had not so many years ago? What are we doing wrong?
Broken software– we got used to it, and we are becoming more efficient at making programming more complex.
If you feel like me, you are not alone; there are “bothered” people like us– for example, Robert C. Matin (Uncle Bob)– who want to do something about it, because at this rate, we’ll have more people creating bugs than actually developing working software.
Efficient programming won’t be the path to true quality software; effective programming is what we need.
— Sebastian Ferrari (me).
Think about efficiency as knowledge, and effectiveness as wisdom.
I recommend you take a few minutes to watch this talk about the importance of systems and true quality by Russell L. Ackoff. I would love to write more about why the key to a good system is how well the parts fit together, but this post is getting long already.
Code with bad smell
As software developers, we can quickly identify bad software when the code is too difficult to read, and it’s difficult to understand what the code does or what’s happening when a bug appears (debugging). You’ll spend more time reading than actually writing code.
Joe Armstrong is one of the designers of the Erlang programming language created at Ericsson, and also created the “seven deadly sins” for an excellent talk at StrangeLoop (which gave me the inspiration to write this post) that might help you identify bad, smelly code:
1. Code even you cannot understand a week after you wrote it — no comments written in the code.
2. Code with no specifications.
3. Code that is shipped as soon as it runs and before it is beautiful.
4. Code with added features.
5. Code that is very, very fast, very, very obscure, and incorrect.
6. Code that is not beautiful.
7. Code that you wrote without understanding the problem.
If some disagreements are ringing in your head, there’s an awesome discussion about these “sins” onReddit that are worth a full read before you complete your controversial thought.
Does your code have one or two of these problems?
- Side effects: unpredictable results.
- State changes with time using out-of-control assignment statements.
- State-full objects.
- Memory leaks.
- Coupling: interdependence between software modules.
- Lack of unit-testing capability: methods or functions do more than one thing.
- Overloaded encapsulation.
Before we get into more technical details, let’s talk about quality.
I considered myself an optimistic, so I believe in a happy balance between delivery time and software quality which could be achieved with a Lean mindset and good programming techniques that encourage you to build good, maintainable software that users love. Here’s one of my favorite principles:
Build Quality In
Find and fix defects the moment they occur.
Mistake-Proof the Process
Think of tests as specifications. Use them to establish confidence in the correctness of the system at any time during development, and at every level of the system.
Integrate Early and Often
Every development process ever invented had as its primary purpose to find and fix defects as early in the development process as possible.
Don’t Tolerate Defects
If you expect to find defects during final verification, your development process is defective.
Back to what we were discussing at the beginning: remember the programmer from the past dreaming about how brilliant the future computing world could be? Well, like Joe Armstrong said, something went wrong, because I don’t feel we are going along the right path. Maybe we can learn something from the past in order to get back on track.
Something like Functional programming, and its friends:
- Pure functions.
- High-order functions.
- Recursive functions
- Reactive programming.
- Composition over Inheritance.
- Strong typing.
- …and others, like Map and Reduce.
Maybe you are asking yourself, why are these old paradigms not commonly used if they created quality software?
Here’s my theory: in the old days, hardware was a heavy constraint for programming. Slow processors, tiny RAMs, and very little storage space that occupied a huge physical space. Very unlike today’s computers.
Programming had to fit those constraints; the mainstream was looking for efficient ways of programming because performance was a major issue. Remember, resources like memory weren’t cheap like they are today, so paradigms like Immutability couldn’t be at a mainstream scale.
And then, the industry took off, and we got used to Classes and other ways of programming coupled / complex software. Legacy Code was born and
Distributed Computing is all over the place now, making things even more unpredictable (threads).
We are addicted to IDE’s in order to develop software, simply because without them, it’s almost impossible to deal with all the complexity of the code we ourselves are producing.
What happened to the power of simplicity?
I think Alan Kay explains it very well in this talk at an SAP event.
Wake up! We don’t have those resource constraints anymore. We can do better!
Why are we programming like it’s the old days? We don’t have those constraints anymore. Remember that you have in your pocket a computer with multiple cores and plenty of RAM.
Nowadays, we have resources that open the door to new and old paradigms which encourage us to program more flexible, predictable, and most importantly, sustainable software that just f***ing works.
For years, we’ve been programming the same way. Let’s change that scenario– let’s learn other paradigms besides OOP with inheritance classes and MVC, and let’s rule the state of our applications.
Functional programming and its friends aren’t a silver bullet– there’s no such thing, and that’s why we need to keep evolving and creating more effective ways of programming.
This is my first post in English, so expect some misspellings, and please be nice :)
By the way, there’s a Portuguese (pt-br) version of this post.