The purpose of this post is to share the decision making process of one particular software developer, hopefully it can help guide you when you don’t have enough information to pin point the right solution. This is subjective, it’s not the only way to do it, it’s not even going to be labelled as the right way to do it, it’s just one developer’s thoughts on what you can do when you don’t have enough context to know in which direction to turn.

These are tenets and guiding principles. I’ll try and include examples to help illustrate the main points.

Initially, approach the solution as if you don’t know the right answer, even if you think you do

There is a saying, “trust your gut”, and often your very first impression of the answer to a problem will be close to the final one you land on. I would prefer to alter this saying, to another similar expression, “trust your gut, but verify”. Use your gut instinct on the answer as a way of narrowing the problem scope. I am sure that by this stage you can identify over a thousand answers that are not suitable. Use your gut reaction as a filter that limits the solution to only a few possible solutions.

Limiting the solution space provides clarity to your colleagues, and allows you to focus on a narrow set of possible solutions. You can tell a much more compelling story to your stakeholders, at the early stage, that you feel like we should investigate these two or three possible solutions. If you’re like me, you are wary when someone immediately provides a solution with no alternatives. Your stakeholders put trust in you to help guide the company towards success. You are not tasked with knowing all of the answers. Nobody cares that you don’t immediately know what to do. Senior developers are tasked with setting direction and bringing your whole department / org towards it.

Challenge your assumptions, explore other options, listen to people. Communicate a plan, assist others in achieving it. You will not be right all the time - good - now you will know what to bear in mind the next time this situation happens.

Understand what is valuable

There is a difference between what a developer sees as important vs what the company sees as important. Sometimes, the things that are important for the company are direct contradictions to what a developer or senior developer would say is important. Let me demonstrate:

Developer: Concise functions, good test cases, high code coverage, precise types and interfaces / inheritance, low bug tickets.

Senior Developer: My team use consistent tools and languages, the migration to language X is almost complete, the customers are happy with the products, we have idiomatic APIs that adhere to industry standards, the new service has been used by several other teams. Our backlog is well defined and prioritized.

Principal Developer: We are building technical solutions that help the company achieve their 2 year vision. We are able to minimize the impact of this initiative being cancelled, and we can re-use some of the output for this product replacement. We notice that the following teams need assistance with the maintainability of their apps, lets organize training. Our SaaS vendor for X now costs too much, we need to build it in-house, which developers can we use to get it done without disrupting our quarterly objectives.

As you see the kinds of things that each role level is responsible for, you might notice that it’s necessary to break / ignore some of the things that were deemed important, in order to make things work. To react to the SaaS provider being replaced with an in-house solution, you might have to set your backlog on fire and start again. In order to meet the replacement deadline, you might need to skimp on building a full e2e test suite, and only test a few things that are critical.

The annoyingly trite bit of advice I have here is: it’s all about balance.

You will feel an internal struggle or resistance to break some of the things that you used to hold dearly and were previously praised for. That’s called cognitive dissonance and it’s a real thing that may happen to you. There comes a point in time where your are expected to use your wisdom to know which things are safe to break, in order to achieve the outcome for the greater good.

If nobody can use your solution, you have not provided a solution

Probably even worse, you have cost money in order to not provide a solution. OK this one sounds dramatic, and I suppose it is, but the point is: build things that solve an objective and will delight your users. You might have the perfect type system, perfect CI/CD pipelines, 100% test coverage on a repo using the very coolest frameworks and libraries. If it doesn’t solve a user’s problem, then it was all for nought.

Perfectionism can be a common trait with software developers, if you have it then the sooner you can shrug it off, the sooner you can build the right thing at the right time, grab a high five and move on to the next.

Nobody is saying become sloppy, nobody wants buggy software. An even more important point: you won’t have users for very long if you provide a perfectly implemented solution that does not solve their problem.

A very real example of this was when our product team embarked on a new strategy named “Partner First”. I was involved in the early discussions and I lead the overall solution design. I had a feeling that shipping react components for partners to use in their own apps was the superior technology to use, but I didn’t pick it. I picked the solution that gave universal adoption of the whole embedding idea, which was iframe based with an SDK to control it.

