0Pricing
Swift Academy · درس

وصل الطبقات معًا دون إطار DI

ركّبوا الكائنات عند نقطة دخول التطبيق باستخدام نمط Composition Root.

وصل الطبقات معًا دون إطار DI درس مجاني في Swift Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Swift Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Swift Academy 4 دروس في المجموع.

جذر التركيب

جذر التركيب هو المكان الوحيد الذي تُنشأ فيه جميع الكائنات وتُربط معًا. وفي تطبيق SwiftUI، يكون عادةً @main.

@main
struct MyApp: App {
  // All wiring happens here
  private let container = AppContainer()
  var body: some Scene {
    WindowGroup { container.makeRootView() }
  }
}

نمط AppContainer

تنشئ بنية أو فئة AppContainer الرسم البياني للكائنات، وتخفي تعقيد الربط عن بنية App.

final class AppContainer {
  let db = SQLiteDatabase()
  lazy var userRepo: UserRepository = RemoteUserRepository(db: db)
  lazy var fetchUser = FetchUserUseCase(repo: userRepo)
  lazy var profileVM = ProfileViewModel(useCase: fetchUser)
  func makeRootView() -> some View { ProfileView(viewModel: profileVM) }
}

الخصائص lazy لضبط الترتيب

استخدم خصائص lazy لضمان إنشاء التبعيات بالترتيب الصحيح من دون ترتيب يدوي.

final class Container {
  lazy var network: NetworkClient = URLSessionClient()
  lazy var api: APIService = APIService(client: network)  // created after network
  lazy var repo: ItemRepository = RemoteItemRepository(api: api)
}

أساليب المصنع

أضف أساليب مصنع إلى الحاوية لإنشاء كائنات على مستوى العرض مع تبعيات خاصة بكل شاشة.

extension AppContainer {
  func makeOrderFlow() -> OrderFlowView {
    let repo = RemoteOrderRepository(api: api)
    let useCase = PlaceOrderUseCase(repo: repo)
    let vm = OrderViewModel(useCase: useCase)
    return OrderFlowView(viewModel: vm)
  }
}

قيم البيئة للحقن

في SwiftUI، استخدم EnvironmentKey مخصصة لحقن التبعيات بعمق في شجرة العروض من دون تمريرها عبر كل طبقة.

private struct FetchUserKey: EnvironmentKey {
  static let defaultValue: FetchingUser = FetchUserUseCase(repo: NullUserRepo())
}
extension EnvironmentValues {
  var fetchUser: FetchingUser {
    get { self[FetchUserKey.self] } set { self[FetchUserKey.self] = newValue }
  }
}

استخدام مفتاح البيئة

احقن التبعية عبر .environment(\.fetchUser, container.fetchUser) واقرأها باستخدام @Environment(\.fetchUser) في العروض.

ContentView()
  .environment(\.fetchUser, container.fetchUser)

// In a deep view:
@Environment(\.fetchUser) private var fetchUser

الحاويات ذات النطاق

أنشئ حاويات فرعية لنطاقات الميزات، بحيث ترث التبعيات المشتركة وتمتلك التبعيات الخاصة بالميزة.

final class CheckoutContainer {
  let cart: CartRepository
  let payment: PaymentService
  lazy var placeOrder = PlaceOrderUseCase(cart: cart, payment: payment)
  init(parent: AppContainer) {
    cart = parent.cartRepo
    payment = parent.paymentService
  }
}

اختبار جذر التركيب

اختبر أساليب المصنع في الحاوية بالتحقق من أن الكائنات المُرجعة تملك النوع والإعداد الصحيحين.

func testContainerBuildsProfileView() {
  let container = AppContainer(db: InMemoryDatabase())
  let view = container.makeRootView()
  XCTAssertTrue(type(of: view) == ProfileView.self)
}

تجنب التبعيات الدائرية

إذا كان A يعتمد على B وكان B يعتمد على A، فأدخل وسيطًا أو أعد هيكلة المسؤوليات لكسر الدورة.

// Circular:
// UserService → NotificationService → UserService
// Fix: UserService → NotificationInput (protocol) ← NotificationService

متى نلجأ إلى إطار عمل للحقن؟

يتوسع الربط اليدوي جيدًا في التطبيقات متوسطة الحجم. ضع في اعتبارك أطر العمل مثل Needle وSwinject فقط عندما تصبح الحاوية كبيرة جدًا بحيث يصعب الحفاظ عليها.

// Manual: fine for <20 top-level dependencies
// Framework: helps with large teams, 50+ services, code-generation for factories

مثال على المراجعة

مثال كامل على الربط في تطبيق صغير: تنشئ الحاوية جميع التبعيات، وينشئ المصنع العرض الجذري.

final class AppContainer {
  private let db = CoreDataStack.shared
  lazy var userRepo: UserRepository = LocalUserRepository(db: db)
  lazy var fetchUser = FetchUserUseCase(repo: userRepo)
  func makeContentView() -> ContentView {
    ContentView(viewModel: ProfileViewModel(useCase: fetchUser))
  }
}

تحقق سريع

ما جذر التركيب في تطبيق Swift؟

مراجعة الدرس

اربط تطبيقك في جذر التركيب (عادةً @main). استخدم AppContainer مع خصائص lazy لضمان ترتيب الإنشاء الصحيح. أضف أساليب مصنع لإنشاء الرسوم البيانية الخاصة بكل شاشة. واحقن التبعيات العميقة باستخدام EnvironmentKey مخصصة. واكسر التبعيات الدائرية باستخدام بروتوكولات وسيطة.

الأسئلة الشائعة

هل درس «وصل الطبقات معًا دون إطار DI» مجاني؟

نعم — نص درس «وصل الطبقات معًا دون إطار DI» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Swift Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Swift Academy 4 دروس في المجموع.

ماذا ستتعلم في «وصل الطبقات معًا دون إطار DI»؟

ركّبوا الكائنات عند نقطة دخول التطبيق باستخدام نمط Composition Root. تتمرن على Swift Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Swift Academy؟

لا تُشترط خبرة سابقة. Swift Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «وصل الطبقات معًا دون إطار DI»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Swift Academy هذا؟

نعم. كل درس في Swift Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الطبقات: النطاق والبيانات والعرض
  2. أنماط حالات الاستخدام والمستودع
  3. عكس التبعيات باستخدام تجريدات البروتوكولات
  4. وصل الطبقات معًا دون إطار DI
← العودة إلى Swift Academy