Reduce Complexity
Higher complexity makes software development harder and less fun. Learnings from reading book "Philosophy of Software Design".
I recently finished a reading group about “Philosophy of Software Design”. It was a great book covering many aspects of coding in a high level. Mainly, the book is about reduce complexity. So here are my takeaways.
Complexity
Complexity is anything related to the structure of a software system that makes it hard to understand and modify the system
It can show in many forms
Change amplification: A simple change requires changes in many places.
Cognitive Load: In order to change one thing, we need to know many other things.
Unknown Unknowns: Not obvious which change is required to achieve a certain task.
and complexity is usually due to the following reasons:
Dependencies: We introduce them when the code gets more complex.
Obscurity: important information is not obvious. It can come from inadequate documentation or design issues.
Centering the book about complexity is a wise choice because it balances technical detail and high level principle well.
Strategic Programming
Tactical Programming means getting something working, such as a new feature or a bug fix. Strategic Programming means on top of that, we need to avoid introducing unnecessary complexities in order to finish our current task faster.
Programming is an iterative process. It is hard to know from the start which design choice is the best. When we add new things, we need to constantly making new choices, adjusting existing structure to fit new features well. Tactical programming can work well in the beginning of the code development phase, such as in startup and research phase. But in a long term, strategic programming payoff better because it will make the code easier to develop.
Unfortunately, I was probably a tactical programmer. When I read the following sentence from the book, I was thinking “lol, that’s probably me."
Almost every software development organization has at least one developer who takes tactical programming to the extreme: a tactical tornado. The tactical tornado is a prolific programmer who pumps out code far faster than others but works in a totally tactical fashion.
I can now better understand why my colleagues aren’t very happy about the code I checked in. I promise, I am pivoting towards strategic programming.
Research Code
What is research code? It is a piece of code that is mainly used for fast iteration and experimentation. It may be in a relatively crappy state, without much test coverage, without much design or documentation.
I used to think writing test is necessary. However, writing tests is time consuming and can hurt idea flow, especially for research. Those code usually has high dependencies and requires data or more compute to fully cover the code. If we require rigorous test in the beginning, it can make the development less fun and make adding new changes more challenge. So when we review an research code, align our intention well and not block those fast experimenter.
Deep Module vs Shallow Module
Module should be deep. It means less interface but more powerful and intuitive functionality. For example, for an code editor, instead of having `write_line`, `write_character` or `write_word` options, we can use `write` only and handle all the cases implicitly within the method.
This usually means standing in the shoes of users — understanding what they need to use the most often and making those solution easy and powerful.
Comments
Comments are important but often get ignored. They provide additional helpful information for the code.
They can be high-level about the design.
They can be about what the code is doing (instead of how).
They can help clarify some low-level detail.
They can also help the author design better code.
I didn’t realize the importance of comments until I read this book. Previously I often think good code doesn’t require comments. I am wrong. Code and comments stay at different level. No matter how well a code is written, readers will be happier to read 1 sentence of comment / docstring instead of 50 lines of code.
Design at least twice
When we implement a new big feature, we should think about alternatives and considering those pros and cons before diving into actual implementation. They can be fast for small features and time-saving for big ones. IMO, a good rule of thumb is to use >=5% time in design: ~10 minutes in design if you expect the implementation takes 3 hours.
I didn’t pay enough attention to design. This caused me wasting hours of work
I might have ignored existing solutions and rebuilt the wheel.
My colleagues or myself find those features unintuitive and hit our feet.
Due to suboptimal solution, the development becomes harder and less fun. So I will need to refactor the code later.
So I would encourage design at least twice. Having two options at least for any major features we wanna add. Be humble and be willing to listen to others’ suggestion in the beginning. This can save a lot of time in the long run.
Outro
Overall, I highly recommends this book. It is short and easy to read. It can help build good habits for new programmer and hone skills for the experienced. They also have a free version online. Hope you find this helpful :)