If I had stuck to what I knew was the better way for other developers at other companies to implement our widgets in their apps, I have no doubt that after 6 months the project would have failed. This seems like a contradiction doesn’t it? If it was superior, then why didn’t I pick it? The answer lies in who the customers / users are for the vast majority of cases. They have a website written in anything (most often not react), that hasn’t been updated for a number of years, that only allows superficial configuration. The actual customers we were targeting with this strategy didn’t have dedicated engineers on staff who maintained the site that our embeddable widgets would go in to. In short, providing them with the “superior” react components via an NPM library would have been a disaster.

I only knew how to make my decision by asking deeper and deeper questions to our product and partner implementations team. They let me know the types of systems that our embeddable components would be used in. If I didn’t ask these questions, and thus have enough information to make a decision, then I would have gone with my gut and delivered something unusable. Trust your gut, but verify. In this case, I verified that my gut was wrong.

Sometimes, you just don’t know

It took me a while to become comfortable in saying “I don’t know”. Throughout my career that wasn’t always an answer that was “safe” to give, which is a shame come to think of it. Oh well. Don’t be like me! Say it!

I say it often enough now, that I actually look forward to being able to say it next, because it means I’m about to learn something new. There’s a flywheel effect here. I find that this topic has a lot of cross-over with the first point, where you approach the situation and are doing your best not to label the solution before you’ve explore things thoroughly enough.

Let me just make some things really clear

  • Nobody will think less of you for saying you don’t know
  • You are guaranteed to learn something when you say you don’t know, and commit to finding out

With your new knowledge, you will have more of an idea the next time, and this all just adds up in your memory banks and helps you make decisions, or have initial impressions on a possible solution, in the future.

If you’re the senior or the principal developer in the team and you’re helping to break down a complex task, you are not going to lose your title and role in the team by being the first to admit that you don’t know what the right thing to do is. Try using the following considerations to help guide you:

  • What do the customers really want?
  • Put yourself in the user’s shoes, what kind of experience would you like?
  • How will this make the company successful?
  • Does this help on any of the items listed in our quarterly / yearly planning cycle? If not, should we even do it?
  • Can I use this to strengthen my knowledge in a certain area?
  • Can I defer this decision to someone else, and learn from them?
  • What did that other team do when they had a similar problem? Start a dialogue with them, ask for their advice.

I know what to do, let’s do it like this

OK great! You have formed an opinion on what to do! Hooray!

Share it.

Write an amazingly clear design document that communicates your solution’s major architectural points, and gather feedback from your peers. Never rely on your team-mates only, they probably like you. You want more feedback that just this small sample size. Aim for about 100 years of experience in the room when you run your design session (if you can!)

The review process is absolutely critical to the long term success of non-trivial systems. You should definitely use the feedback you gather in these sessions in your decision making process. You might choose to disregard certain advice, and that’s fine. The purpose of the design review process is to gain confidence in your solution, not to do what other people suggest you should do. Often the reviewers don’t have the same domain experience as you do in your certain spot in the company, but they’ve made their share of mistakes in the past and they’re trying to help you avoid them as well.

Get feedback. Be prepared to refactor your initial solution. Let pride go.

Helping others

Often when I think about the implementation phase of a solution, I am trying to give other developers the right opportunities to challenge themselves and go above and beyond their usual remit. I am giving them opportunities to gather experience, so that they can put it on their promotion document and get promoted. I want every developer that I work with to go as far in their careers as they want to. I don’t try and do everything, I give people the opportunity to smash goals as well.

At each stage of the roll out, I ask myself, and often chat with engineering managers too, about how we can give person X the opportunity to demonstrate skills at that next role level. At the senior level you stop being solely an individual contributor and turn into a force multiplier, where your actions make the team produce more value within themselves compared to if you were not involved. This continues to the principal level too, where you are expected to be a force multiplier. Knowing how to give developers the experience to increase their skill set is an important characteristic of leaders. The next time you’re thinking about who should get the glory for smashing the roll out of sub-system Y, perhaps it should be someone else.