Logo
Logo
Home
Archive
AI Agent Notes
Advertise
YouTube
Login
Sign Up
Logo
  • Home
  • Posts
  • 🦥 Debugging Techniques You Should Know

🦥 Debugging Techniques You Should Know

Jul 2, 2024

Hello friends!

Welcome to this week’s Sloth Bytes. Hope you had an amazing week!

Sloths sleep as long as humans

Gif by CoopPrix on Giphy

People think that sloths sleep for 20 hours a day, but that’s a myth! Wild sloths only sleep for about 8 to 10 hours each day, about the same as humans.

Debugging Techniques

What is debugging?

Debugging is the process of finding the cause of incorrect or surprising behavior, then verifying a fix. The visible failure is a symptom; the useful question is what state, input, assumption, race, dependency, or code path produced it.

Why is debugging important?

  • Quickly identify and fix issues

  • Improves code quality

  • Understand your code better

  • Learn from mistakes and prevent future bugs

Techniques

  1. Print statements / temporary instrumentation: Add focused output around the state or branch you are investigating.

    How it helps: Confirms what values and paths actually occurred instead of what you assumed occurred.

    When to use: Quick local checks, small scripts, or places where attaching a debugger is inconvenient. Remove noisy temporary output afterward and never dump credentials/tokens/personal data just because “it’s only debugging.”

Example:

def calculate_sum(a, b):
    # Debug print
    print(f"a: {a}, b: {b}")
    # Debug print
    result = a + b
    print(f"result: {result}")
    return result

sum = calculate_sum(5, 3)
print(f"Sum: {sum}")
  1. Using a Debugger: A tool that allows you to pause code execution, step through it line by line, and inspect variable values.

    How it helps: Gives detailed insight into code execution and variable states at any point.

    When to use: For complex bugs or when you need to closely examine code behavior.

    Here’s an example video using a debugger for python code

  1. Raise/propagate meaningful errors: Use exceptions or error values to add context at the layer that actually understands what failed.

    How it helps: Preserves a useful failure path while explaining what operation/input caused it.

    When to use: When a caller needs actionable context. User-facing/API errors should be safe and stable; detailed stack traces and internal diagnostics belong in developer/operator logs, not blindly in the browser.

Example:

def divide(a, b):
    if b == 0:
        raise ValueError("b must be non-zero")
    return a / b

try:
    result = divide(10, 0)
except ValueError as exc:
    print(f"Could not divide values: {exc}")

# Output:
# Could not divide values: b must be non-zero

  1. Assertions: Check internal invariants—conditions that should be true if your program is correct.

    How it helps: Makes impossible/internal-bug states fail close to their cause during development and testing.

    When to use: Programmer assumptions and invariants. Do not use Python assert as your only validation for user input, permissions, payments, or other required runtime checks; Python can remove assertions when run with optimization.

Example:

def normalized_percent(part, total):
    # Internal invariant: the caller already validated total.
    assert total > 0, "total must be positive"
    return part / total

# For external/user input, perform a normal runtime check instead:
def safe_average(numbers):
    if not numbers:
        raise ValueError("numbers must not be empty")
    return sum(numbers) / len(numbers)
  1. Rubber Duck Debugging: Explain your code line by line to somebody, or if you don't have friends, to some object (like a rubber duck).

    How it helps: Forces you to articulate your logic, often revealing flaws in your thinking.

    When to use: When you're stuck and need a fresh perspective on your code.

  1. Logging / observability: Record structured context about requests, jobs, failures, timing, and important state transitions.

    How it helps: Lets you investigate bugs you cannot reproduce locally—especially intermittent production failures.

    When to use: Long-running services, background jobs, distributed systems, or any issue where you need history. Include correlation/request IDs and useful fields, but redact secrets and sensitive data.

Example:

import logging

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)

def divide(a, b):
    logger.debug("divide called", extra={"denominator_is_zero": b == 0})
    if b == 0:
        logger.warning("division rejected: zero denominator")
        raise ValueError("b must be non-zero")
    return a / b

try:
    result = divide(10, 2)
    logger.info("division completed")
except ValueError:
    logger.exception("division failed")

My Debugging Process

  1. Reproduce the bug reliably. Capture the input, environment, version/commit, browser/device, timing, and exact steps.

  2. Reduce the reproduction. Remove unrelated code/data until you have the smallest case that still fails. Smaller bugs are easier to reason about.

  3. Preserve evidence before changing things. Read the full error/stack trace, logs, network request, database state, or profiler trace. Restarting everything may destroy the clue.

  4. Form a hypothesis. State what you think is wrong and what observation would prove/disprove it.

  5. Change one variable at a time. Add a breakpoint/log, compare a known-good case, or temporarily remove half the suspected path. Randomly changing five things creates new mysteries.

  6. Find the root cause. Fix the violated assumption/invariant, not merely the visible symptom.

  7. Add a regression test when practical. Make the bug fail before the fix and pass afterward so it stays dead.

  8. Test neighboring behavior. Verify the fix did not break another path or only handle one lucky example.

  9. Commit/document the useful lesson. Update tests, comments/docs, monitoring, validation, or runbooks when the root cause revealed a systemic gap.

Tips for Effective Debugging

  • Read the whole error first. The stack trace is often a map, not decorative red text.

  • Compare good vs bad. Inputs, environment variables, versions, requests, database rows, and timing differences are powerful clues.

  • Use version control/bisecting. If it used to work, identify the smallest change range that introduced the behavior.

  • Beware Heisenbugs. Logging, timing, breakpoints, and debug builds can change race/timing-sensitive behavior; collect evidence with the least intrusive instrumentation that works.

  • Take breaks and explain the problem. Rubber-ducking or writing a good question forces assumptions into the open.

  • Do not “fix” by swallowing errors. Removing the exception/log or adding a giant try/except can hide the alarm while the fire keeps burning.

Remember, debugging is a skill that improves with practice. Each bug you solve makes you a better programmer!

If you want to keep learning

  • Error handling explained — how exceptions and failures should be handled once you’ve found the bug.

  • Code profiling explained — find CPU and memory bottlenecks when the problem is performance, not correctness.

  • Command Line for beginners — get comfortable with the terminal tools you’ll constantly use while debugging.

  • How to ask better programming questions — when you’re stuck, give people the context, errors, and reproduction steps they actually need to help.

Binary Search

What is Binary Search?

Binary search is an efficient algorithm for finding a target value in a sorted array. It works by repeatedly dividing the search interval in half.

Why is it important?

  • Extremely efficient for large datasets

  • Common interview topic

How it works

  1. Start with the middle element of the sorted array

  2. If the target value is equal to the middle element, we're done

  3. If the target is less than the middle element, repeat the search on the left half

  4. If the target is greater than the middle element, repeat the search on the right half

  5. Repeat until the target is found or it's clear the target isn't in the array

Time Complexity

  • O(log n) - much faster than linear search O(n) for large datasets

Basic Implementation (Python):

def binary_search(arr, target):
    left, right = 0, len(arr) - 1
    
    while left <= right:
        mid = (left + right) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    
    return -1  # Target not found

# Example usage
sorted_array = [1, 3, 5, 7, 9, 11, 13, 15, 17]
target = 7
result = binary_search(sorted_array, target)
print(f"Target {target} found at index: {result}")

Key Points to Remember

  1. The array must be sorted for binary search to work

  2. It's much faster than linear search for large datasets

  3. Can be implemented iteratively (as above) or recursively

  4. Be careful of integer overflow when calculating mid point (use left + (right - left) // 2 for very large arrays)

Tips for Interviews

  • Always ask if the array is sorted

  • Consider edge cases (empty array, target not in array)

  • Think about how to handle duplicates

  • Be prepared to explain the time and space complexity

Figma Config 2024 recap (7 minute read)

Figma announced a lot of things! A redesign, Figma Slides, and a new suite of AI features, along with major updates to Dev Mode and usability improvements.

Instagram is starting to let some creators make AI versions of themselves (2 minute read)

Soon, you might chat with an AI version of your favorite creator.

Remove Polyfill.io code from your website immediately (5 minute read)

Scripts turn sus after mysterious CDN swallows domain

Video Calling API for Web and App Developers | Whereby

Get started for free and integrate WebRTC video calls into your website or app using the Whereby API and SDK.

The Best Social Media Site Still Looks Like It Was Made in the 1990s (12 minute read)

Craigslist forces its users to trust each other. Other social media sites should take note.

Toys “R” Us riles critics with “first-ever” AI-generated commercial using Sora (5 minute read)

AI-generated commercials are here, and critics are displeased—but human work is still key.

Prisma, Drizzle, TypeORM or Sequalize — When Your Focus Is Scale, Which One To Choose? (7 minute read)

Node.js ecosystem is experiencing an interesting development of toolings in the ORM fields.

Thank you to everyone who submitted last week!

Vijaychandra2, Anand Prabhu, 220241, CarolinaFalcao, QueenlyHeart, ddat828, IshanKumar22, Codin-bee, Nuc1earOwl, Shraddha Patel, ravener, Addleo, RelyingEarth87, and many more (You all are awesome. Sorry if you were left out; there are a lot of submissions.)

Binary Search Practice

Given a sorted array of integers and a target integer, find the first occurrence of the target and return its index.

Return -1 if the target is not in the array.

Examples

#Input:

arr = [1, 3, 3, 3, 3, 6, 10, 10, 10, 100]

target = 3

find_first_occurrence(arr,target) # Return 1

#Explanation: The first occurrence of 3 is at index 1.
#Input:

arr = [2, 3, 5, 7, 11, 13, 17, 19]

target = 6
find_first_occurrence(arr,target) # Return -1

#Explanation: 6 does not exist in the array.

How To Submit Answers

Reply with

  • A link to your solution (github, twitter, personal blog, portfolio, replit, etc)

Published that yap session

Yes, I posted the video I teased last week. If you haven't seen it yet, check it out.

Back to working on the AI project

Spent most of last week editing, so now I’m back to working on this project. I keep getting ideas for it, but I’m doing my best to stay on track (I won’t let feature creep win).

That’s all from me!

Have a great week, be safe, make good choices, and have fun coding.

See you all next week.

Keep Reading

Read all
arrow-right
envelope-simple

Join 50k+ developers and become a better programmer and stay up to date in just 5 minutes.

© 2026 Sloth Bytes.
beehiivPowered by beehiiv