👋Hi there! It has been a minute since I’ve been able to send one of these. I started a new job and it’s been a whirlwind. I also have a one year old in my house. Life has been great but quite busy. I made a decision to drop the newsletter and blog for a few months while I adjusted to the new normal. Things are still busy, but I’ve learned a lot the last few months and I’m hoping to clear some time to share. Tonight I’ll start with my first new article since July. But before I do, a quick note about that new job.
I now work at Kustomer as an Engineering Manager in our Durham NC office. We’re a fast-growing startup with plenty of money and a lot of interesting technical challenges. If you’re interested in joining us in Durham or New York City, please feel free to reach out. We have openings for Front End Devs, Back End Devs, and an Engineering Manager (NYC only).
On the front end we’re building a complex enterprise application in React & Redux and put a heavy emphasis on performance and responsiveness. We have lots of interesting challenges around scaling our UI patterns, introducing TypeScript, and improving the usability of some complex UI features. Job Postings: NC / NYC
Our backend stack is Node Microservices on AWS. We have a lot of cool challenge around reliably receiving a huge load of incoming messages, adding AI functionality to the platform, and making things extensible for our customers so that they can customize us to match their business needs. Job Postings: NC / NYC
We’re also hiring another Engineering Manager in NYC. If you’d like to work with me as a peer and help figure out how to grow successful teams in a high growth environment (the team has tripled in 18 months, and we’re aiming to double again next year), please reach out! Job Listing.
Happy to share more to anyone interested, feel free to respond to this email directly.
I had the opportunity this week to walk a software engineer who is new to the field through some lessons I’ve learned over the years about how software engineers add value to the business. It seemed generally applicable, so here’s a cleaned up version of what I shared.
It can be easy to think of software engineering work as a series of task where you’re given instructions and you make the computer do what the designer / PM / CEO asked. Or as a series of fun problem solving challenges that you’re somehow getting paid to complete. Both of those views will eventually lead you to make suboptimal decisions when it comes to helping your business and growing in your role though. Instead consider the following definition:
> Software Developers create value through shipping working code that solves important user problems in a predictable manner.
This captures a number of important things.
> Real Artists Ship - Steve Jobs
Software Engineer’s super power compared to other roles is that we get to build. We create new things, add new behaviors, and ultimately (for a product company) control the shape of the product our company is built around. This only has value when software actually ships though. When we’re not shipping, it’s actually worse than just being slow to deliver value, because of a few non-obvious factors.
First, unshipped code rots. When we leave code in a branch 90% done, it doesn’t just stay the same. It’s quite common for our situation to get worse. Our teammates check in code that may cause merge conflicts, or worse just doesn’t take into account the unshipped code and sets us up for subtle bugs. And when we do get back to the work we’ve often lost valuable mental context that makes any remaining work or testing harder and more error-prone.
Second, we learn from shipping! It’s quite common in software development for a developer or team to complete 90% of their feature according to the spec, only to find that they have another 90% of the work to go. Doing the work to push things through to production inherently de-risks things, because we learn what the challenges are, and we know how long the work took. Up until then, we will always have unknowns. And when software goes out to users, we get to hear their feedback as well. Shipped software lets us learn from our users (and from the performance of our system) and make adjustments that we wouldn’t have known about if we sat on the code.
So how do we get to shipping? First, it’s important to push things through to completion rather than allowing ourselves to jump from project to project, making progress without finishing, and incurring a lot of cost from context switching. Soemtimes this may mean imposing kanban style work in progress limits on ourselves. Second, its often helpful to break things into smaller chunks. Small code reviews are easier to complete, test, review and verify. So multiple small changes will often go through faster than the same changes bundled together into a big chunk. This can go too far, but as long as your changes work in isolation and provide value, I’d encourage erring on this side when in doubt.
> [We Prefer] working software over comprehensive documentation - The Agile Manifesto
Software engineers are responsible for their code working. At the simplest level that means delivering code that doesn’t crash when run in the intended way. As we grow and mature as developers however, we should aspire to learn to write code that will scale to any reasonable load the system might see (and maybe even to unreasonable loads), code that handles odd input or context gracefully, and code that is easy to modify and maintain. We should also take responsibility for proving that it works; writing tests, making the code easy to monitor in production, and providing good logging for debugging all fall under a software engineer’s domain. We also should make sure that our definition of working matches what the business needs, not just a pedantic reading of whatever spec we’re working off of. More on that in a moment.
Just really funny- What the Customer Wanted expanded pic.twitter.com/kdr7HKTSDy— Frank Spillers (@farreaching) August 13, 2016
Software Engineers can be quite inventive in the ways they write code without solving important user problems. Some common routes:
These are ultimately issues of ownership. When we’re invested in our work, we will want to work on useful problems and make sure they produce real value. If you’re consistently not feeling that way, it may be time to find something else to work on.
> The challenge and the mission are to find real solutions to real problems on actual schedules with available resources - Fred Brooks
Ok, now we come to the section that is the boring part for many software engineers. But as somebody who has recently converted to the management side of the fence, the ability to ship predictably is incredibly important.
It’s important for software engineers to ship predictably in 2 senses:
Estimating software engineering projects is not an exact science. Nobody reasonable expects estimation perfection from software engineers, especially those new to the field. Instead we aim to be as accurate as possible, and especially to be transparent as those estimates change over time.
When we encounter obstacles, it’s important to be realistic about what they mean to schedules and update the important people in a timely manner.
For those working on a product team that may be a manager and a PM, for those building something solo, that may be the customers or internal users of the software directly. It’s never fun to say something is going to be late, but its always better to say that we’ll miss a date that is 2 weeks away than to tell somebody for the first time that you’ve missed the date that was 2 days ago.
Communicating about the scope of work is just as important as schedule. If we find out a piece of a feature is unfeasable or we dropped it due to time pressure, its important to communicate that. Depending on your team/product, that may mean sharing with people directly, updating documentation, or just making the new behavior clear in an interface.
Nobody starts out their first software engineering job with a fully evolved sense of how to estimate, scope and document their work. Most have no clue how to think about building a system to be scalable or when to escalate problems to other members of the team. These are skills learned through hard experience. Make sure to always be reflecting on what you’re experiencing though. Experience combined with reflection is a powerful mixture, and eventually will lead to growth. Good luck!