Loyiha tuzilishi: Module, Controller, Service
NestJS'da har qanday ilova uch xil qurilish blokidan yig'iladi: Module (modul), Controller (kontroller) va Service (servis). Bu uchlik NestJS falsafasining yuragi. Ularni bir marta yaxshi tushunib olsangiz, butun framework tushunarli bo'lib qoladi. Keling, har birini alohida ko'rib chiqamiz.
Mas'uliyatlarni ajratish tamoyili
NestJS arxitekturasi Separation of Concerns (mas'uliyatlarni ajratish) tamoyiliga tayanadi. Buning ma'nosi: har bir qism faqat bitta ishga javob berishi kerak. Uchlikda vazifalar shunday taqsimlanadi:
- Controller โ HTTP so'rovlarini qabul qiladi va javob qaytaradi. U "qaysi manzilga qaysi funksiya"ni belgilaydi, ammo biznes-logikani o'zi bajarmaydi;
- Service โ asosiy biznes-logika shu yerda. Ma'lumotni hisoblash, bazaga saqlash, tashqi API'ga so'rov โ bularning hammasi service'da;
- Module โ controller va service'larni bir joyga bog'laydi va ularni tashkil qiladi.
@Module โ modul nima?
Modul โ bu bir-biriga bog'liq kodni birlashtiruvchi konteyner. Masalan, foydalanuvchilar bilan bog'liq barcha kod (controller, service) UsersModule ichida, mahsulotlar esa ProductsModule ichida bo'ladi. Har bir NestJS ilovada kamida bitta modul bo'ladi โ bu ildiz modul (AppModule).
Modul @Module dekoratori bilan belgilangan oddiy klass. Dekorator argument sifatida to'rt xossali obyekt qabul qiladi:
// src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [], // Boshqa modullarni import qilish
controllers: [AppController], // Bu moduldagi controller'lar
providers: [AppService], // Bu moduldagi service'lar (provayderlar)
exports: [], // Boshqa modullar uchun ochiq provayderlar
})
export class AppModule {}
To'rt xossaning ma'nosi:
controllersโ shu modulga tegishli controller'lar ro'yxati;providersโ shu modulda ishlaydigan service'lar va boshqa injektsiya qilinadigan obyektlar;importsโ boshqa modullarni ulash (masalan,UsersModuleichidaDatabaseModule);exportsโ ushbu modul provayderlarining qaysi biri boshqa modullarga ko'rinishi kerakligi.
@Controller โ so'rovlarni qabul qilish
Controller HTTP so'rovlarini qabul qiladi va tegishli javobni qaytaradi. U @Controller dekoratori bilan belgilanadi. Dekoratorga berilgan satr โ bu marshrut prefiksi (route prefix), ya'ni ushbu controller'dagi barcha manzillarning boshi:
// src/users/users.controller.ts
import { Controller, Get } from '@nestjs/common';
@Controller('users') // Barcha manzillar /users bilan boshlanadi
export class UsersController {
@Get() // GET /users
findAll() {
return 'Barcha foydalanuvchilar';
}
@Get('active') // GET /users/active
findActive() {
return 'Faol foydalanuvchilar';
}
}
Bu yerda @Get() โ HTTP metod dekoratori. U funksiyani ma'lum bir GET manziliga bog'laydi. Express'da biz app.get('/users', handler) yozardik; NestJS'da esa route va uni bajaradigan funksiya dekorator orqali bir-biriga ulanadi. Bu kodni ancha o'qishli qiladi.
res.json() chaqirish shart emas.@Injectable โ service (biznes-logika)
Service โ bu haqiqiy ish bajariladigan joy. U @Injectable dekoratori bilan belgilangan klass. Bu dekorator NestJS'ga "bu klassni boshqa joylarga injektsiya qilish mumkin" deb aytadi (buni keyingi darsda Dependency Injection mavzusida chuqurroq ko'ramiz):
// src/users/users.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {
private users = [
{ id: 1, ism: 'Ali' },
{ id: 2, ism: 'Vali' },
];
findAll() {
return this.users;
}
findOne(id: number) {
return this.users.find(u => u.id === id);
}
}
Endi controller service'ni ishlatishi kerak. Buning uchun service controller'ning konstruktoriga qo'shiladi โ bu Dependency Injection deb ataladi. NestJS UsersService nusxasini avtomatik yaratadi va controller'ga uzatadi:
// src/users/users.controller.ts
import { Controller, Get, Param } from '@nestjs/common';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
// Service konstruktor orqali injektsiya qilinadi:
constructor(private readonly usersService: UsersService) {}
@Get()
findAll() {
return this.usersService.findAll(); // Ishni service'ga topshiramiz
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.usersService.findOne(Number(id));
}
}
E'tibor bering: controller hech qanday biznes-logikani o'zi bajarmaydi. U faqat so'rovni qabul qiladi va usersService'ga uzatadi. Bu ideal ajratish: controller HTTP bilan, service esa ma'lumot bilan shug'ullanadi.
Hamma narsani modulga bog'lash
Controller va service yaratganingizdan keyin ularni modulda ro'yxatdan o'tkazishingiz kerak. Aks holda NestJS ularni topolmaydi:
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
@Module({
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}
So'ng ushbu yangi modulni ildiz modulga import qilamiz, aks holda u ilovaning bir qismi bo'lmaydi:
// src/app.module.ts
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module';
@Module({
imports: [UsersModule], // UsersModule'ni ilovaga ulaymiz
})
export class AppModule {}
providers ro'yxatiga qo'shishni unutish. Bunda NestJS ishga tushganda "Nest can't resolve dependencies" xatosini beradi. Har doim tekshiring: service providers'da, controller controllers'da bo'lishi shart.Nest CLI bilan avtomatik generatsiya
Bu qismlarning hammasini qo'lda yozish zerikarli. Nest CLI'ning generate (qisqasi g) buyrug'i barcha fayllarni yaratib, ularni modulga avtomatik bog'lab beradi:
# To'liq resurs yaratish (modul + controller + service + testlar):
nest generate resource users
# Yoki alohida:
nest generate module users # nest g module users
nest generate controller users # nest g controller users
nest generate service users # nest g service users
nest g resource users buyrug'i ayniqsa qulay โ u CRUD (yaratish, o'qish, yangilash, o'chirish) uchun tayyor shablon bilan to'liq modul yaratadi. CLI hatto REST API yoki GraphQL kabi turni ham so'raydi. Bu bir necha daqiqalik qo'l ishini bir buyruqqa qisqartiradi.
controllers va providers ro'yxatiga qo'shiladi. Ya'ni yuqoridagi "modulga bog'lash" bosqichini CLI siz uchun bajaradi.Xulosa
- Controller โ HTTP so'rovlarini qabul qiladi va javob qaytaradi, biznes-logikasiz ingichka bo'lishi kerak;
- Service (
@Injectable) โ biznes-logika, hisob-kitob, ma'lumotlar bilan ishlash shu yerda; - Module (
@Module) โ controller va service'larni birlashtiradi,imports/controllers/providers/exportsxossalari bilan; - Service controller'ga konstruktor orqali injektsiya qilinadi;
- Har bir yangi modulni
AppModuleningimports'iga qo'shish shart; nest g resourcevanest gbuyruqlari fayllarni avtomatik yaratib, modulga bog'laydi.