Discover how a few simple markers can transform messy code into clean, powerful architecture!
Why Decorator-based architecture in NestJS? - Purpose & Use Cases
Imagine building a large server app where you must manually add logging, validation, and routing code everywhere.
You write repetitive code in every function to check inputs, log actions, and handle errors.
This manual approach is slow and error-prone.
You might forget to add validation or logging in some places, causing bugs and inconsistent behavior.
It's hard to read and maintain because the core logic is mixed with extra code.
Decorator-based architecture lets you add extra behavior by simply placing special markers (decorators) on classes or methods.
This keeps your main code clean and lets the framework handle the extra work automatically.
function getUser(id) {
console.log('Fetching user', id);
if (!id) throw new Error('Invalid ID');
// fetch user logic
}@Log()
@Validate()
getUser(id) {
// fetch user logic
}It enables clean, readable code where extra features like logging and validation are added simply and consistently.
In NestJS, you can add @Controller and @Get decorators to define routes clearly without writing routing logic manually.
Manual code mixes core logic with repetitive tasks, making it messy.
Decorators let you mark where extra behavior should happen, keeping code clean.
This leads to easier maintenance and fewer bugs.
Practice
@Controller() and @Injectable()?Solution
Step 1: Understand decorator roles in NestJS
Decorators like@Controller()and@Injectable()add metadata to classes, telling NestJS their purpose.Step 2: Recognize how NestJS uses this metadata
NestJS uses this metadata to organize and manage components like controllers and services during runtime.Final Answer:
To mark classes with specific roles and add metadata for NestJS to manage -> Option CQuick Check:
Decorators add metadata = C [OK]
- Thinking decorators run methods automatically
- Confusing decorators with styling tools
- Believing decorators remove the need for methods
Solution
Step 1: Recall the syntax for controller decorators
In NestJS, the@Controller()decorator is placed immediately before the class definition.Step 2: Check each option for correct decorator usage
@Controller() class MyController { } correctly shows@Controller()before the class. class MyController { } lacks any decorator. function Controller() { } class MyController { } incorrectly defines a function instead of using a decorator. @Injectable() class MyController { } uses@Injectable()which is for services, not controllers.Final Answer:
@Controller() class MyController { } -> Option AQuick Check:
Controller decorator before class = B [OK]
- Omitting the decorator entirely
- Using @Injectable() instead of @Controller()
- Trying to define decorators as functions
@Controller('hello')
export class HelloController {
@Get()
greet() {
return 'Hello, NestJS!';
}
}Solution
Step 1: Analyze the route and method decorators
The@Controller('hello')sets the base path to '/hello'. The@Get()decorator ongreet()means this method handles GET requests to '/hello'.Step 2: Understand the method return value
Thegreet()method returns the string 'Hello, NestJS!'. So, a GET request to '/hello' returns this string as the response.Final Answer:
"Hello, NestJS!" -> Option AQuick Check:
GET /hello returns method string = A [OK]
- Assuming 404 because of missing route
- Expecting JSON instead of string
- Thinking decorators cause runtime errors here
@Injectable
export class UserService {
getUser() {
return { name: 'Alice' };
}
}Solution
Step 1: Check the decorator syntax
The@Injectabledecorator requires parentheses even if no arguments are passed, so it should be@Injectable().Step 2: Verify other code parts
The methodgetUser()can be synchronous and return an object. Class name and return type are valid as is.Final Answer:
Missing parentheses in @Injectable decorator -> Option BQuick Check:
@Injectable() needs parentheses = D [OK]
- Omitting parentheses on decorators
- Thinking methods must be async
- Changing class names unnecessarily
Solution
Step 1: Identify the correct HTTP method and route parameter usage
The route is '/users/:id' and should respond to GET requests, so@Get(':id')is correct.Step 2: Check parameter decorator usage
The method parameter must use@Param('id')to extract the 'id' from the URL path.@Controller('users') export class UserController { @Get(':id') getUser(@Param('id') id: string) { return `User ID is ${id}`; } }does this correctly.Step 3: Verify other options
@Controller('users') export class UserController { @Get() getUser(@Body('id') id: string) { return `User ID is ${id}`; } }uses@Body('id')which reads from request body, not URL.@Controller('users') export class UserController { @Post(':id') getUser(@Param('id') id: string) { return `User ID is ${id}`; } }uses POST instead of GET.@Controller('users') export class UserController { @Get(':id') getUser(id: string) { return `User ID is ${id}`; } }misses the@Paramdecorator, so 'id' won't be injected.Final Answer:
The code snippet with @Get(':id') and @Param('id') -> Option DQuick Check:
GET + @Param('id') for URL param = A [OK]
- Using @Body instead of @Param for URL params
- Using wrong HTTP method decorator
- Forgetting @Param decorator on method argument
Ready to prove it?
Pass the test and this pattern moves unknown
