DEV Community

DEVANSHU PATIL
DEVANSHU PATIL

Posted on

Debugging Got Easier When I Stopped Guessing

Debugging Got Easier When I Stopped Guessing

One of the biggest mistakes I make while debugging is trying to fix the problem before understanding it.

A screen doesn't update.

An API returns unexpected data.

A database query gives the wrong result.

A deployment fails.

The instinct is immediately:

"What code should I change?"

I've found a better question is:

"What exactly do I know is failing?"

That small change in mindset makes debugging much more systematic.

Start with the symptom

Suppose an Android screen isn't showing a transaction.

There are several possible failures:

User action
    ↓
ViewModel
    ↓
Repository
    ↓
Room
    ↓
Database
Enter fullscreen mode Exit fullscreen mode


`

The UI might be the problem.

But it could also be:

  • The event never reached the ViewModel
  • The ViewModel didn't call the repository
  • The repository queried the wrong data
  • The database contains unexpected data
  • The state wasn't updated
  • The Compose UI isn't observing the expected state

Looking only at the screen can send you in completely the wrong direction.

Follow the data

Instead of changing code randomly, I try to trace the value through the system.

For example:

text
Expected transaction

Was the user action triggered?

Was the ViewModel called?

Was the repository called?

Did the database query return the record?

Did the state contain the record?

Did the UI receive that state?

At some point, the expected behavior diverges from the actual behavior.

That's where I want to investigate.

Logs should answer questions

Adding logs everywhere isn't debugging.

Useful logs answer specific questions.

For example:

text
Fetching transactions for personId = 42
Query returned 3 transactions
Calculated balance = ₹2500
Updating UI state

Now the logs tell you something about the execution path.

Compare that with:

text
DEBUG: function called
DEBUG: something happened
DEBUG: result

Those logs create noise without explaining the system.

The goal isn't to have more logs.

It's to have useful evidence.

Reproduce before fixing

If a bug happens only sometimes, the first objective should be making it reproducible.

Try to identify:

`text
Input
+
Sequence of actions
+

Application state

Bug
`

For example:

text
Open transaction
→ Edit amount
→ Save
→ Navigate back
→ Open transaction again
→ Incorrect value appears

Now you have a scenario you can test repeatedly.

Without reproducibility, you can easily "fix" the wrong problem.

Check assumptions

A surprisingly large number of bugs come from assumptions.

For example:

"This ID can never be null."

"This API always returns this field."

"This query always returns one record."

"The database must contain the correct value."

"The code definitely reached this function."

Instead of trusting the assumption, verify it.

text
Assumption

Evidence

Confirmed / disproved

This is especially important when debugging systems with multiple layers.

Don't change five things at once

If I change:

text
Query
+
ViewModel
+
UI state
+
Database schema
+
API response

and the bug disappears, I still don't know what actually fixed it.

Worse, I might have introduced another bug.

A better approach is:

text
Hypothesis

Small change / test

Observe result

Update hypothesis

Debugging becomes an investigation rather than a guessing game.

The same method works outside Android

This approach isn't specific to Compose or Kotlin.

For a backend request:

text
Client

Reverse proxy

API

Business logic

Database

For a VPS deployment:

text
DNS

Server

Reverse proxy

Container

Application

For every system, the same question applies:

Where does the actual behavior first differ from the expected behavior?

Find that point.

Then investigate it.

The lesson I'm taking from this

Debugging isn't primarily about knowing more fixes.

It's about reducing uncertainty.

At the beginning:

text
Something is broken.

After investigation:

text
The request reaches the API.
The API returns the correct data.
The repository receives it.
The ViewModel state is correct.
The UI is displaying stale state.

Now the problem is much smaller.

And once the problem is smaller, the fix is usually much easier to find.

**Don't debug by changing code until something works.

Debug by collecting evidence until you know what is wrong.**

debugging #android #kotlin #softwareengineering #backend #programming #jetpackcompose #development #buildinpublic

Top comments (0)