Writing Code? STOP! Think First...
What you should do before jumping into implementing and writing code.
As a person who is action-biased, I am not accustomed to spending much time in the preprocessing and thinking phases. I prefer taking obvious actions; it's part of who I am.
This is why, as a junior engineer, I struggled to take a step back and think before implementing or jumping to conclusions.
I am still training myself to paint the full picture, or at least most of it (since you can’t know everything before implementation), before diving into code implementation.
As you know, coding requires time and effort, so it's important not to waste that!
Here are some useful steps I remind myself of, and I try to practice before tackling every problem.
1. Stop and ask yourself the following
Before leaping to solutions, the first step is to validate your assumptions or initial instincts.
You can do this by asking yourself a series of questions:
Is what you are implementing still relevant?
Often, we encounter numerous tasks or issues that have been logged in the backlog for a long time.
The first thing you need to do is re-evaluate these assumptions. Take the time to research the issue thoroughly and consult with others to ascertain its current relevance.
Have you understood enough to jump into code?
Investigate as thoroughly as you can. This means reading extensively:
Code: Dive into the codebase to understand how the current systems and functionalities are implemented.
Documentation: Go through any existing documentation that can provide context or background information.
Relevant Threads/Conversations: Review discussions or threads that may shed light on the issue.
Other Relevant Materials: Consider anything else that might be relevant to the problem you are trying to solve.
Ensure you understand the complete picture. Here are some strategies that can help:
Draw Diagrams: Create diagrams to visually connect the different components you encounter. This can clarify how parts of the system interact with each other.
Write Draft Documents: Compile notes and insights from what you've read or the responses you've received. This can be a valuable reference as you work through the problem.
Investigate Dependencies: Understand any dependencies that may affect your work. These can include:
Other upstream code that your solution might depend on.
Other teams who might be impacted by or have input on your solution. This includes non-engineering teams like analysts.
Have you shared your thoughts with someone?
Make sure to share your thoughts with your teammates before beginning the implementation.
The method you choose for sharing should depend on the complexity of the solution and the most effective way for your team to understand it. Consider whether it's best to discuss your ideas in a meeting or to present them in a written format.
This could be through a post in Slack, a mini-proposal, or a more detailed technical proposal, depending on what suits the situation best.
Do you have the big picture and full context in mind?
Once you've gathered all the above information, you should have most of the context around the problem. Keep in mind, however, that you will never have the full picture before implementation — and it's not practical to try to know everything beforehand.
You need to find a balance between having sufficient knowledge and falling into perfectionism.
As a general rule of thumb, here's what you should know:
Who or what will be affected by your solution?
Do you thoroughly understand the problem you are trying to solve?
Are you aware of the different edge cases?
Do you have a rough idea of how you will test the solution?
Have you decided on the technologies you'll use?
Is there existing code that you can reuse?
Do you have a high-level plan for the implementation?
Here’s what you should not seek to know:
Every detail about every line of existing code.
Trying to understand non-relevant context (it may be part of the system you're working on, but if it's not directly relevant, then it's not useful).
Every implementation detail. A rough, high-level plan is sufficient.
2. Start small and incrementally
One of the key distinctions between a junior and a senior is that a senior knows how to break down work into smaller, manageable pieces. This way, they don't tackle everything simultaneously but approach the solution incrementally, in small chunks.
For example, if you are writing complex code, try to divide it into smaller steps. Submit small pull requests for each of the following steps:
Write a skeleton for the endpoints.
Develop the helper functions library, along with its unit tests.
Create the core logic (this can be split further or not, depending on the implementation), and its unit tests.
Avoid making unrelated changes simultaneously.
For instance, if you need to fix indentation, revise comments, or sort imports, handle these in separate PRs.
Your goals are to:
Make it easier for reviewers to understand the logic you’re implementing.
Save yourself time.
Prevent overwhelming yourself.
3. Review your code before asking others
It's crucial to ensure you are completely satisfied with your own code before requesting a review from others.
By doing this, you demonstrate your best effort to save others' time, which greatly increases their respect for you and enhances your credibility within the team.
Consider this scenario: you have a multitude of tasks to handle, and someone asks you to review their code. You allocate time in your schedule for this, only to discover that the code is riddled with typos, unhandled errors, uncovered edge cases, and non-clean structures. This would undoubtedly lead to disappointment, as you might feel that these issues should have been addressed by the coder before seeking your input.
So, be proactive. Rectify your mistakes before someone else points them out.
By adopting this approach, you significantly reduce the chances of overlooking important details. Plus, you'll feel more confident about yourself, and your tasks will proceed more smoothly.
Speaking from personal experience, I've made many mistakes in the past. I would jump to conclusions, overlook important context, and start drafting a solution before fully understanding the problem, among other things.
Once I made a conscious effort to deliberately change how I approach problem-solving, everything became much clearer, and my coding experience became smoother and easier. Not to mention, my credibility within the team increased significantly as I stopped making small errors that could accumulate into larger issues.
You might already be aware of or practicing much of what I've mentioned above, but a reminder never hurts. 😉
I'd love to hear your thoughts in the comments: if you have any more tips on how to draft solid coding solutions, or what steps to take from ideation to implementation, please share them!
Thank you for reading! I hope you enjoyed it, let me know by hitting the like button ❤️ to help others find it on Substack, and share it to spread the love!
Other stories you don’t want to miss
Stretch yourself from time to time. — by
How to write great feedback in 360 reviews (every year) — by
Is Work Life Balance a Myth for Software Engineers? — by
The power of questioning your first instinct in the engineering industry — by
Thank you! :)
Talk soon,
— Basma
The developer's backlog can indeed become outdated.
It's a good exercise to ask whether tasks are still relevant.
Regularly cleaning the backlog goes a long way in helping you work on the right projects and build a great product.
Really great advice Basma – I particularly like how you've offered up practical, tactical tips on how to slow down and be more intentional before moving into coding. Nice. I think these are skills that many (most?) engineers will benefit honing. (Mentioned you in my comments here, very complimentary article: https://bit.ly/3OH6gfp)