NodeJS

How to make your controller code cleaner?


In order to make the code in the controller to be clean, readable, and easy to follow as your application is built with NestJS, the above guidelines can be put into consideration. This approach is especially useful when collaborating with multiple developers. The following best practices can also be used to improve your controller code as you suggested in this example.

 

Make proper use of decorators

It is rather simple to take repeated decorators such as @Roles, @UseGuards and put them before classes that are reused. Rather than having to repeat these decorators in each method, also they can be combined together using a custom decorator.

@Controller({ path: 'alert', version: '1' })@ApiTags('alert')@Roles(Role.USER)@UseGuards(AuthGuard("jwt"), RolesGuard)export class AlertController {… } 

Separate Swagger Config for Maintainability

When working on large scale applications it’s better to consolidate Swagger Config into a separate file. This makes it easier to update and manage the configs especially when the Application grows or scales.

Example: Standalone Swagger File (alert.swagger.decorators.ts)

In this file, you can define the Swagger configurations created using the applyDecorators function which can then be used in controllers where it has been imported.

// alert.swagger.decorators.tsexport const AlertSwaggerDecorators = {    generateAlert: () => applyDecorators(        ApiBearerAuth(),        ApiOperation({ summary: "Generates an alert" }),        ApiResponse({            status: HttpStatus.CREATED,             description: "Api success",             schema: {                allOf: [                    {                        properties: {                            message: { example: getSuccessMessageResponse('ALERT_GENERATE_SUCCESS') },                            data: { $ref: getSchemaPath(GenerateAlertResponseDto) },                        },                    },                ],            },        })    ),    // You can continue defining other Swagger decorators in a similar manner};

 

Controller File

Then, in your controller, you can simply import and use these decorators:

// alert.controller.ts    @AlertSwaggerDecorators.generateAlert()    async generateAlert(        @Body() generateAlertDTO: GenerateAlertRequestDto,        @Req() request    ) {        return this.alertService.generateAlert(generateAlertDTO, request);    }}

By this way all your swagger decorators are applied in just one line, so it will make the controller more cleaner and readable.

Use the Service Layer

Do not pack your controller with too much business logic. The business logic of the application should be coded in services while the controller is meant for receiving HTTP requests. In the example, the AlertService is handled by the actual logic to which methods like generateAlert, stopAlert, and addAlertLocation transfer their work.

return this.alertService.generateAlert(user, generateAlertDTO, getLanguage(request)); 

Place Related Endpoints Together

If you have endpoints that perform similar operations on the same resource (for example, alerts) place them under the same controller. This helps to keep things clean and structured.

The example does a great job of keeping all the alert-related functionality under the /alert route, such as generating, stopping, and managing alerts.

@Controller({ path: 'alert', version: '1' })

Do Not Forget Validation and Transformation

To enhance the capability of HttpServer, NestJS makes use of transformers which aid in validating and transforming user designed input data. Use pipes for doing validation instead of handling validation in the handler of every route separately. In the example, ValidationPipe is utilized for validating the input in order to control the data that is supplied inputs to the methods in the controller.

@Body(ValidationPipe) generateAlertDTO: GenerateAlertRequestDto

Custom Error Handling

It is clear that having independent messages per scenario is effective in condensing the boilerplate code while preserving many ways of dealing with many types of errors. In the example, errors for each endpoint are abstracted out by custom decorators like ApiResponseStatus and from their endpoints where the errors are applied.

ApiResponseStatus([HttpStatus.BAD_REQUEST, HttpStatus.NOT_FOUND])

Reduce Dependencies in the Constructors

For each controller, ensure that you inject only the services required. Doing this ensures that your controller remains concentrated on its main function of processing HTTP requests and branching out to the available services.

constructor(private readonly alertService: AlertService) { }  

Formatting Codes

Always remain consistent with the formatting style and even the naming format throughout your project. This is very important in enhancing the readability of the Project and reducing cases of confusion. Ensure that you properly indent, use spaces, and use proper naming formats in situations such as when dealing with DTOs and API responses.

 

Ready to transform your business with our technology solution? Contact Us today to Leverage Our NodeJS Expertise.

0

NodeJS

Related Center Of Excellence