NestJS — Node.js للمؤسسات

الوحدات بعمق

15 دقيقة الدرس 6 من 48

الوحدات بعمق

الوحدات هي وسيلة NestJS لتنظيم التطبيق إلى ميزات متماسكة ومكتفية ذاتيًا. قد يحوي تطبيق صغير وحدة واحدة، لكنّ التطبيقات الحقيقية شجرة من وحدات الميزات — كلٌّ تملك متحكّماتها وخدماتها وتبعياتها. إتقان الوحدات هو ما يُبقي الكود الكبير سهل التصفّح.

وحدات الميزات

تجمع وحدة الميزة كل ما يتعلّق بمجال واحد. بدل حشر المستخدمين والطلبات والمدفوعات في وحدة الجذر، تحصل كلٌّ على وحدتها:

// 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 {}

ثم تربطها بوحدة الجذر عبر imports:

// app.module.ts @Module({ imports: [UsersModule, OrdersModule, PaymentsModule], }) export class AppModule {}

التغليف: القاعدة الأساسية

المزوّدات خاصّة بوحدتها افتراضيًا. إن أعلنت UsersModule عن UsersService في providers دون تصديرها، فلن تستطيع أي وحدة أخرى حقنها — حتى لو استوردت UsersModule.

هذا التغليف مقصود. يُبقي الخدمات الداخلية مخفيّة ويُجبرك على التعمّد في ما تكشفه الوحدة — الانضباط نفسه كـ public مقابل private في الصنف.

الوحدات المشتركة: تصدير المزوّدات

كي تسمح لوحدات أخرى باستخدام مزوّد، أضِفه إلى مصفوفة exports للوحدة:

// users/users.module.ts @Module({ controllers: [UsersController], providers: [UsersService], exports: [UsersService], // صار قابلًا للاستيراد من وحدات أخرى }) export class UsersModule {} // orders/orders.module.ts @Module({ imports: [UsersModule], // يكتسب الوصول إلى UsersService providers: [OrdersService], }) export class OrdersModule {}

الآن تستطيع OrdersService حقن UsersService لأنّ OrdersModule تستورد الوحدة التي تُصدّرها.

إعادة تصدير الوحدات

تستطيع الوحدة استيراد وحدة أخرى وإعادة تصديرها، فتُحزِّم قدرات مرتبطة:

@Module({ imports: [DatabaseModule], exports: [DatabaseModule], // أي وحدة تستورد هذه تحصل على DatabaseModule أيضًا }) export class CoreModule {}

الوحدات العامة

بعض المزوّدات مطلوبة في كل مكان تقريبًا — خدمة إعدادات، أو مُسجّل، أو اتصال قاعدة بيانات. وسمُ وحدة بـ @Global() يُسجّل صادراتها على مستوى التطبيق كلّه، فتستوردها مرّة واحدة (في وحدة الجذر) وتحقن مزوّداتها في أي مكان دون تكرار imports:

import { Module, Global } from '@nestjs/common'; @Global() @Module({ providers: [ConfigService], exports: [ConfigService], }) export class ConfigModule {}
استخدم @Global() باعتدال. جعل كل شيء عامًّا يُفسد الغرض من الوحدات — فهو يُخفي التبعيات ويُصعّب فهم البنية. احفظها للاهتمامات العابرة فعلًا كالإعدادات والتسجيل.
قاعدة عامّة: يجب أن تُصدّر الوحدة فقط ما تحتاجه الوحدات الأخرى فعلًا. إن كانت خدمة تفصيلًا تنفيذيًا داخليًا، أبقِها غير مُصدَّرة.

الخلاصة

تُنظّم الوحدات التطبيق إلى وحدات ميزات مُغلَّفة. المزوّدات خاصّة ما لم تُصدَّر؛ وتكتسب الوحدات الأخرى الوصول باستيراد الوحدة التي تُصدّرها. يُسجّل @Global() صادرات الوحدة في كل مكان — قويّ لكن يُستخدم باعتدال. تاليًا نغوص تحت الغطاء لنرى كيف يحلّ NestJS هذه التبعيات فعليًا.