Logo

dev-resources.site

for different kinds of informations.

Six Factors That Raise The Risk Of Bugs In A Codebase

Published at
3/4/2024
Categories
bugs
architecture
patterns
codequality
Author
timothyokooboh
Author
14 person written this
timothyokooboh
open
Six Factors That Raise The Risk Of Bugs In A Codebase

As a frontend developer, I've come across several key factors that greatly impact the presence of bugs in a codebase. While my insights are based on JavaScript applications, these principles are relevant across different codebases. Let's explore them together.

1. Lack of Static Code Analysis
Static code analysis tools like TypeScript and ESLint play a crucial role in identifying and preventing bugs. TypeScript provides static typing, enhancing the robustness of the code. ESLint detects issues and enforces coding standards. The absence of these tools can significantly elevate the likelihood of bugs due to the lack of early detection and guidance provided during development.

// Example of TypeScript usage
// Define a function with static typing
function greet(name: string): string {
  return 'Hello, ' + name;
}
Enter fullscreen mode Exit fullscreen mode

2. Lack of Automated Testing
Codebases devoid of automated tests, such as unit and end-to-end tests, are at risk of too many bugs. Without automated tests, the detection of regressions and bugs relies heavily on manual testing, leaving room for oversight and undetected issues. Consequently, developers may hesitate to introduce changes or refactor existing code, fearing unintended consequences. When working on a codebase that lacks automated tests, it becomes really hard to ship new features with confidence.

// sample unit test with jest
test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

// sample end to end test with playwright
test.describe("porfolio page", () => {
  test.beforeEach(async ({ page }) => {
    await page.goto("/portfolio");
  });

 test("can view the tech jobs project", async ({ page }) => {
    await page.getByTestId("techjobs").click();
    await expect(page).toHaveURL("http://localhost:3000/portfolio/techjobs");
});
)
Enter fullscreen mode Exit fullscreen mode

3. Lack of a Continuous Integration Build Process
Codebases lacking a continuous integration (CI) build process miss out on automated checks for production readiness, code quality, and test coverage. Without CI, discrepancies between developer environments and the production environment may lead to undetected bugs surfacing in production. Depending on where your code repository is located, you can setup a CI workflow using GitHub Actions, Bitbucket Pipelines, Gitlab CI etc.

Example of a GitHub Action workflow that checks the formatting of files, builds for production, checks linting and runs test cases

name: CI

on:
  push:
    branches:
      - develop
      - master

  pull_request:
    branches:
      - develop
      - master

jobs:
  actions:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: cache dependencies
        uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: yarn

      - name: install dependencies
        run: yarn

      - name: check formatting of files
        run: yarn format:check

      - name: build for production
        run: yarn build

      - name: check linting of files
        run: yarn lint

      - name: run unit tests
        run: yarn test:unit

Enter fullscreen mode Exit fullscreen mode

4. Misleading Variable or Function Names
A variable or function is considered misleading if its name does not accurately reflect its functionality. This discrepancy can lead to bugs when developers rely on the function's name to guide their implementation logic. For instance, consider the function isLoggedIn. One would expect it to return true if a user is logged in and false otherwise. However, imagine if the function returns a user object when a user is logged in and null otherwise. While a user object is a truthy value and null is a falsy value, such discrepancies in return types can result in unintended bugs.

// Better
const isLoggedIn = () => auth.currentUser ? true : false;
OR
const isLoggedIn = () => !!auth.currentUser;

// Misleading
const isLoggedIn = () => auth.currentUser ? auth.currentUser : null;
Enter fullscreen mode Exit fullscreen mode

5. Multiple Sources of Truth for the Same State
Having multiple sources of truth for the same state can lead to bugs that are hard to trace or debug. It introduces inconsistency and confusion into the codebase, making it difficult to maintain and debug issues. Consider the example below

// Vue.js

<template>
 <input type="text" v-model="loanBalance">
</template>

<script setup lang="ts">
const loanBalance = ref<number>(0)

const getLoanBalance = async (userId: string) => {
 const response = await axios.get(`/loans/users/${userId}`)
 loanBalance.value = response.data.data;
}

const updateLoanBalance = (balance: number) => loanBalance.value = balance
</script>
Enter fullscreen mode Exit fullscreen mode

The component above has three sources of truth for the state loanBalance: the input field (two-way data binding), the getLoanBalance function, and the updateLoanBalance function. When a state is modified in many places, such multiple side effects can lead to bugs that are hard to trace and debug.

6. Redundant States
A component contains redundant states if the same value is stored in more than one state. This becomes problematic if you have to manually keep track of the states and ensure they contain the same value.

// Vue.js

interface Notification {
 subscribers: string[];
 message: string
}

 const notification = ref<Notification>(
 { 
   subscribers: [],
   message: ''
 }
)

const subscribers = ref<string[]>([])

const getNotification = async () => {
 const response = await axios.get('/notifications')
 notification.value = response.data.data;
 subscribers.value = notification.value.subscribers
}
Enter fullscreen mode Exit fullscreen mode

In the example above, the list of subscribers is contained in both the notification state and the subscribers state. Having to manually ensure that both states contain the same value can lead to bugs.

However, if subscribers need to be accessed across multiple places in the component, it is much better to use a computed property to ensure that you don't have to manually synchronize the values.

 // Vue.js
const notification = ref<Notification>(
 { 
   subscribers: [],
   message: ''
 }
)

const subscribers = computed(() => notification.subscribers))

