Coding with zero bugs
Software with zero bugs may seem like an ambitious goal. Over time, defects in software have increased and have become so normalised that some developers and users even expect them. But while it's difficult to get to zero bugs, I think it's worth trying for.
The mindset
You don't have to action all of these items for every change you make. I typically give this list a quick scan and pick out only the items that are relevant to the change I'm making.
My code is buggy unless proven otherwise.
Having the discipline and patience to go through your code is a sign of a good developer.
Enjoy the feeling of fixing bugs and leaving the code better that you found it.
This activity is building the mental muscles which will move you forward in all aspects of problem-solving.
How to fix bugs early
Typos, accidental keystrokes, debugging statements. Every time you're about to commit, hold back for a moment and review the diff of changes going in. Make sure you're only committing what you fully intend to commit. A compiler or linter can usually pick these up, but there are often cases that are missed.
Subtle logic errors. Look for all those mistakes that look like reasonable code, to both the first glance and the compiler, but are actually the wrong way round or otherwise incorrect: False-positives, Expressions being coerced to incorrect boolean values, Off-by-one errors, Filtering operations.
Edge cases. Basically do everything you can to break your application and ensure that it recovers gracefully in all circumstances:
Click a lot of different parts of the UI in very quick succession.
Test long sequences of actions and make sure the result at the end is exactly as expected.
Input values in unexpectedly large quantities, in an unexpected format or null/empty values.
Test with correctly formatted but illogical values.
Add a larger than normal number of items to a list.
Values vs. references. Do you expect a value to be set in one place and updated in many others? Or do you want to hold independent copies of that value in multiple places?
Memory leaks.
Code executing too often. Do you perform unnecessary operations within a for loop, a game loop, a template, a rendering cycle, or any other part of the code base that gets executed many times in succession?
Same same but different. Be extra careful in situations where you have two things that look and behave very similarly, but are qualitatively different.
Null-checks. Whenever two values are being compared, have you null- or undefined-checked both sides of the comparison if needed, and handle what to do if either/both are null?
Async data dependencies. Does your app depend on multiple sets of data, which may load at different times? What happens when not all of the data has loaded? Does the application crash and burn? Or does it handle the situation gracefully, perhaps waiting until all the data has loaded, and showing a 'loading' indicator in the meantime? Use Javascript's
setTimeout
method, RX's Delay operator or .NET'sThread.Sleep()
Browser/OS upgrades. Depending on the environment you're developing for, be aware of the potential for breaking changes to that environment, when a new version comes out.
Devices, screen sizes and zoom factors. Test your app with multiple devices if needed – mobile, tablet and/or desktop.
Accessibility. Bugginess or even absence of accessibility features is a major problem in the software application landscape. If your app will be used by a broad segment of the population, you probably should be ensuring that it is accessible.
Date and time handling and formatting. Be extra careful to test code that does anything with dates or times. If the code is performing some kind of calculation on a date/time value, try to test it with a variety of inputs and ensure that it always produces a correct result date/time.
Numeric values, such as currency. As with dates/times, thoroughly test any aspect of your application that operates on numbers, and especially locale-specific numbers such as currency values.
Load testing. Does the system break down when large number of items are passed through it? Substitute a fake data-source with thousands or even millions of records and see if the application can handle that load.
Requirements vs solution. Double-check the original requirements and see if you actually addressed them. There might have been a subtle indication in the language that you overlooked or some ambiguities that you didn't yet clear up. If you need to go back to the business to clarify these issues, do this as soon and early as possible, so that you have a better chance of fixing any bugs in the code before releasing it.
Hit refresh. Sometimes, for reasons that I don't entirely understand (and perhaps don't wish to) a running application will get out-of-sync with the code that generated it. Yes, this can happen even when automatic compilation tools are in use. In the case of web apps, caching of assets can play a role. For native apps, processes may remain open. Long story short: when in doubt, hit restart and refresh.
Multiple environments. Most organisations have multiple environments into which software is deployed in a staged manner. There's the local developer machine, then a Development server, then Staging and/or QA, then Production/Release/Live. It's a good idea to run some tests on your application in every environment. This is especially important if your feature or change depends on environment-specific factors, such as configuration values, database schemas, data and other systems, services or resources. Anything might go wrong in a new environment, from a typo in a configuration value to a missing authorisation on a resource. You don't have to test everything in every environment, but it's probably a good idea to at least test the happy path.
Find similar bugs and fix them (and generalise the fix!).
Last updated
Was this helpful?