TodayI'll share some of the software engineering "soft skills" I've learned from my first 10 years on Google Chrome, where I am a Senior Staff Engineering Manager. On my 10th anniversary, I wanted to reflect on some of lessons that have stayed with me. I hope these prove useful to you during your career.
Becoming a good engineer is about collecting experience. Each project, even small ones, is a chance to add new techniques and tools to your toolbox. Where this delivers even more value is when you can solve problems by pairing techniques learned on one project with tools learned working on another. It all adds up.
The following pointers should help most junior or mid-career developers move forward, deal with changing technology, and build complex systems while following the standard processes in the software engineering paradigm and discovering new best practices. Apply first principles when you can. Learning to break down problems into smaller pieces is one of the most important skills in life.
This means you can discern tasks that add value and help your team focus their energy in that direction. It also means you know how to avoid work that doesn't provide the team/company value - the best engineers can even steer whole teams away from work that isn't that useful. Work on what matters most.
I often get asked, "How do I know if I'm making the best use of my time?". There will almost always be tasks you can fill your time with to "feel" busy. The real trick here is making sure you are working on the right things. If you want to move mountains, focus on tasks that move the needle, even if that movement is small.
As engineers, we can sometimes rush to solve a problem right away so it feels like we're making progress or looks like we're being responsive to stakeholders. This can introduce risks if we aren't fully considering causes and consequences. Put another way, critical thinking is thinking on purpose and forming your own conclusions. This goal-directed thinking can help you focus on root-cause issues that avoid future problems that arise from not keeping in mind causes and consequences.
I've found these questions often help. Sometimes we'll address the symptom of a problem, only to discover there are other symptoms that pop up. At other times, we might quickly ship a solution that creates more problems later down the road. With a lens on critical thinking, we might challenge assumptions, look closer at the risk/benefit, seek out contradictory evidence, evaluate credibility and look for more data to build confidence we are doing the right thing.
For example, a common mistake I've seen engineers make is assuming correlation implies causation (i.e. just because two things correlate does not necessarily mean that one causes the other). A critical thinker might push back on assumptions such as this, asking why we believe them to be true.
The fundamentals are the foundation of any software engineering career. There are two layers to them - macro and micro. The macro layer is the core of software engineering and the micro layer is the implementation (e.g. the tech stack, libraries, frameworks, etc.).
At a macro level, you learn programming concepts that are largely transferable regardless of language. The syntax may differ, but the core ideas are still the same. This can include things like: data-structures (arrays, objects, modules, hashes), algorithms (searching, sorting), architecture (design patterns, state management) and even performance optimizations (e.g. eager vs lazy evaluation, memoization, caching, lazy-loading etc). These are concepts you'll use so frequently that knowing them backwards can have a lot of value.
At a micro level, you learn the implementation of those concepts. This can include things like: the language you use (JavaScript, Python, Ruby, etc), the frameworks you use (e.g. React, Angular, Vue etc), the backend you use (e.g. Django, Rails, etc), and the tech stack you use (e.g. Google App Engine, Google Cloud Platform, etc). There involve details that can be valuable to gain expertise in to be effective, but are not always transferable.
That said, pragmatically, no one has time to learn everything at the beginning of their careers. There comes a point when you shouldn't over-index on the fundamentals and learn what is needed to actually build applications for the real world. This is where the "learn by doing" approach comes in.
Understanding the fundamentals well can help you write more efficient code. This includes concepts such as time complexity (the time it takes to run your code), memory usage, and the trade-offs between performance and maintainability. These ideas allow you to make trade-offs that are helpful when building any reasonably large application. Speed is often critical for modern applications and can often impact end-user experience in a noticeable way.
You can use the knowledge you've gained to make better decisions about which technologies to use and which ones to avoid based on the goals and constraints of any project. This can help you avoid the pitfalls of choosing the wrong technology or the wrong tool for the job.
Software engineering involves thinking about many different layers - the core languages, the implementation, the infrastructure, the tools, and the people. Only having a surface-level appreciation for these layers can absolutely let you build faster. But really knowing the fundamentals (including O(n) time complexity) can help you go that much farther, especially when the landscape of languages and frameworks changes over time.
This quote has stuck with me, because as engineers, it's far too easy to start from a place of wanting to use specific solutions - whether due to popularity, developer experience or just personal preference - and try to find a way to rationalize using them. Instead, we should focus on who we're building for, what problems they have, and how the current options available are falling short.
Great user experiences come from combining both points of view - both the customer and technology. Show people what you think they want and pay attention to what they say. There is of course, immense nuance to this problem space - what engineering choices will allow you to deliver a great experience on mobile hardware? What choices will impact engineering velocity? or scale? or hiring?. Ultimately, we benefit from having a relentless focus on the customer first and then navigating what allows us to address their needs within the constraints we have to work with.
Business success depends on customer satisfaction which often translates to user experience in the case of software. Understand how the end-users experience the product or service. Make sure your solutions do not hamper their ability to do their jobs efficiently. If you are in a position that allows you to interact with end-users directly, attempt to understand their needs and pain points better.
When picking new skills to learn or use, don't be afraid to choose something that's boring and not in the news. FOMO may not be productive when it comes to technology whether it be languages, frameworks, and libraries and tools. While it's important to know what to use, your main goal is to deliver an excellent final product. Please don't chase the new and shiny technologies unless you think they add value to your solutions. At the same time, don't shun something because it is not being talked about enough.
At the same time, personal and hackathon projects can be a great opportunity to learn new tech. Many of us have fewer opportunities to start something completely brand new, as opposed to working on an existing codebase where many decisions have been made. Such projects can be a low-risk way to research new tech, evaluate its strengths and weaknesses (at a small scale) and build up some first-hand knowledge that could be valuable to you in the future.
Learning should be a continuous process - people who claim to know everything about a particular technology are often not experts. Real experts are proficient with the technology but realize there is always scope for learning and improvement. Curiosity drives learning - so if you are curious about a new framework, google it, read the docs, try the tutorials, read the source! Learning need not happen in a classroom. It can happen anywhere, anytime. Take half an hour each day to read a chapter from a textbook, listen to a technology podcast, read development blogs or learn a new programming language.
Having this confidence lowers the expectation that Senior Engineers have to know everything. You absolutely don't need to have all the answers, but being able to admit you're human and are committed to figuring out how to solve problems with your team is the important part.
It's important to teach your team how to handle mistakes with humility and the desire to learn and improve. The real world isn't perfect and it's totally okay to show your team it isn't perfect to prepare them for it.
In the early stages of open-source projects, it's common to think like an owner. You often directly own proving out value, working on features, answering issues and advocacy. This can be great for getting something adoption, but may not be the best way to scale a project later down the line when staffing changes or your own time gets limited.
After the initial crunch, another way to think of evolving your role is towards being a caretaker, rather than an owner. A caretaker might focus on scaling themselves out. This can be done by sharing as much knowledge as is possible with other maintainers, contributors and the community (via design docs, code comments, and other documented best practices). It also helps to grow the pool of reviewers with enough context to make the right decisions when you're no longer as involved.
One of the greatest skills you can master is learning how to learn. This should be a priority over say, just going deep on particular programming language or framework. It helps to stay curious. Once you have experience with this, you may question if you should aim to be a specialist or a jack of all trades.
3a8082e126