The world is full of software. Coding covers everything from local scripts that help us be more efficient to large-scale solutions for leading enterprises and everything in between. Software can be shaped using different techniques and patterns to create microservices, build monoliths, and break things down into front-end and back-end.
Good software at its heart is not about following a design or applying a specific pattern. Instead, great software starts with us, the people who create it. Any good practice or design becomes meaningless if we, the people, don’t honestly believe in the software we are shaping.
For that reason, more than applying a design pattern or particular architecture, what I have experienced here at Wizeline is the joy of teaming up with people as passionate as me to follow best practices and care about the principles and values beneath these practices.
A value or principle works like a compass. It helps us make decisions when it matters the most: should I do this, or should I do that? In other words, it’s a guide to help us choose between paths of action.
According to Robert C. Martin, building great software is hard because not only does it take knowledge and skills but also the right mindset to incorporate these values throughout the lifecycle of the project:
- Even if you want to be fast, you still have to balance following best practices.
- The trait of good designs is that they are easier to change.
These values connect at different levels and at different times when designing our software. For example, let me describe a project I worked on here at Wizeline.
Our team was hired to create an MVP (Minimum Viable Product) for a big client. We were given a short amount of time to prove the concept, and if correct, we would continue shaping the project by adding more features. We were a four-person team collecting the requirements and breaking them down into user stories. We started by picking up the highest priority stories and shaping up the software. We had a short time to complete the project, so at some point, we came to a crossroads where we entertained the idea of not writing unit tests, skipping the decoupling of components, or not separating the business logic from our services or controllers. Thankfully we didn’t make any of these decisions. We wanted to be fast and prove the MVP but not by accumulating technical debt.
The client’s company adopted the MVP, and then we were tasked with adding more features and scaling the whole project significantly. Had we cheated on our values, we would have ended up with a system so interconnected and intricately decoupled that every change, regardless of how trivial, would take us days or even weeks to deliver. We would have had to explain to our clients why we couldn’t build the product at the same pace as before.
The experience provided me with a few insights: Because we stuck to our principles and values since the beginning, we did go a bit slower, but it paid off greatly by creating a solid architecture that was easy to understand — making it easy to code, maintain, and extend. This also made us, as a team, happier and willing to code any new features that came later.
How Can We Be Fast and at the Same Time Develop Code That’s Easy to Change?
There are multiple techniques and best practices widely adopted nowadays: Decoupling, DRY, SOLID, and Clean Architecture, to name a few. But remember, more than applying best practices, understanding the underlying principles and values makes the best practice shine.
For example, why do we care about creating decoupled components? Because by isolating concerns, we make our software easy to visualize, test, and change. In our project, we created an architecture where changes to the database models didn’t affect our business logic or the services that interacted with them.
Why are SOLID principles like the SRP (Single Responsibility Principle) practical? Because identifying actors and reflecting them into a module is mirrored by a change in just that module, again making the software easier to change. In our project, our architecture made it easy to spot the different actors who would trigger the process in the form of actions to our services.
I’m not working on that project anymore. However, the sentiment remains: Every time I commit a new change to the codebase, I think about this experience and ask myself, “Does this change I’m committing make our codebase easier to change?” “If another teammate or I have to work on this feature again, will it be easy to change?” If the answer is no, then what can I do to make it so?
In conclusion, there are no shortcuts to building great software. It takes passion and love for what you do to continue adopting or start picking up these values. It also takes courage to be the catalyst of change in your project so that everyone starts seeing the real benefits of these values. Chances are, you will work on different projects across your career, and landing on a project where the former team followed these principles would make a huge difference for you and your team’s morale. It did for me!