0Pricing
Swift Academy · บทเรียน

เชื่อมชั้นต่าง ๆ เข้าด้วยกันโดยไม่ใช้เฟรมเวิร์ก DI

ประกอบอ็อบเจ็กต์ที่จุดเริ่มต้นของแอปด้วยรูปแบบรากการประกอบ

เชื่อมชั้นต่าง ๆ เข้าด้วยกันโดยไม่ใช้เฟรมเวิร์ก DI เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 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 จะสร้างกราฟอ็อบเจ็กต์และซ่อนความซับซ้อนของการเชื่อมโยงจากโครงสร้างแอป

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 เพื่อให้แน่ใจว่าการพึ่งพาจะถูกสร้างตามลำดับที่ถูกต้องโดยไม่ต้องจัดลำดับด้วยตนเอง

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

เมื่อใดควรเลือกใช้กรอบงาน DI

การเชื่อมโยงด้วยตนเองรองรับแอปขนาดกลางได้เป็นอย่างดี ควรพิจารณากรอบงาน เช่น นีดเดิลและสวินเจกต์ เฉพาะเมื่อคอนเทนเนอร์มีขนาดใหญ่เกินกว่าจะดูแลรักษาได้

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

ตรวจสอบความเข้าใจอย่างรวดเร็ว

จุดประกอบระบบในแอปสวิฟต์คืออะไร

สรุปบทเรียน

เชื่อมโยงแอปของคุณที่จุดประกอบระบบ ซึ่งโดยปกติคือ @main ใช้ AppContainer ที่มีคุณสมบัติ lazy เพื่อสร้างสิ่งต่าง ๆ ตามลำดับที่ถูกต้อง เพิ่มเมธอดโรงงานสำหรับกราฟการพึ่งพาของแต่ละหน้าจอ ฉีดการพึ่งพาที่อยู่ลึกลงไปด้วย EnvironmentKey แบบกำหนดเอง และทำลายการพึ่งพาแบบวนรอบด้วยโปรโตคอลตัวกลาง

คำถามที่พบบ่อย

บทเรียน “เชื่อมชั้นต่าง ๆ เข้าด้วยกันโดยไม่ใช้เฟรมเวิร์ก DI” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “เชื่อมชั้นต่าง ๆ เข้าด้วยกันโดยไม่ใช้เฟรมเวิร์ก DI” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “เชื่อมชั้นต่าง ๆ เข้าด้วยกันโดยไม่ใช้เฟรมเวิร์ก DI”

ประกอบอ็อบเจ็กต์ที่จุดเริ่มต้นของแอปด้วยรูปแบบรากการประกอบ คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “เชื่อมชั้นต่าง ๆ เข้าด้วยกันโดยไม่ใช้เฟรมเวิร์ก DI” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม

ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ชั้นต่าง ๆ: โดเมน ข้อมูล และการนำเสนอ
  2. รูปแบบกรณีใช้งานและคลังข้อมูล
  3. การกลับทิศทางการพึ่งพาด้วยนามธรรมของโพรโทคอล
  4. เชื่อมชั้นต่าง ๆ เข้าด้วยกันโดยไม่ใช้เฟรมเวิร์ก DI
← กลับไปที่ Swift Academy