Simplicity to everyone
Simplicity is a popular topic (KISS, Occam's razor, "Simplify, simplify, simplify", YAGNI, etc) across time, but still is underrated by many people.
As a technician, I dedicated a significant portion of my time to creating a more predictable life for myself. While some may perceive this as unhealthy, it’s a common practice that many people engage in, even if unconsciously. In the past, these behaviors were often referred to as superstitions. However, now, in a technologically advanced world, we categorize them as patterns.
Enterprise patterns
Patterns are prevalent in various aspects of our lives, but the most effective ones have been developed in controlled environments, such as military operations and large corporations that employ individuals with minimal training1.
Software Engineering, especially when it began to scale rapidly, lacked sufficient differentiation, particularly as colleges were unable to produce high-quality specialists in demand.
I clearly remember when Software Engineering interviews centered around Design Patterns from Martin Fowler’s books (almost all his books were used as a source of truth, although people consulted other authors who simplified the learning process), rather than algorithms on LeetCode. At that time, we were all familiar with the concepts, but Design Patterns held greater significance in enterprise software development compared to algorithms and data structures. It did not mean that a candidate can create products efficiently, it meant that team can be scaled and show some increase in productivity.
We were trained as “soldiers“ to describe and identify all the patterns, but one crucial aspect was missing: understanding how to effectively utilize them.
Most of the people whom I worked or stay in touch with while using enterprise frameworks and technologies warmly met new simplified frameworks2, architectures and programming languages, and there is a reason for this shift.
Without taking credits from the contribution made by all these enterprise patterns, frameworks and technologies. But, we must to learn and move forward.
Although we used all of these patterns on daily basis, and fought a huge amount of abstractions and different positions to build every single layer of a software:
Software architecture diagram
DB architecture diagram
Class architecture diagram
And many more
Convincing teammates
The most experienced software engineers (architects, CTOs, principal engineers, you name it) always tried to convince other teammates to keep it as simple as possible, even though achieving absolute simplicity was often challenging. It confused a big percentage of software engineers in every team. In my personal experience, this number could be as high as 75%. But it was our mantra, even though not everyone aligned with it. We tried, and tried again, and again. There was a lot of confusion and misalignment in people’s eyes. It felt too much. But guess what? We tried again. The crucial part of these attempts was not only to make a product easy to develop, but most importantly simple to support and evolve.
Simplicity, simplicity, simplicity… What stays behind of this word? Sure thing, simple is good, however, it is different for every one. And the most important, why did we discussed so much about patterns, where simplicity stands for?
Let’s step back and try to determine, what principles called to simplicity?
Principles called to simplify
We can find many formulated principles, but in this chapter I will cover my personal preferences. There are two fundamental principles that deeply resonate with me: KISS and Occam's razor.
KISS principle
KISS, an acronym for "Keep it simple, stupid!", is a design principle first noted by the U.S. Navy in 1960. First seen partly in American English by at least 1938, KISS implies that simplicity should be a design goal. The phrase has been associated with aircraft engineer Kelly Johnson.
- description of KISS principle from Wikipedia
Keep it stupid simple (this order of words I like more). It means what it says.
On one hand the idea of the principle is repeatability. It needs to be clear and easy to understand for everyone, and can be repeated/supported/improved/changed by anyone who has a task to do so. Scalability, the second goal, is achieved through repeatability and simplicity. For military (Army, Navy, etc.) and corporations it is important for hiring.
The KISS principle is a no-brainer, but it’s tough to replicate. We can sacrifice efficiency in favor of scalability.
For example, we can have a clear and step by step instruction on how to cook a dish, but it won’t be as efficient as can be done by a professional chef.
Occam's razor
Occam's razor is the problem-solving principle that recommends searching for explanations constructed with the smallest possible set of elements. Attributed to William of Ockham, a 14th-century English philosopher and theologian
- description of Occam's razor principle from Wikipedia
Search an explanation with the smallest possible set of elements. Pretty simple as well.
It more touches an a software’s or an infrastructure’s architecture. Let’s bring some instances for clarity:
Build a project with less teams possible involved
The bigger the interface, the weaker the abstraction
A little copying is better than a little dependency
One big dependency better than many small dependencies
Less is more, the goal is to include as little components as possible into a product/project/etc.
Simplification
There is a question “how do those principles align to real life?“ may arise. Hold on, we are almost there.
In every project development, independent of a role, decision can be made from top to bottom or from bottom to top. Independently from a way company operates, close alignment between levels will help to optimize processes and results.
In our case, we have a micro service architecture or a monolith. It requires a bunch of dependencies and enterprise patterns applied to support and develop the product. On one hand everything works great, but from operational perspective simplification should be essential.
All these questions are complex and needs to be reviewed case by case, due to difference in architecture, team(s) structure, team experience, programming languages and other technologies, etc. But we can start from changing our view on the processes.
LOC
The simplest way to understand simplicity is to count lines of code. There are even different standards on product valuation based on LOC number, but, even though it can be counter intuitive, lines of codes is not a good metric. DRY principle uses as mantra for many leads to “simplify” products and make them “scalable”. Even though DRY principle suggests to use it to simplify development, increasing quality and scalability, but the reality is quite not clear there.
The main issue with LOC calculations starts from languages themselves, as Python may have fewer lines of code than Java even with the same amount of code when we try to replicate code without using internal magic.
It continues with interest of developers. They may use some hacks or overcomplicating to decrease lines of codes, but increase complexity and number of bugs. When a team over engaged to save LOC number or something like DRY is forced, instead of creating new functions, people start to patch the current one, even if it’s not the best idea. The result maybe unpredictable. Anyone experienced situations when one place is fixed, but there other ones are broken.
Unnecessary optimizations of saving LOC leads to increase of cognitive load.
Individuals must keep a huge context of the product and, instead of working on a specific task. They try to refactor code and synchronize with teammates to keep quality.
Avoiding algorithms, data structures, and patterns
Apparently, the Computer Science is hard. It requires a lot of time to learn, understand and try before the knowledge can be used for real projects. Meanwhile, many people joined the field without a college degree or another background3, they contribute to many projects we use every day. It’s not a problem, it’s an amazing opportunity to build, create, and earn for individuals and companies. However, people who did not spend enough time learning fundamental knowledge may have a luck of experience to use it.
If an algorithm/pattern/data structure/framework seems to be complex, it definitely is!
Be sure, not every software developer can implement new solutions more efficiently and simpler than they were proposed and agreed upon. Especially it’s true for security algorithms. Never, ever implement your own security algorithm if you do not really understand what is happening there.
If you don’t feel confident to implement some known solution, but it can efficiently solve your task, check Open Source libraries. In the most cases, some Open Source solution can be found. When the library is available, don’e forget to read a documentation.
Team is incorrect
Over-excitement from recently learned technology leads to emotional decisions.
I’ve just returned from a conference where an amazing topic was brought up! We have to use it in prod! Next week! No, let’s do it this week! Oh, no… I’ll do it today!
This happens much often than anyone would like too. However it should not be taken personal. In the most cases it’s not something negative, more a reason of miscommunication or a luck of experience. Frequently, the initiative comes from the least experienced colleagues, not it years, not in technology, but in behavior4. Anyway, when you feel you’re not supported in an initiative, it maybe not because people are incompetent or rusted.
You're fortunate if you have someone nearby who is experienced in a field and willing to spend time explaining things in detail
Most likely the initiative will be ignored or aggressively pushed back5. Learn and build experience, do your best! Your proactive learning will pay you off over time.
Coming back to team incorrectness. They just not ready to take a risk with new technologies. It maybe overcomplicating or time consuming change without a reasonable output for the product. You need more time to convince them or they just know something you don’t. Try to level-up the communication with the team. Schedule a 1:1 with more experienced colleagues to get a feedback. Find a mentor. Be motivated and keep it going.
Readability
In software life cycle, more of the 50% of time of a software we support a product, not creating it. The most of the time developers read code, not write it. That means writing high-quality code is the key, but writing clear and self-explainable code is a priority #1.
Try to avoid magic in your code
There are modern programming languages growing in popularity, like Golang, Rust, etc. They rid off all (or almost all) magic from a language and provide clear, readable code. It requires to write more code initially, but the amount of cognitive load decreases for developers is significant.
But it’s not only magic, it also abstractions (people from enterprise Java, C#, Php, etc, know what I mean). OOP paradigm is great, but it can be abused as anything else. I think Java’s enterprise world is an amazing example of it when a class extends abstract class that extends another class that extends abstract class, etc.
There are also long names of classes and functions. Long functions in LOC. Single files that contain thousands of lines, etc.
I don’t want to say that you need to switch stacks today, I suggest to write as clear as possible code in the stack’s standards. The product should be simple to debug, support, and fix.
The main our goal is to keep code readable with clear understanding of all dependencies. We should have a chance to read code and understand what is happening, without running it or using specific tools.
Repeatability
It’s an undervalued part. Our solutions should be able to be repeated by other team members. It includes transparency in communication, clear code, comments, well-known solutions, libraries, frameworks, etc. From the first looks it fairly simple to do, however, it’s almost impossible to scale.
There could be many suggestions on how to scale yourself, but it always makes sense to start from consistency and communication. Create a proposal, framework, library, or all of that. Share for review. Remind about it consistently. Provide more proposals and try to convince people.
It will pay off. Not today, and definitely not tomorrow, but soon enough. The goal is to build a confidence about intention and goals. Standardization is an opposite movement from individualism and can feel like a fight for a promotion or leadership inside a team. Just do it!
Scaling
Do you think it’s about vertical scaling? Maybe horizontal? Nope… It’s scaling from product and business perspectives.
Documentation, education, support…
Tech department always works in, obviously, technical perspective of solutions. How to build something? How to process more requests? How to make it secure?
But what about business? How will it be used? Who is the end customer? Will it scale for customers from another areas? Can we scale our team to support more users?
When we simplify something, it definitely helps in scaling, but it also starts from scaling’s end. We know the solution should be readable and understandable. It also needs to be repeatable. But also scalable.
If it makes sense, eventually new team-members, people from other teams and departments, other than even companies, will join in using it, integrating into their ecosystem (there many examples as programming languages, frameworks, libraries, and even management stales and project managements).
At this point of time amount of requests may push the inventor into depression, but it’s possible to avoid that. Think about scaling in the process. Add a couple of lines of documentation where it looks not clear. Add screenshots or notes. Don’t forget about warnings and how to(s).
Scaling won’t require too much investment if it’s a starting point. The goal of simplicity is scaling. Keep it in ming and move on.
Thoughts
The covered idea looks simple, but usually open-up with an experience. Many people suggest one or another book to learn the best practices in development, management, or investment, etc. I cannot agree more that books a fundamental part of learning process, however, in a cooperation with consistency and people who are willing to teach and learn in both ways, can speed-up the process.
Subscribe and let’s stay in touch!
By minimal training means to train a person in months or even days without requirements to get a higher education in college or long-term training.
There are many frameworks that provided a simplifications, like Spark, Sinatra, Laravel, Flask, etc.
Many people could be without college degrees, but they are very motivated and live in the field. Their hobby is to learn and write code. This people could be really good, much better than an average person with a degree.
Usually experience is based on years in a field, but it’s not an exception when people just not ready to learn during years and get behind, especially while switching technologies or fields.
There is a reason for that in a style of management, but we will discuss it in future articles.