10 Things I Learned After 6 Years as a Software Engineer
This year is my 6th years as a software engineer. Upon seeing Addy share what he learned from his 10 years at Google, I began to reflect on my own experiences over the years. I've compiled 10 insights that I've gathered during my journey. Here they are for you:
Maintaining a Problem-Solving Mindset
From my observations, the common trait among those who excel in their work through technology is their ability to maintain a problem-solving mindset. They are often the first to think of a better way to address existing issues, typically related to efficiency. It's not that they have an exceptionally keen sense of smell or are particularly skilled in technology, but rather that when they encounter a problem, they don't just complain about it. Instead, they start thinking about why no one has solved it yet, how it should be solved, and then they implement the solution. This mindset is particularly rare in the workplace.
When I was at a startup working on a graphic design app, designers would create templates and hand them over to me for implementation. We had many templates, and testing how they would appear on different screen sizes required a lot of effort. The number of tests was equal to the number of templates multiplied by the number of screen sizes. Later, I used Puppeteer to write a script that automatically generated screenshots for different screens and templates, which I then handed over to the designers to review one by one. This saved a significant amount of time. While this task wasn't technically challenging, it solved a crucial problem.
The problems that need solving at work aren't always technical. I enjoy chatting with non-technical colleagues to understand their workflows. Often, the bottlenecks in a project aren't due to using the wrong or outdated technology. By understanding their processes, I've discovered that some of their tasks could be exponentially reduced with a simple script, something that non-technical colleagues might not easily realize.
There are many such examples. Once, while chatting with an operations colleague, I learned that they spent a lot of time querying content from a news management backend and manually copying it into Excel. This often took them an entire afternoon. Later, I created a feature that allowed them to export the data directly to Excel with a single click. They found it incredible, but from a technical perspective, it was quite simple. This made me realize that non-technical people often don't know what can be solved with technology, so it's up to us, the technical people, to proactively understand their needs.
Another time, while having lunch with a tester, I learned about their testing process. They would use mind maps to outline test cases and then execute them one by one. The pain point was that they had to manually maintain a document listing the results of these cases, including screenshots and request responses to prove the tests passed. This was not only tedious but also hard to track. So, I created a small demo web app where they could upload their mind maps, generate case items directly from them, and record request logs during testing. After testing, the logs would be uploaded to the platform, allowing them to see the entire process for each case. This demo was later used in most of Huabei's frontend projects, although I heard it has evolved significantly since then.
Understanding Your Users
I consider myself a programmer with some product sense, as I often create small products of my own. However, when I first started working, I was too engrossed in the technical aspects, focusing on things like refactoring and improving build speeds. During my promotion interview at Alibaba, I was asked a question that left a lasting impression on me: "Do you understand how your users use the product you're working on?"
This was something I had never thought about, and I was speechless. It might have been just a standard interview question, but it made me realize how much I had overlooked. At the time, we were working on an internal news management backend used by editors. We had a group chat with these editors, but it was mainly used for reporting bugs. I was so close to these users yet never took the time to understand their experience. If I had talked to them, I might have gained unexpected insights. Perhaps they would have complained about the slow loading speed, and we could have focused on improving that instead of debating which frontend state management library to use. Users don't care whether we use MobX or Redux.
Don't Measure Others by Your Own Standards
One of the biggest mistakes I made early in my career was measuring others by my own standards. I've been obsessed with programming since I was young, and it's my greatest passion. I spent almost all my time on technology. I naively believed that all programmers should be like me, treating technology with idealism. The friends I made online were all like this, so I was particularly harsh on my colleagues, even looking down on those who treated programming as just a job. Looking back, this was a very wrong mindset. Everyone has their own pursuits, and technology is just one of many interests. To others, I probably seemed like a "weirdo," maybe even a bit of a "show-off."
Keep Learning and Be Open-Minded
Every day, I discover the latest technologies and technical thoughts on Twitter and Hacker News. I follow many open-source library authors, allowing me to stay updated on what they're thinking about and working on. This proactive approach broadens my perspective and gives me a wider range of solutions when tackling problems.
Don't limit yourself to your own field. I also follow people who write Rust, Go, and iOS/Android apps. The key to learning is understanding the problem-solving approaches behind these technologies, as they might be applicable to your own domain.
Continuous learning is the most important factor in staying ahead of your peers.
Think Before You Code
I code very quickly because I've been doing it for over a decade. For me, implementing something is often just a matter of writing code. This led me to start coding without much thought, which often resulted in unforeseen issues halfway through, requiring redesigns and rewrites. A former boss, who was also an experienced programmer, once told me during a discussion about a new project, "Don't rush, think it through before you start coding." This advice has stayed with me. Now, before I start coding, I always think through the entire design process, avoiding unnecessary rewrites.
Respect Your Users
When working on open-source libraries or internal platforms with few users, it's easy to release code without much thought. However, working on a product like Huabei, with its massive user base, made me realize that code releases are a completely different experience.
Ant Financial has a "three-step rule" for code releases, emphasized from onboarding to daily work: "canary release," "monitoring," and "rollback." Before releasing code, you need to ensure it meets these three criteria:
- Can any issues be monitored after the release?
- Can the code be released incrementally rather than all at once?
- If something goes wrong, can the code be rolled back? How?
After working on a product with such a large user base, I became much more cautious about code releases. I remember once making a simple HTML change, but I still spent several minutes reviewing the PR diff, thinking about potential issues.
Although Ant's infrastructure makes it easy to implement these three steps (with mature release platforms for canary releases and rollbacks, and robust monitoring libraries), and even following them doesn't eliminate all bugs, this mindset is valuable. Even if I move to another company, I'll still ask myself these three questions before releasing code.
Cross-Team Collaboration is About Mutual Benefit
In large companies, sometimes you need to collaborate with other teams, whether it's using their APIs or having them develop new ones. This can be challenging. I used to naively think that if what we were doing was beneficial to the business, other teams would naturally collaborate. However, in reality, teams are more concerned about what's in it for them.
Put yourself in their shoes: collaborating with another team increases their workload and risk (higher QPS, more code to maintain). Whether they agree to collaborate depends first on whether it's a top-down requirement and second on whether it benefits their KPIs.
So, I learned that when persuading another team to collaborate, it's essential to first understand what's in it for them, rather than just talking about the project itself. This makes collaboration more likely.
Speak Their Language for Unexpected Gains
Research shows that if you communicate with someone in their native language, they are more likely to accept your views and be friendlier. I found that this psychology also applies to technical communication. As a frontend developer, when discussing technical solutions with backend developers, using more backend terminology and approaching the problem from their perspective makes them more receptive.
Since I'm a full-stack programmer in my spare time, it's easy for me to switch contexts and understand others' perspectives, making communication smoother.
Understand the "Bad Code" Written by Predecessors
Here, "understand" doesn't mean understanding the logic of the bad code, but rather why it became bad code. I often hear colleagues complain about how poorly written some old code is, but in many cases, the bad code wasn't due to lack of skill but rather the limitations of technology and the complexity of the business. The more code I write, the more I understand the existence of such "bad code." If you come across bad code, don't rush to refactor it; it might contain special business requirements you're unaware of. If you don't need to touch it, it's best to leave it alone.
Find a Balance Between Technology and Work
In my early years of working, I was obsessed with trying to apply every new thing I learned to my job. I believed that only by using a technology in real work could I truly learn it.
This mindset is flawed. Learning a technology doesn't necessarily mean you have to use it at work. Work is work, and learning is learning. Work serves the business. When I was at a startup, I once used a library I had just learned in a project, and due to some unknown issues, it caused delays. My boss angrily said, "The business is not your testing ground."
Later, many "juniors" asked me for advice, feeling that they couldn't apply what they learned to their work and thus felt their skills weren't improving. I think this is a misconception.
While it's best to apply what you learn to your work, it's not always possible. However, not using it at work doesn't mean you haven't truly learned it. Many people misunderstand technical learning. For me, the essence of learning a technology lies in understanding its "Why," "What," and "How." Whether you use it at work is less important.
For example, when I first encountered Redux, I didn't just learn how to use it; I was particularly interested in its philosophy, what inspired its creation, and how it differed from other libraries. Following these questions, I learned more, such as how Redux was inspired by Elm, which led me to explore functional programming and immutability. I also followed Dan (Redux's creator) on Twitter to see what he shared and how he viewed his creation. Even though I never used Redux at work, I learned much more than just Redux itself. I might forget Redux's API, but the underlying knowledge is invaluable and unforgettable.
Work, on the other hand, provides a real-world scenario to help you think practically about new technologies. You need to consciously consider whether a technology is suitable for your work, what problems it can solve, and why it is or isn't a good fit. When learning new technologies, thinking about these questions is what true learning is about.
🎁 If you like this post, try explore my store PaddingLeft. I made some fancy developers lecklace that you might be interested.