Code • Life
We are already doing these things for our code; why not do them for our lives?
We have been investing a tremendous amount of effort and thought into how to improve our code so it can run more efficiently, become easier to maintain, have fewer bugs, and be more fun to work with. We discovered many theories and best practices and invented many processes and tools.
Our lives are obviously much more complex than code, but a lot of the ideas for making the code better are actually applicable to making our lives better. These ideas can have a much bigger impact if we use them for our lives. In this post, I’m going to explore some of these ideas.
When we improve code efficiency, we profile its execution to identify performance bottlenecks. We use profiling tools that track and examine a wide spectrum of metrics: I/O latency, memory usage, the execution time and frequency of a code block, or sometimes even the number of executed instructions.
When we try to improve our own efficiency, why not try to “profile” ourselves as well?
For example, if we feel easily distracted, we could write down each distraction and how long it takes us off track. Maybe we can see patterns so we can avoid common triggers of distraction. If we struggle to change an old habit, how about recording each time it happens and why? If we want to form a new habit, why not write it down and track our progress? If Benjamin Franklin could record how he did with his thirteen virtues every day, so can you and I.
When code doesn’t work as expected, we debug it, often as detailed as stepping through every statement. “Debugging” is very powerful, but also very expensive. We do it for the code because we need to get the code to work, but we often ignore it for our lives. Debugging requires self-awareness, intentionality, and the desire to level up.
Next time when you make a mistake, or you wish that you could have done something better, try to sit down and carve out time to “debug” the process. Go through what happened step by step, examine what you did and why, figure out the “bugs,” and take action to improve for the next time.
Debugging is useful for both personal life and professional events. For example, at Medium, we run post-mortem meetings for site incidents, we write RCA (Root Cause Analysis) for major bugs, and we run project retro after a project has shipped. In these settings, we first investigate the reality and list what happened, and then we ask ourselves a lot of “whys.” Every time we’ve done this, we learned a ton.
#3: Design Patterns
Design patterns for software are tested and reusable solutions to commonly occurring problems. Good design patterns not only speed up your work but also teach you how to think about software designs. There are many types of design patterns in different contexts. The classic example is the book Design Patterns: Elements of Reusable Object-Oriented Software.
We could apply similar ideas to life and work as well. A lot of great books and articles summarize how authors repeatedly solved real-world problems and the lessons they learned. We can collect these patterns and evolve them for our own use. What is beautiful about these books and articles is that the authors spent years and years solving problems and writing about their patterns of solutions and lessons, and we can spend a relatively small amount of money and time and save ourselves years of trials and making the same mistakes. I can’t think of a better investment than that.
The approach I found useful is to have a personal library of problem-solving patterns — a written collection of real problems you encountered and the patterns you learned, tried and adjusted for yourself. If you struggle to find a good solution for repeated problems, read relevant books and look for advice, then add them into your library.
#4: Open Sourcing
Most of us have used open source code; some of us have even open-sourced our own code. Open source is great because it lets us learn from others, get feedback on our own work, and benefit from the work of others. Many of the most influential software projects in the world wouldn’t have existed without open source.
Wouldn’t it be wonderful if we could “open source” our thoughts as well? Writing is a great way, and probably the only scalable way, to open source our thoughts. Writing helps us clarify our thoughts, think better and more deeply, get feedback from others, and inspire others.
Open sourcing code enables us to build better software together. Similarly, writing and sharing create a network of ideas that feed off each other, so we can move our thinking forward together.
#5: Using Frameworks
When we code, we use a lot of frameworks. Nobody would build a complex software system from scratch. Good frameworks provide common foundations and suggest best practices, so we can focus on the unique business logic. Great frameworks even make us rethink about programming.
Frameworks for thinking are equally important. They simplify our thought processes and help us focus on our unique goals, so we can make better decisions faster. Thinking frameworks are often generic — they can apply to many different scenarios without losing value. Take Stephen Covey’s four-quadrant framework of time management as an example. It teaches us to focus on important but not necessarily urgent things, like planning, exercise, or self-improvement, which are often de-prioritized because they are not urgent. If we apply this framework to software engineering, production bugs are urgent and important (Quadrant #1), whereas automated testing and tools are important but not urgent (Quadrant #2). We should invest in better testing and tools, so we will have fewer bugs in the long run, and we can spend time on more important things.
Building frameworks for thinking is not only beneficial but also super fun! In many cases, the problem we need to solve is just “one of those”. If you observe patterns across different disciplines, try to abstract the similarities, peel off specifics, and build a framework. This type of synergistic thinking helps you understand the world better and more deeply, and likely you will find the framework can apply to many other areas you haven’t even thought about. It inspires creativity.
We all try to write code that is easy to understand. Good code should be readable and tell what it does. Do we still need comments then? Yes, we do, because comments tell us the “why.” No matter how good the code is, it does not always explain why it is being written in certain ways, or be compared with alternative solutions.
Similarly, it’s very important to “comment” on the things we do with thoughtful communication. People can observe what we do and how we do it, but they do not always understand why we do it or why we do it in certain ways. Without knowing the why, people may get confused, defensive, or even misunderstand what we do; however, once they know the why, they become supportive, encouraging, and even get inspired.
Thinking about and articulating the why helps ourselves as well. Maybe there are better alternative ways of doing it, or maybe we have other more important things to do first.
Logging is a common practice to track important events or message exchanges when a software system runs, so we can go back to understand its execution or triage issues. Without logging, troubleshooting production issues become extremely difficult if not impossible.
Just like logging in code, writing down the major events, decisions, successes, lessons, etc. in your life and work could be tremendously useful. It doesn’t mean you have to write a 500-words diary every day. The life logs could be just a few sentences each time. The key is to build a habit of writing them down and looking back regularly. I keep a personal log with the Day One App and a work log in Evernote. I’m always amazed by how much I learn just by reflecting on my past self.
After you write some code, how do you know it works? You may think that’s easy — you can test the code. Testing has been widely adopted to improve code quality before shipping it. We invented tools and frameworks to make testing easier. The Extreme Programming (XP) practices even suggest writing test cases before implementing the code, which is called TDD (testing-driven development).
It might not be always possible to live a “test-driven life”. When we need to make a decision, how can we know we are making the right decision?
Although it is often difficult to fully test an idea or a decision before it is applied to real life, we could at least test it by running it through the principles that reflect our fundamental beliefs and what we learned in the past. We could also test it by asking for feedback from people who are believable. If a decision passes this test, we should at least know it is good enough that we can live with the consequences. If you want to get inspired by principles in life and work, I highly recommend Ray Dalio’s book, Principles.
#9: Style Guide
In coding, we often create opinionated style guides to make code looks consistent. Sometimes style guides also suggest best practices, but most importantly, they save debates about how to format code, which is usually the most contentious but the least consequential topics.
In life, we also need to make decisions about many trivial topics. Obviously different people trivialize different things—what to wear, what to eat, which path to take to commute, etc. They are all small things, but mental energy spent on these topics adds up. Making consistent decisions upfront on these topics helps us focus on more important things. For example, Steve Jobs wearing the same clothes every day is akin to a programmer choosing tabs over spaces for every indent.
Life is a way more complex system than software. It is easy to get caught up in the blizzard of things coming at us in life. Take a step back and observe ourselves and surroundings objectively at a higher level. This higher-level perspective allows us to use our engineering skills to figure out how things fit together, identify and diagnose problems, improve the system, and finally achieve our goals. Remember, we are also engineers to our lives.
Can you think of other things that we do with code but not with ourselves as often? Write a response!
P.S. This post is a revised version of a post I wrote in 2015. I want to thank Wanmin Wu for always patiently listening to me when I talk about random stuff and inspiring me with her thoughts. Thank Dan Pupius, Jean Hsu, Evan Hansen, Herzog for letting me bounce ideas off them. Thanks to many for their great responses to my original post, especially Ryan Huang and Buster Benson, from whom I borrowed some ideas.