🐈 D1 · Nest CLI and Module Architecture
D1 · Nest CLI and Module Architecture: NestJS is like **Spring Boot's twin in the TypeScript world**: opposite to Express's "build everything by hand" philosophy, Nest returns to
NestJS is like **Spring Boot's twin in the TypeScript world**: opposite to Express's "build everything by hand" philosophy, Nest returns to an "opinionated" structure — the `@Module`, `@Controller`, `@Injectable` decorators are nearly a direct translation of Java's `@Configuration`, `@RestController`, `@Service`. A module (`AppModule`) declares which controllers and providers (services) are wired together, much like a Spring `@Configuration` class; Nest's own DI (dependency injection) container "wires" them for you. So why return to a "skeleton/discipline" layer after Express? Because freedom speeds up a small prototype, but in a large team (5, 10, 50 developers) EVERYONE needs the same folder structure, the same error handling, the same DI logic — Nest imposes this as a framework decision, just like Spring does. A Java developer seeing Nest for the first time feels right AT HOME: classes, decorators, constructor injection — all familiar. What matters for a tester: module registration (a controller being ADDED to `@Module`) produces a DIFFERENT bug class than an Express route definition — even if the code itself is correct, if it is not registered in the module, that route simply does not EXIST.
Skeleton: Module + Bootstrap
**🐞 Defect Birth — if `BugsController` is not added to `@Module`** **Code:** `bugs.controller.ts` was written entirely correctly (all the `@Controller`, `@Get()` decorators are right), but it was NOT added to the `controllers: [...]` array in `app.module.ts`. **What happens:** the app starts WITHOUT error (the TypeScript compiler does not see this as an error — the class is still a valid class), but Nest's DI container never learns about this controller at all. A `GET /api/v1/bugs` request gets Nest's own default 404 — as if the route was never written. **Why sneaky:** someone opening the file in a code review says "the controller is written correctly" and moves on — because the file's CONTENTS really are correct. The missing piece is a single ARRAY entry in a different file (`app.module.ts`); this is the NestJS counterpart of the "correct code, just not registered in the right place" category. **Where the tester catches it:** even if code review says "everything looks correct", sending a real request and getting 404 — concrete proof of the principle that "code review is not enough, verification on a running system is mandatory".
🎬 Correct Code, Unregistered Controller
BugsController (correct code)
@Module({ controllers })
Route does not exist!
Got 404, checked the code: it was correct
The developer writes `bugs.controller.ts` correctly from start to end — decorators, methods, all fine.
Normally this controller MUST be ADDED to the `@Module({ controllers: [BugsController] })` array.
If this step is SKIPPED, Nest's DI container never learns about this controller — TypeScript's compiler does not consider this an error either.
A `GET /api/v1/bugs` request is sent — even though the route is DEFINED, since it is not REGISTERED with the DI container, Nest returns 404.
The lesson — code review says "the file is written correctly" but the route does not exist in the running system. A tester always verifies with a real request.
A Controller's Journey to "Existing"