DEV Community

Emmanuel Gatwech
Emmanuel Gatwech

Posted on • Originally published at eman.hashnode.dev on

The Planet of The Bugs, Book 1

The Planet of The Bugs ๐Ÿช - First Act

"With great power comes great responsibility." - Uncle Ben

In the Renderland saga, we learned about Renderland's history, its new savior, and the invaders who sought to destroy it. The planet was invaded by an intelligent species of bugs. They came in different shapes and sizes and wreaked havoc on the planet.

This part will trace back the origin and history of those bugs and how they came into existence. We will explore multiple debugging techniques.

The Origins of the Bugs ๐Ÿ‘พ

I was back on earth watching Planet of The Apes when my TV started peeping and glitching the screen turned blue. I tried switching it off, but suddenly got sucked into a portal and found myself in Renderland again!

I was greeted by the federation's chairman, Dennis Ritchie who then started briefing me about an imminent danger. The once-defeated bugs have been regrouping and are seeking revenge!

Years have passed since the battle on Renderland and the bugs have been evolving, they are more complex now, reproduce and spread at incredible speeds, and have adopted and can even hide in plain sight!

What is a software bug?

๐Ÿ’ก How do bugs occur?

The chairman then began narrating some of the most common causes of bugs he had witnessed during his days. Things have changed and the list might be a lot bigger.

Dennis explained that bugs were a natural result of the complex systems and languages used to build programs. Sometimes, the simplest mistakes, like a misplaced semicolon, could cause a catastrophic failure. Other times, bugs arose from the very design of the program, or due to miscommunication between the stakeholder.

๐Ÿ’ก Here are some of the common reasons why bugs occur in programs:

Human Errors

Human errors refer to mistakes made by people during the software development process, such as incorrect data entry, incorrect interpretation of requirements, and programming mistakes.

  • Miscommunication or no communication during initial project discussions.

  • Lack of collaboration or communication blockers.

  • Communication or Miscommunication might result in unwanted outcomes.

  • Scope creep, team conflicts, and unrealistic deadlines.

How to mitigate such errors

  • Creating specification documents and agreeing on deliverables before embarking on development.

  • Thorough self-review of code before pushing and further reviews by teammates/managers.

  • Participating in pair programming and utilizing methodologies such as QA.

For instance:

interface User {
    id: int;
    email: string
}

// assume we would like to add more info the user object before we send a response
const returnUserByID = async (id: User["id"]): User => {
    const user = fetch(`/users/${id}`);

// this function will return `undefined` because JavaScript automatically inserts semicolons after every return statement.
    return 
    {
        ...user,
        online: false
    };
}

// this should be the right way to return a way object
    return {
        ...user,
        online: false
    };

Enter fullscreen mode Exit fullscreen mode

Syntactical and Programmaticals

These bugs arise due to a lack of understanding of the programming language in use i.e syntactical errors or implementing the wrong types.

  • Lack of understanding of certain/advanced programming language features.

  • Copying code from sources such as StackOverflow or ChatGPT (what works for others might not work for you).

  • Using deprecated features and ignoring compiler warnings.

How to mitigate such errors

  • Reading documentation and ensuring that you're adhering to the API protocols. Each API has a list of standard inputs, outputs, and metadata. Make sure none is violated and that the API is being used as intended.

  • When working on a large codebase, you could identify patterns from other parts of the system. Try asking existing team members for an explanation of these patterns, no need to re-implement the wheel.

  • You could become proactive and suggest updating the contributing doc for your project! (This will give you extra points!)

might arise due to issues interpreting the project requirements and relying on assumptions rather than communicating before the development.

Compatibility:

Compatibility issues arise when you try running a program on an unsupported platform. For instance, this site shows how many browsers support CSS Grid natively supported in each browser.

How to avoid compatibility bugs

  • Make sure you run your programs in a consistent/ predictable environment such as Docker or NVM which lets you switch between Node versions.

  • Suggesting polyfills or alternatives for systems that don't support some of the required dependencies. Also using nightly releases of certain software pieces such as Nightly Rust

  • Document the installation/ setup instructions in your README.md file for future reference and new contributors.

๐Ÿ’ก Note on software release patterns

Stable Version, Release Candidate, Beta, Alpha Release, etc.

Environment Bugs

These are often caused by hardware or software failures, such as crashes, memory errors, and network issues when working with external services.

The Search Party ๐Ÿฅท

We decide to form a search party that consists of the federation's top heroes. Together, we'll go out on a hunt, traditionally known as debugging which is the process of identifying, analyzing, and resolving errors or bugs in computer programs. The goal of debugging is to identify the root cause of a problem.

Identifying Bugs ๐Ÿ”Ž

To prove a bug exists, we need to reproduce it. This step may involve running the program multiple times to confirm the existence of the bug. It involves comparing the current and desired behavior of the program.

  • Current Behavior: Modal closes before confirming user info.

  • Desired Behavior: Modal closes after confirming user info.

Bugs are affected by factors such as the environment (hosted vs local), and it's hosted, there could be multiple instead of a hosted environment (staging, QA, and production).

Reproducing a bug involves ๐Ÿ’ก

  • Replicating the same environment that bug occured i (Operating System, Version)

  • Producing detailed description of the steps that led to this bug i.e login, click create button and fill out the new form, etc.

If you contribute to open-source projects, you'd find issue templates such as:

Isolating Bugs ๐Ÿ”

After locating the bug, the next step is to isolate it. This involves understanding the conditions under which the bug occurs and identifying any relevant info.

  • Find out where the bug is and how much of the system it affects.

  • Think about any recent changes that might be connected to the bug.

  • Use debugging tools such as log files, tracing, or a debugger to pinpoint the source of the bug.Resolving Bugs

Fixing the Bug ๐Ÿงน

Once the bug has been located and isolated, the next step is to fix it. This may involve rewriting code, changing input values, or making other modifications to the software program.

This could be as simple as changing a single line of code or as complex as re-engineering the entire software system.

The hero has also discovered that debugging is an iterative process, where they must test and refine their code until all the bugs have been resolved.


The Bug Hunter Training ๐ŸŽฏ - Second Act

  • I fear not the man who has practiced 10,000 kicks once, but I fear the man who has practiced one kick 10,000 times. Bruce Lee

In order to defeat the newly evolved bugs, our hero needs to train further and learn new skills.

Dennis Ritchie shares programming and debugging techniques that have been practiced for centuries planet.

Console Training ๐ŸŽฎ

This is the simplest and most commonly used debugging method. Used by beginners and experienced developers. It's a very powerful tool and this section will help equip our heroes with newer skills and techniques.

The chairman has cast a simple spell to summon all the children of this technique.

console.log(Object.keys(console)); // outputs an array of methods
/**
['debug', 'error', 'info', 'log', 'warn', 'dir', 'dirxml', 'table', 'trace', 'group', 'groupCollapsed', 'groupEnd', 'clear', 'count', 'countReset', 'assert', 'profile', 'profileEnd', 'time', 'timeLog', 'timeEnd', 'timeStamp', 'context', 'createTask', 'memory']
*/

Enter fullscreen mode Exit fullscreen mode

Some of these methods aren't built into JavaScript. For instance, the memory method is provided by Google Chrome.

Console.log

This method is used to print out information to the console. It's the simplest and probably the first one we learn in JavaScript. It's very customizable and you could do a lot with it.

You could customize it by passing CSS rules. For instance, Facebook displays a message to warn users when they open the DevTools while browsing.


console.log("hello, world!");
// styling output
const style = 'background-color: maroon; color: white; border: 5px solid #333; font-size: 2em; padding: 0.5rem'

console.log("%cHello, World", style);

Enter fullscreen mode Exit fullscreen mode

You could also pass multiple arguments and substitute strings as well!

Console.error

This is used to display error messages on the console. You might wonder, why to use this method instead of the good o' log? Because this method comes with additional enhancements such as an error Stack Trace.

The Stack Trace shows the sequence of function calls that led to the error and can be very helpful for debugging.

๐Ÿ’ก The stack trace may not be available in some environments, like certain versions of Internet Explorer.

import { LicenseNotError } from "utils/errors";
const retrieveImages = async (userId: User["id"]): Promise<User> => {
    try {
        const licencseInfo = await getLicencseInfo(userId);
        if(licencseInfo === null) {
            throw new LicenseNotError("Not Found"); // custom error
        }
    } catch (error) {
        // automatically displays a stack trace
        console.error(error);
    }
}

Enter fullscreen mode Exit fullscreen mode

It's recommended to use this level if you're collaborating with others or developing a library or public API. It will help other developers trace the origin of the bug.

Console.table

const levels = [
{
    name: "memory",
    description: "provides memory usage info on a web page",
    arguments: ""
},
{
    name: "info",
    description: "used to display an informational messages",
},
{
    name: "warning",
    description: "used to display warninings"
},
{
    name: "error",
    description: "Used to log error messages. It allows you to include additional data such as a stack trace."
}
];

console.table(levels);

Enter fullscreen mode Exit fullscreen mode

This should output the following table:

Useful for displaying tabular information such as a list of users.

Console.group

  const label = 'The ancinent debugging techniques are';
  console.group(label);
  console.info('Identifying Bugs');
  console.info('Isolating Bugs');
  console.info('Resolving Bugs');
  console.groupEnd(label);

Enter fullscreen mode Exit fullscreen mode

This will output the following:

Console.dir

  const wrapper = document.getELementById("_next");
   console.log(wrapper)
  const label = 'The ancinent debugging techniques are';
  console.dir(label);

Enter fullscreen mode Exit fullscreen mode

This will output the following:

Useful for displaying related information. For instance, you could use it to print out nested values or the values in an array of objects.

Filtering Levels

There are several options to filter logs such as level, source, text or regular expression.

Popular frontend frameworks and libraries make use of these logging levels to display different types of messages. For example, React does:

  • Use console.error to highlight errors in code, they often include a stack trace to help find issues quickly.

  • Use warn to display warnings such as when you forget to include dependencies in an useEffect array.

  • They use source based filtering to show you where each console.log came from.

Console Best Practices & Tips

  • Use the appropriate logging level so you could easily filter and search for logs.

  • Clicking on the source of a log will take you to the file the log lives in.

Debugger Training ๐Ÿ’ป

After learning the basic debugging principles and passing the console exam, the hunters now move on to the second stage of the training. In this stage, they will learn how to use a very powerful weapon known as a debugger. A debugger consists of the following:

Breakpoints

A breakpoint is a signal to the debugger that tells it to pause the execution of the program at a specific point. This allows the developer to inspect the state of the program at that point and step through the code line by line to identify bugs.

Step-through execution:

This feature allows the developer to step through the code one line at a time, examining the state of variables and the program as a whole as they go.

Variable inspection:

Debugging environments usually provide a way for developers to view the values of variables and data structures at any point in the program's execution.

Call stack inspection:

Debuggers also allow developers to examine the call stack, which shows the sequence of function calls that led to the current point in the program's execution. This helps developers trace the flow of control and identify where bugs may be occurring.

Log analysis:

Debugging environments may also provide tools for analyzing log files, which can help developers identify issues that are difficult to reproduce or diagnose.

Hunter Code of Conduct

You have now passed your basic hunter exam. Go out there and gain more skills and become the best hunter you could become!

And of course, after completing the Bug Hunter training, each Hunter had to swear an oath.

  • Document every bug along with the necessary information to help others verify and reproduce.

  • Submit error/ bug reports when possible.


Bug Bounties - Third Act

Practice is the best way to learn! You could try exploring Open Source projects for bugs. This will help you gain practical skills. There are also several bug bounty programs that you can participate in and hopefully earn some cash. Best of luck hunters!

Preventing Bugs

We have explored how to identify and deal with various bugs, this section will explore prevention methods.

Preventing Bugs

Preventing bugs is a crucial step in building robust software.

The 3 Questions Method

I usually ask myself 3 simple questions whenever I try to solve problems at work and on personal projects.

What?

Understanding a problem is 50% of the solution. This helps me understand the problem I am dealing with at a deeper level. This is where I'll ask questions and try to clarify everything before I attempt anything.

How?

After formulating a good understanding of the problem, I'd then start exploring the possible solutions and comparing them.

Why?

Why choose approach A over approach B or C?

Conclusion

The other parts of the saga will explore each concept in detail. Stay tuned!

  • The Planet of The Bugs, The Markup Tribes (Explores HTML and CSS)

  • The Planet of The Bugs, The Scripts Tribe

  • The Planet of The Bugs, The Web (Explores Networking, CORs)

Resources ๐Ÿ“š

Top comments (0)