Hack it together or pull an all-nighter. Skip the integration tests and pray for a miracle. Do away the rigid design pattern and fix it later (spoiler: this never ends well). Rushed builds and decisions early on can lead to issues that blow up at scale, and we find ourselves dug into our own ditch once again.
Can we not have nice things?
Well, I believe we should aspire to have things that are nice enough in the face of disorder. Beyond the point of “nice enough” the same amount of effort yields marginal results. What we need is good judgement to weigh the many tradeoffs in a software project — what to prioritize, what to do later, how much time to spend. Judgement is a skill, and everyone from any skill level or any role - engineering, design, PM, and so on - can benefit from working on it. After all, who doesn’t want to work less but get more done?
By trying new things myself, making mistakes, and recalibrating time and time again, I’ve come up with a few rules for building software I wish I had known sooner and that I hope you might find handy.
We shouldn’t try too hard to fight the flow of changing tech and business requirements. There are too many unknowns for us to even attempt to grasp early on. Instead, we should deliver often and in small but valuable chunks.
We shouldn’t be hung up over “the launch” because doing so feeds the delusion that we have a perfect product and we completely understand the needs of the target user, so they will pay for it with their hard-earned money straight away. This is a fairytale.
Instead we would benefit from a fast and actionable loop of shipping improvements and getting feedback - metrics, interviews, and so on. Doing so means making small adjustments in the right direction before investing too much in a potentially (and often) wrong strategy. Gaming companies like Valve care about playtesting for the same reason. Getting out of the hole we’ve dug ourselves in costs more time and effort than checking every now and then if we’re on the right track.
This kind of adaptability and trying new things often applies not just to decisions for product and tech, but also those regarding people and workflows. While it’s true that a growing team needs some order to stay cohesive and running like a well-oiled machine, everybody works a little differently and we have to account for that. Too many rules and the job becomes soul-sucking; too few and we fail to coordinate. While concepts such as scrum and kanban are recognized methodologies organizations can look into and enforce as-is, I’m of the opinion that most teams would be better off treating them as inspiration rather than gospel.
Try them out at first but tweak where appropriate. Are the statuses “todo”, “in progress”, and “done” not enough? Throw in some more and check if it helps the team feel better with tracking. Is a 2-week sprint feel too rushed for the team? What if we run with 3-week sprints for a bit and see if it works?
We should leave ourselves the flexibility - and importantly, creativity! - to try different things that fit how the team and its members can effectively work together. Later on when the team size changes and the inevitable growing pains kick in, we’ll at least have the skills from earlier pilot runs to adjust and eventually find a new point of balance.
As mentioned earlier, it’s hard to really know what the user wants. That’s why smaller, iterative feedback loops often yield better results. But that alone won’t quite cut it — when we get feedback from users, we must try our best to listen without judgement or biases. We must not try to confirm our own hypotheses, but instead try to see what they’re actually saying.
We as builders naturally feel a sense of pride in our work - especially if it’s something we really care about - and would love to know that others see it too. But left unchecked, this kind of hubris can lead to poor self-evaluation and product decisions. We should refrain from asking others “What did I do right?” and instead lean more towards “What do you think?” After all, the most valuable kind of feedback would tell us how to make the user love the product more. This means throwing aside our ego, being highly attentive to what others find good or bad, drilling into the why’s of what they say, and not being so defensive (see: don’t talk or explain yourself too much) when we receive negative comments.
We are not our work, and we’ll have a better idea of what to improve by focusing on listening to what others have to say.
This idea also goes for the people we build product with - engineers, designers, PMs, stakeholders, and so on. Disagreements happen often, and navigating them poorly often results in workplace politics (which nobody likes). Instead of brute-force pushing our own agendas, have we considered hearing the other side out?
It helps to think that everyone wants to do well and that nobody disagrees just for the sake of disagreeing. The team isn’t working against you; the team is working against the problem with you. Different ideas are pushed because everyone has different interests and perspectives. Arguments often get heated because of a lack of understanding between both sides, not because you guys actually hate each other.
That’s why it’s proven helpful for me to accept that I don’t know everything, and that listening intently to what someone else has to say would help me understand their opinions better.
Do we have the same understanding of the scope of the problem? What’s valuable to each of us - KPIs, deadlines, other outcomes? Are we worried about the same things? Are they under more pressure than me?
Stepping back to answer questions like these helps form a clearer picture of the actual idea we’re disagreeing upon, and that in turn gives us more information for making collaborative decisions.
All this leads to better discussions, better teamwork, more respect for each other, and overall a more thoughtful outcome. Instead of tunnel visioning on winning the argument, we should step back, throw our ego aside, listen intently to others, and think about solving the problem together.
Often I find myself worrying about whether I’m prepared enough or not. Despite however much more preparation - be it a race, a music performance, or shipping code - that feeling never truly goes away. Instead I’ve found it more interesting to think, I’ll do what I reasonably can then just wing it. I save myself from burning out, actually finish the thing on time or earlier, and I assess the results for next time. Instead of over-preparing, we can afford to trust ourselves to sharpen our instincts and improve when we get concrete feedback after giving a good shot. “Perfect” is the enemy of “done”, so we should probably stop spending too much time getting everything in pixel-perfect order and settle for “good enough.”
That being said, we must also reasonably assess if the thing we’re shipping may be completely unusable and not satisfy any requirements. Sometimes we’re pushing the deadline and the work truly is far from “good enough” (again, too many unknowns in the wild). Such mishaps should be communicated early. It’s not a pleasant experience to tell someone else that we messed up, but at least we put ourselves in a position to readjust sooner rather than later. And from that, we learn and get better and move on a little more prepared for next time.
But I’m scared of messing up!
Most mistakes are forgivable. You’re probably not the person that issued a false missile alert to Hawaii in 2018 (truly one for the books); it won’t be the end your career if you miss the deadline for AI-assisted chat features by 2 weeks. Not ideal, but not catastrophic.
Mistakes are also how we learn; if everything always goes well, you’re probably not at your limit. There’s more to gain from testing the outer bounds of our skills, both soft and technical, than playing it safe and staying in the walled garden of “I’m good at this, let’s just keep it that way.” Unless we’re working on something where someone else’s health or well-being is materially on the line (example: military-issued push notifications sent to millions of people in times of increasing political tension) we can probably afford to ease up, play around, try new things, and expand our toolkit as builders.
While there are a myriad of other things to keep in mind when planning and building software projects, I’ve found myself thinking about these three the most often. Applying them thoughtfully and intently has brought me amazing results and taught me countless things; I hope the same goes for you!