DEV Community

Teerasak Vichadee
Teerasak Vichadee

Posted on

ทำ IoC ใน NestJS อย่างเหมาะสม

ใน NestJS document เค้าบอกเราว่า จะทำ IoC ใน NestJS ทำแบบนี้

// user/user.module.ts
@Module({ 
  providers: [UserService],
  controllers: [UserController],
})
export class UserModule {}
Enter fullscreen mode Exit fullscreen mode

เพียงเท่านี้ UserController ก็จะสามารถใช้งาน UserService ได้เพียงแค่เรา inject UserService เข้าไปใน constructor

@Controller() 
export class UserController {
  constructor(
    private readonly userService: UserService
  ) {}
}
Enter fullscreen mode Exit fullscreen mode

นั่นทำให้หลายคนคิดเอาเองว่า ถ้าในกรณีที่ต้องการใช้ service ที่อยู่ใน module อื่น เราก็แค่เอามาใส่ใน Module.providers น่ะสิ

หน้าตาของ code ใน module ก็เลยกลายเป็นแบบนี้

// user/user.module.ts
@Module({ 
  providers: [UserService, TodoService],
  controllers: [UserController],
})
export class UserModule {}
Enter fullscreen mode Exit fullscreen mode

ถ้าเจอ code แบบนี้ ใน code review เราควรจะถามว่า

แล้ว module จะมีความสำคัญอะไร ทำไมถึงยังต้องมี module อยู่ ในเมื่อสามารถเอา service จากไหนก็ได้มาใส่

การเอา service จาก module อื่นมาใช้งานด้วยการใส่ลงไปใน Module.providers เป็นเรื่องที่ทำได้ เพราะ NestJS ไม่ได้ enforce rules ไว้ แต่มันไม่ได้เหมาะสมเท่าไหร่ เนื่องจากมันทำให้ความสัมพันธ์ระหว่าง module หายไป จนแทบไม่แตกต่างอะไรจากการที่เราเขียนโดยไม่มี module เพราะ module ไปทำ relation ตรงๆกับ service เลย

ท่าที่ถูกต้องคือ

  • ถ้าจะใช้ service จาก module อื่น ต้องใช้ Module.imports import module เข้ามา (ซึ่ง module นั้นจะต้อง export service ออกมาด้วย)
  • สำหรับ Module.providers ใช้สำหรับ internal service เท่านั้น

หน้าตาของ code ที่เหมาะสมก็จะเป็นแบบนี้

// todo/todo.module.ts
@Module({ 
  providers: [TodoService],
  exports: [TodoService],
})
export class TodoModule {}


// user/user.module.ts
@Module({ 
  imports: [TodoModule],
  providers: [UserService],
  controllers: [UserController],
})
export class UserModule {}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)