// React
const [notification, setNotification] = useState({})

const subscribers = useMemo(() => {
  return notification.subscribers
 }, [notification.subscribers]
)

Enter fullscreen mode Exit fullscreen mode

In conclusion, the pursuit of bug-free code is an ongoing endeavor. Throughout this article, we've explored six key factors that contribute to the proliferation of bugs within a codebase. From the absence of static code analysis and automated testing infrastructure to the presence of misleading variable names and duplicate states, each factor presents its own set of challenges and risks. By acknowledging these factors and implementing strategies to mitigate their impact, developers can strive towards building more robust and resilient software applications.

bugs Article's
30 articles in total
Favicon
Debug or Be Doomed: How Errors Nearly Sparked World War III
Favicon
The Bug Bounty Dilemma: Are We Rewarding Skills or Exploits in Blockchain?
Favicon
How Can I Create a DevOps Pipeline That Automatically Resolves All Conflicts and Bugs Without Human Intervention?
Favicon
Little Bugs, Big Problems
Favicon
The 29 Days per Year Bug (30 Days for Leap Years!)
Favicon
A Quick Look at Why We Call Them "Software Bugs"
Favicon
Cleaning routines to keep your project without bugs
Favicon
This month we're snug as a bug under a Glitch-powered rug
Favicon
Six Factors That Raise The Risk Of Bugs In A Codebase
Favicon
Error monitoring and bug triage: Whose job is it?
Favicon
5 platform that pay huge if you're an Ethical H4CK3R
Favicon
5 platform that pay huge if you're an Ethical H4CK3R
Favicon
How to optimise JMeter for performance tests
Favicon
Crush Bugs with Laravel Contract-Based Testing
Favicon
When Two Bugs Cancel Out
Favicon
The Anatomy of a Perfect Bug Report: What It Needs to Contain
Favicon
Code Detective: Unraveling Bugs in Your Code
Favicon
Priority and Severity of tasks and bugs
Favicon
Burning Bugs at Manychat: Sharing Expertise and Experience in Bug Management
Favicon
"Bugs in Software Development: Types and Real-World Examples
Favicon
Java 101 for software testing (Using fruits and vehicle asย example)
Favicon
Just one more check before I push my changes
Favicon
Reiterating why you should never use Array โ€˜indexโ€™ as โ€˜keyโ€™ in your React Applications
Favicon
Today I intentionally copied a bug
Favicon
What causes bugs?
Favicon
Why are Software bugs named bugs?
Favicon
What Is Holding A Software Tester From Finding Bugs?
Favicon
Data Races with value types in Swift
Favicon
uint vs uint256 -> Small Solidity detail that can cause big Heisenbug
Favicon
dev.to says 1

Featured ones: