Skip to content

Instantly share code, notes, and snippets.

@craftybones
Last active March 14, 2026 12:23
Show Gist options
  • Select an option

  • Save craftybones/4b40534f43d38636d14977455ba62f7c to your computer and use it in GitHub Desktop.

Select an option

Save craftybones/4b40534f43d38636d14977455ba62f7c to your computer and use it in GitHub Desktop.

Common Errors Across Projects

Categories

  1. Weak Separation of Concerns
  2. Domain Layer Leaking HTTP Concepts
  3. Missing or Improper Dependency Injection
  4. Missing Persistence or Improper Storage Design
  5. Weak or Absent Automated Testing
  6. Inconsistent API Contracts Between Frontend and Backend
  7. DOM Manipulation Instead of State-Driven Rendering
  8. Fragile Data Modeling

1. Weak Separation of Concerns

What it means

Handlers, domain logic, persistence logic, and routing are mixed together in the same modules.

Instead of having layers like:

routes → handlers → domain → persistence

projects collapse everything into one layer.

Why it matters

Without separation:

  • Testing becomes difficult
  • Refactoring becomes dangerous
  • Code reuse becomes impossible
  • Bugs propagate across layers

This is one of the first architectural instincts engineers must develop.

Example

Bad pattern:

app.post("/task", async (c) => {
  const body = await c.req.json();
  todos.push(body);
  await Deno.writeTextFile("db.json", JSON.stringify(todos));
  return c.json({ ok: true });
});

Here the route:

  • parses HTTP
  • mutates domain state
  • writes to disk

All inside the same function.

Antidote

Introduce clear layers:

app.js → handler.js → todoManager.js → storage.js

Example:

export const createTaskHandler = (manager) => async (c) => {
  const task = await c.req.json();
  const result = manager.createTask(task);
  return c.json(result);
};

Pairs with this issue

  • Nikhil Chodavarapu / Dinesh Kumar
  • Sorangi Gopi Vinay / Priyanshu Arya
  • Javed Ahmed / Vismaya P S

2. Domain Layer Leaking HTTP Concepts

What it means

Domain classes return HTTP responses or HTTP-style objects instead of domain objects.

Example:

return { success: true, status: 200 };

Why it matters

The domain layer should not know transport protocols.

If domain objects depend on HTTP semantics:

  • They cannot be reused in CLI tools
  • They cannot be reused in different APIs
  • They mix business logic with transport logic

Example

Bad:

class TodoManager {
  addTask(task) {
    if (!task) {
      return { status: 400, error: "invalid task" };
    }
    tasks.push(task);
    return { status: 200 };
  }
}

Antidote

Domain layer returns domain values or throws domain errors.

class TodoManager {
  addTask(task) {
    if (!task) throw new Error("invalid task");
    tasks.push(task);
    return task;
  }
}

Handlers translate this to HTTP:

try {
  const task = manager.addTask(data);
  return c.json(task);
} catch {
  return c.json({error:"invalid task"}, 400);
}

Pairs with this issue

  • Amisha Rawat / Jyothi Praveen Gorre
  • Som Nath Gupta / Karthik Dasari
  • Rahul Vishwakarma / Peddakota Bhargavi

3. Missing or Improper Dependency Injection

What it means

Shared state like todoManager or db is imported globally instead of injected.

Example:

import todoManager from "./todo_manager.js"

Why it matters

Without DI:

  • Tests cannot swap dependencies
  • State becomes hidden global state
  • Multiple app instances become impossible

Dependency injection makes systems composable and testable.

Example

Bad:

import db from "./db.js"

export const createTask = (c) => {
  db.tasks.push(...)
}

Antidote

Inject dependencies through middleware or constructor.

Example:

app.use((c, next) => {
  c.set("todoManager", todoManager);
  return next();
});

Then handlers read from context.

Pairs with this issue

  • Nikhil Chodavarapu / Dinesh Kumar
  • Sorangi Gopi Vinay / Priyanshu Arya

(Some others implemented DI correctly.)


4. Missing Persistence or Improper Storage Design

What it means

Projects remain in-memory only, or persistence is implemented incorrectly.

Phase-2 required data to survive server restarts .

Why it matters

Persistence is fundamental to real applications.

Without persistence:

  • Systems lose state
  • Testing production behavior becomes impossible
  • Restarting servers wipes user data

Example

Bad:

let todos = [];

Better:

readFile("db.json")
writeFile("db.json")

Or a database abstraction.

Antidote

Introduce a storage abstraction:

TodoManager(storage)

Where storage could be:

  • JSON file
  • SQLite
  • memory

This enables easy swapping and testing.

Pairs with this issue

  • Vivek Bhardwaj / Khasim Sheik
  • Paulami Dutta / Sivaji Sai
  • Samiran Gharami / Rashmika Gandra
  • Adithyan K / Dilliswara Rao Galala
  • Gautham Krishna T G / Sidhartha Maji
  • Vikas Yadav / Chiranjeevi Gurram
  • Sorangi Gopi Vinay / Priyanshu Arya

5. Weak or Absent Automated Testing

What it means

Either:

  • No tests
  • Only trivial tests
  • Only unit tests but no route tests

Why it matters

Testing is the only scalable way to evolve systems safely.

Without tests:

  • Refactoring becomes dangerous
  • Regression bugs appear
  • Edge cases are ignored

Example

Weak test:

assertEquals(res.status, 200)

Better test:

assertEquals(res.body.task.text, "Buy milk")

Antidote

Test three layers:

  1. Domain logic
  2. HTTP handlers
  3. Integration behavior

Example:

app.request("/task", {...})

Pairs with this issue

  • Nikhil Chodavarapu / Dinesh Kumar
  • Shaik Rafiya / Dasari Nandini
  • Som Nath Gupta / Karthik Dasari
  • Rahul Vishwakarma / Peddakota Bhargavi
  • Sanket Pawar / IBRAHIM BADUSHA KK
  • Javed Ahmed / Vismaya P S

6. Inconsistent API Contracts

What it means

Frontend and backend disagree on request/response format.

Example:

Frontend sends:

POST /task?todoId=1

Backend expects:

{todoId:1}

Why it matters

When contracts drift:

  • Bugs become difficult to trace
  • Systems become brittle
  • Integration breaks easily

Example

Frontend expects:

{ data: ... }

Backend returns:

{ message: "ok" }

Antidote

Define an API contract.

Example:

POST /todos/:id/tasks
→ returns {task}

Both sides implement against this.

Pairs with this issue

  • Som Nath Gupta / Karthik Dasari
  • Umar Khaji / Adarsh P
  • Javed Ahmed / Vismaya P S

7. DOM Mutation Instead of State-Driven Rendering

What it means

Frontend directly manipulates DOM elements after operations.

Example:

element.remove()

instead of updating state and re-rendering.

Why it matters

Direct DOM mutation causes:

  • UI state drift
  • inconsistent rendering
  • difficult debugging

State should be the single source of truth.

Example

Bad:

button.onclick = () => {
  li.remove()
}

Better:

tasks = tasks.filter(...)
render(tasks)

Antidote

Adopt render-from-state architecture.

state → render → DOM

Many teams solved this by re-rendering the whole list after every mutation.

Pairs with this issue

  • Jeniffer P Jojo / Ayush Verma
  • Javed Ahmed / Vismaya P S
  • Abhay Pratap Singh / Sirisha Dalasari

8. Fragile Data Modeling

What it means

Data structures make relationships fragile.

Example:

tasks = []
todos = []
task.todoId

with frequent filtering.

Or storing IDs in DOM strings:

task-1
todo-2

Why it matters

Weak models cause:

  • inefficient lookups
  • hidden bugs
  • brittle coupling between frontend and backend

Example

Bad:

tasks.filter(t => t.todoId === id)

Better:

todos = {
  [todoId]: { tasks: {...} }
}

Antidote

Use normalized structures.

todos -> tasks

or relational models.

Pairs with this issue

  • Javed Ahmed / Vismaya P S
  • Shaik Rafiya / Dasari Nandini
  • Himanshu Jaguri / Gajulapalli Mohanthi
  • Nikhil Chodavarapu / Dinesh Kumar

Final Observation

Across the cohort, three core engineering instincts separate strong submissions from weak ones:

  1. Layered architecture
  2. Testing discipline
  3. State modeling

Teams that got these right produced clean, extensible systems.

Teams that missed them struggled with fragile code and integration bugs.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment