How we approach problems often defines whether we succeed or not or how hard success comes to us!

Me ice climbing

This blog post is my humble attempt to come up with some of problem solving advice for software engineers who are starting in their careers. Why would you listen to me? – You don’t have to. In fact, I would argue, that you shouldn’t take anyone’s advice at glance and at the same time be open to evaluate everyone’s advice and then make up your own mind. I do not have many credentials, other than 12 years of experience as a software engineer in various roles (SDE, Sr. SDE, Tech Lead) and various industries (outsourcing, online entertainment, nuclear energy, e-commerce). My experience is different and success is questionable. I am guilty of making career mistakes and solving problems the hard way. My hope here is that the below could save you from making same mistakes.

Worst mistake

The worst mistake of all is to die with regrets but, as not to get too philosophical, we are talking about software here. So…

It is totally normal to get stuck time to time on problems. If you never ever get stuck it might indicate that you are staying in your comfort zone impeding the speed of your progress. Therefore, imho, one of the worst things you could do to yourself at work is to let yourself stay stuck on a problem without any progress or learning and as a result with no advancement to your future career.

Understanding the problem

The first step to approaching a problem is understanding. You’ve got to identify the issues and envision how the success would look like. Sometimes this might be referred to as “working backwards”. More often than not, there will be preprocessing done by business analysts / project managers / senior engineers which results in some kind of requirements (stories, documents, tasks, etc). Your job as a software engineer is to first understand what is wanted from you. Simply state back to requirement givers in your own words what it would solved problem mean. Once you understand the problem completely proceed to the next step.

Strategizing

The second step is strategizing. You need to come up with a potential solution. You might want to brainstorm on options, evaluate them and try to come up with the best one. Decision matrixes and other techniques might help, but don’t bug yourself too much. At this step you might want to create a plan by breaking problem into smaller tasks. You might work on proof of concept or try one or few things out. I do not believe in plans themselves, but I do believe in planning as it makes you think hard about the approach. It is important not to get stuck in “analysis paralysis” mode, so once reasonable time is spent, move on to the next step even if somehow you don’t feel ready. You will never be fully ready. Take on the problem you’ve got. You might learn some new things when doing so which you didn’t anticipate.

Execution

The third step is approach execution. Doesn’t matter how great plan you had, if you fail to execute you fail. Say, you picked option x and it didn’t work out for you, do you continue to push for x or do you switch to option y, do you give up, do you seek help? What do you do? Do you feel how anxiety creeps in?

From my personal observations generally there are two types of execution: erratic and systematic.

Erratic

Basically you just start bashing the keyboard, throwing different copy-pasted blocks of code and praying it is going to work. This is that kind of approach when “<” didn’t work, so you replaced it with “<=” and it worked, but then you realized that your loop had to start with index 1 instead of 0, and so on. Eventually you arrive at the finish line. I bet that most of us, software engineers, have used this approach and it worked at times but then we felt uneasy about it.

Systematic

You think about each piece of code you write and consequences it is going to have, questioning each line of code and thoroughly testing the code. Why do I use “<” instead of “<=”? Why does the loop start at index 0? Should have I used thread-safe data structure here?How would this button look on small screen? Why does this API accept any number of items? I don’t know about framework ABC, so why not read a doc reference first? And so on – you question everything! This approach might seem like taking much more time and it does, but eventually written software has less bugs, is much more maintainable and truly solves the problem. Arguably, maturity of a software engineer can be recognized by observing them solving problems in this systematic way.

Some other bullet points

  1. Reiterating is fine. Although systematic approach wants you to think about each line of code, you might be overwhelmed to do so at once for larger project. In this case coming up with a “skeleton” solution that does something and then building on top of it (maybe changing few “bones” here and there) is totally fine. This goes along with agile methodology as well. Just don’t scarify quality with “oh, this will be one in the next iteration” and eventually never being done.
  2. Do not just copy-paste. As the joke goes: “Dev1: Damn, copied this from StackOverflow and it still doesn’t work. Dev2: Did you copy from the question or the answer?” Although copy-pasting from other parts of the project or SO, for that matter, is totally fine, what’s not fine is not understanding what you are coping or not questioning the quality of the piece of code you are copying. If the code was written by more senior developer or if most of the project is written “this was” this is not a valid justification to not try to see if anything about it could be improved. As a simple example, a developer before you might have took a shortcut by defining style right in html instead of moving it to a css class in separate file.
  3. “Don’t work hard – work smart” – although true, stinks. Most often I heard this from people who were lazier than others. There might be two types of laziness – a) the one that makes you procrastinate, and b) the one that makes you ingenious in problem solving. I’m fine with b) as long as it doesn’t come at cost of quality of your solution in terms of maintainability. Think of someone doing a+=b; b=a-b; a-=b; to swap two integers because they didn’t want an extra variable and now extrapolate this on on system design of your software where no-one could understand what the hell is going on. Long story short, you need to work hard and there is no way around it.
  4. Pause to learn and deliberately practice. At times you might come around something you haven’t worked with before. Stop! Take a moment to understand what it is. Reading one of two pages of documentation or going through “hello world” tutorial might save you a day or few. As an example, you might need to integrate a library into your project and it may look overwhelming as the project is huge. At this point it is best to implement simplest possible project with the library to understand how it works before spending days integrating it and then not understanding why it isn’t working.
  5. Seek help but do your due diligence. It is totally ok to ask others questions – this is the way to learn. At the same time it might not be appreciated to ask something that can be found online or in documentation with a simple query. Also learn to ask how to ask help http://xyproblem.info/
  6. Time bound. Never get stuck on something for too long. Put some boundaries for specific tasks. If x isn’t working, look at your strategy and unstuck yourself. You might need to escalate this with your manager.
  7. Clearly communicate. Very likely you are working in a team and have a manager. Work on improving your communication so that you can convey your status and whether you are blocked and need help. I would advice against obfuscating your status with needless information – just be honest if you are having difficulties.
  8. Retrospect and analyze if you can improve something for the future. Don’t just take everything at its “status quo”. Say, if environment setup for your project is difficult, and always takes time for engineers go ahead and improve it.
  9. Reasonably document your work. Chances are that someone will have to solve a similar problem or that you will need to explain your work at later stages. Documentation is just a tool to help you out in these situations.
  10. Add your bullet-points/thoughts/disagreements in comments!

Conclusion

It is in my personal view that approaching a software problem consists of 1) understanding the problem 2) strategizing about solutions and 3) execution of the strategy. Observation I have made over the years is that engineers tend to solve problems erratically or systematically. More systematic approach supplemented with the above bullet-pointed guidance might be helpful advice for starting software engineers, but be skeptical as this is purely an opinion. Enjoy and let me know if it helps.