The one thing that Humphrey said which really resonates with me on the topic of bug fixing is summed up as this, “[on bugs] they’re easier to understand since the code foundations have already been laid out before you, all you have to do is understand it”. Even at work, I found myself for the past 4 weeks focused on bug fixes to our product prior to the Mobile World Congress (MWC) event, so I was both sick and very well experienced in trial-error approaches towards bug fixing. Here are three concepts / thoughts which I find often result in a step in the right direction when it comes to solving the infamous issue, resolving the ticket, or adding the feature which exists in a different scope.
Is the Bugfix a result of Data Corruption and or Race Conditions?
This issue I find a lot working with ‘data-driven’ applications, the type of applications where charts, tables, and UI elements themselves are powered by JSON responses from a backend. In this case, the expected response (contract) differs from what is actually returned. In my first COOP with TechnicalitiesPlus, part of the learning experience was debugging and discovering that the front-end code itself functioned as expected, and it was the persisted data which had changed. This break of contract / agreement is often easy to overlook, assuming that the data itself is always the expected ‘source of truth’. The issue which led to this experience? The JSON array was returning objects which lacked very specific attributes which existed in the database. This caused failure to render and a very frustrated 19 year old to lose hours thinking it was Front-end logic creating the issue. The amount of hours I spent learning that scope inside-out before verifying the data response itself is a lesson that I will not forget, and it is why my primary debugging check is to verify the data.
Is The Requested Feature Already Implemented Elsewhere?
I find a lot of the bugs that I commit to are feature extensions to an already working component, so this question often comes up quickly when I start going crazy with the keyboard and terminal. Often, the feature exists in a different scope such as a dropdown, component, or platform even. If so, you then have a good base to research and understand how said base was implemented, thus granting you a giant leap ahead. For my two accessibility bugs as of last week, neither were applicable for this approach. That being said, my good friend Svitlana’s (who can be found here) recent work with Visual Studio Code followed this exact pattern with her bugfix / improvement. Her approach was very similar to this, first discover where the functionality exists and understand how it works from there. We toyed with the idea of copying the entire function over to the new scope, or importing it directly; both ideas replaced with a much more suitable
IAbstractAction class implementation which would call the imported function within the required scope. Essentially, it replaced the original idea of reverse engineering and dozens of lines of code with a single, fifteen line
IAbstractAction class which did not repeat code or produce a new scope riddled with potential issues.
Will Calculated Trial and Error Produce a Visual Difference and or Indicator?
This is more of a workflow paradigm that I’ve adopted from the first days at Seneca, where if you don’t understand how to fix or implement a working concept, essentially do ‘smart’ brute force attempts. What do I mean by smart? Well, don’t make the mistakes that I did at first where every single compiler error results in a different implementation. First, focus on the scope which affects your area of the bug. Try to understand its circles of scope and interaction, and from there reach out to all that the scope touches where applicable.
Once I understand the basics of the scope such as adding a button to a list of common functions, here is the ‘smart’ brute force direction I sometimes approach issues from:
- Add a static button to the list forcefully, omit programmatic idioms for now, do you see the visual change?
- Make the button produce an alert / visual indicator of user interaction and handling, is the event handler working?
- Now attempt to add the button programmatically if appropriate, does it appear? Make it.
- Make said button’s scope directly relational to the scope you’re working with, does it interact with the components data, DOM, or other functions?
If the first failed, I’d probably try as many alternatives to adding the button to the DOM as I could. Only then, would I attempt the second point. Likewise with the third and fourth. This method of attack maybe is not the most efficient, but it produces a thorough understanding of the scope and attempts made to work in said scope. I find myself following this approach less and less as experience in the project grows, but I cannot deny just how much time I wasted using said approach, and the results which were produced only being possible in such a way. Break the DOM or logic 20+ times in 30 different ways? Check!
In the End, the Direction is What Matters
I keep saying ‘step in the right direction’, because I truly believe that if you’re new to a code base, it’s easy to get lost in all the functions, methods, variables; the lights and darks. I love the reinforcing concept of taking a ‘good’ step, meaning taking the risk and or time which results in me being closing to where I need to be to achieve this bug fix or feature implementation. Nothing is more depressing than taking a step and falling that much deeper into confusion or misdirection. It’s just like finding treasure, once you find enough clues or the map itself, and take the path which leads you to the correct direction, you’ll find the chest full of gold!