When I landed a job at Microsoft fresh out of college, I was eager to dive into the deep end of complex coding and mind-boggling algorithms. But to my surprise, I found that most things were actually refreshingly simple and straightforward. Gone were the days of pulling all-nighters to wrap my head around some convoluted code. I found myself easily able to contribute to projects without feeling like I needed a degree in computer science just to understand what was going on. I couldn't help but wonder, "Nothing magic here. I can manage to do the same thing. Why does Microsoft need so many senior engineers and architects?” After many years, when I became the leader, I heard similar thoughts from the newly hired young engineers, occasionally.
@ymc9 has recently published a post about simplification:
In the end, he concluded:
Good engineering leaders chase simplification relentless
In addition to having the desire, individuals often overlook the importance of experience, knowledge, and skill needed to simplify things. This implies that one must encounter enough complexity in order to attain simplicity.
Zen master Weixin Qingyuan of the Song Dynasty of China proposed the three stages of Zen meditation:
At the beginning of Zen meditation, mountains are mountains, and water is water; When one has insight into Zen, mountains are not mountains, and water is not water; When one is completely enlightened in Zen, mountains are still mountains, and water is still water.
I feel the journey to simplicity is quite like the three stages of Zen. I will illustrate it with my own journey of learning and understanding the design pattern.
During an internship interview, I was asked to discuss at least three design patterns I knew. Despite never having used them in any projects, I was proud to be able to list five patterns eloquently.
The pattern is just a pattern for me at that time. I did memorize some of the common patterns, such as Factory Method, Adatper, Visitor, etc., and was able to recognize its use when I saw it used by others. The only value for me was to converse with others about the pattern by name in a somewhat intelligent fashion, even though internally, I felt ridiculous to label something as simple and obvious as the Strategy pattern.
When I started to work on real projects and experienced how easy it made me to contribute to them, I began to understand the benefit of using design patterns in software development, such as reducing complexity, improving maintainability, and promoting code reuse.
Suddenly, patterns became the hammer in my hand. So for every feature I need to implement, I always ask myself: Which pattern could I shoehorn into my code? It’s like the more pattern I use, the better design of my code will be. To defend myself, we all do this-it’s not related to programming or design patterns. Once we learn something and get comfortable with a new technique, we want to use it everywhere possible.
However, not before long, I found myself struggling to apply design patterns effectively. Force a pattern where it doesn’t fit would be a disaster. So more patches have to be added later until they get refactored.
I started asking some questions about the design pattern like below:
- Why are there 23 patterns instead of 36?
- Do they still apply in dynamic languages where restrictions can be bypassed?
- Can I create my own design pattern?
Through continued learning and practice, I rediscovered the true nature of the design pattern. It is meant to help us resolve the real problems rather than the end. You should see the patterns evolving out of your code rather than being forced upon it. Sometimes, I would come up with a pattern that I couldn't even remember the name of. and that's when I feel like I truly know them. I not only appreciate their power but also recognize their limitations. As Muger said:
I never allow myself to hold an opinion on anything that I don't know the other side's argument better than they do
So whenever I decide to adopt a pattern, I’m quite sure about the price I need to pay for it. Alternatively, I might decide not to adopt the pattern, knowing that I could do so if and when it’s become necessary.
Patterns are patterns again, but I get the freedom to apply them more appropriately to chase simplification.
The ZenStack toolkit we are building also aims to provide ultimate simplicity to building the web application based on the sophisticated experience we gained from building several SaaS products.
It uses the declarative data model on top of Prisma, adding access policy and validation rules, from which it will automatically generate APIs, including OpenAPI, tPRC route, and hooks for you.