Bugs are an ever present part of my day to day life (whether real or computational - thanks Malaysia!). More often than not, however, I am surprised and frustrated to discover where the bugs come from. Programming courses list three types of bug, syntax bugs, semantic bugs and logical bugs. Or, 1) your computer did not understand what you wrote, 2) the computer understood but fails at runtime, 3) the computer understood, and your semantics are acceptable, but the program does not execute as you expect. The third is like saying a slang that your parents have yet to be introduced to, the language permits your innovation but it fails to register in your parents mind. We have to remember that our computers are very old school and proper individuals who demand a certain level of care over our use of the language.
Early on syntax errors regularly saved my ass and slowly made me a more consistent, language adherent typist. As my understanding of the languages, and their ecosystems, increases I find myself trying to do less quirky/hacky things and strive to constrain myself to the strengths and limitations of the languages I use. Run time bugs are fairly avoidable too by consistent use of testing (particularly test driven development). That leaves me falling into the murky depths of logical and architecturally introduced bugs which, I fear, are mostly overcome through experience. However, logical bugs are not frustrating, they are a challenging and expected part of my development as a software apprentice.
It seems a good measure of my progress that I no longer struggle with the primary tool I use and only fall as I become ever more expressive with my coding foo.
These days I mostly fight a fourth source of bugs, the true bane to my growth and productivity as a software craftsman - ME! The single unwavering source of frustration and mistakes in all matters and projects has always been myself. Whether careless typos, copy and pasting, not reading sufficiently or just being darned lazy. I am the biggest bug in my systems.
Very occasionally I will discover an issue that seemingly appears from no where. If I am paying attention I will walk back through the most recent changes I made, find the offending code and amend is quickly. Other times, I will spend hours cursing my apparently weak coding powers, crawling internet sources looking for any unfortunate soul in the same situation as me. Only, in the end, I discover, “ohhhhh, brackets” or “oooohhhh, gotta use that (method / library / combination)”. Often these will be things I have encountered before and vowed never to fall over again, alas, the human condition (read: my crappy memory) hamstrings me.
There are many ways to counter this source of error, make yourself a better coder and reduce the likelihood of syntactic, semantic, logical and even self induced bugs! Here is what I employ regularly:
◆ Best practices/styles guides ⁃ https://github.com/bbatsov/ruby-style-guide ⁃ https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md ⁃ https://www.python.org/dev/peps/pep-0008/ ⁃ https://www.twoscoopspress.com/products/two-scoops-of-django-1-8roducts/two-scoops-of-django-1-8) ⁃ https://jeffknupp.com/writing-idiomatic-python-ebook/ ◆ Testing ◆ Debuggers ◆ Documenting ◆ Reuse (as in, reusable code) ◆ Abstraction
Some of these I will discuss, but in short:
1. Following industry/well regarded standards when possible. 2. Tests and documentation were a journey of enlightenment for me. I think they are both valuable and quintessential to success as a programmer. 3. Liberal use of run-time debuggers! Ruby’s Pry is a true ‘gem’! No need to get angry at code, just stop it and explore! 4. Never reinvent the wheel (unless you can do a better job or want to learn). Use other people's hard work and save your time. 5. Abstraction - all we do with code is an abstraction and learning to leverage abstractions, such as classes, libraries, frameworks and data structures, will bring your code (and employability) to new heights.
The apprentice will regularly face himself, and the growing complexity of his tasks, as a formidable foe. Yet, once we learn to identify our weaknesses and catch our pit falls, we can step out of our own way and begin making meaningful headway into our growth as software experts and tackle any challenge that comes our way.
Next time you face a troublesome looking bug, if you have not resolved it after one or two tries - STOP! Reread everything you recently typed, track down the source of the bug with your interactive debugger, write a test, reread documentation. Most importantly, once you solve it, think about why it occurred, what should be in place to help prevent the next bug. Maybe it was a foolish typo, you will have to read your code more. Maybe it was misusing a library, write a test or read more documentation. Or maybe you’re trying too hard to implement something someone has already solved.
Stay humble, step out of your own way and continue on to greatness.