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

เหตุผลที่ใช้การฉีดการพึ่งพา

แยกการสร้างออกจากการใช้งานเพื่อให้ทดสอบได้

เหตุผลที่ใช้การฉีดการพึ่งพา เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุผลที่ต้องใช้การฉีดสิ่งพึ่งพา

การฉีดสิ่งพึ่งพา (DI) หมายถึงการส่งสิ่งที่อ็อบเจ็กต์ต้องใช้จากภายนอก แทนที่จะให้อ็อบเจ็กต์สร้างสิ่งเหล่านั้นเอง วิธีนี้ลดการเชื่อมโยงระหว่างองค์ประกอบและทำให้ทดสอบได้ง่ายขึ้น

ปัญหา: การเชื่อมโยงแน่นหนา

เมื่อชนิดหนึ่งสร้างสิ่งที่ทำงานร่วมกันขึ้นมาเอง ชนิดนั้นจะผูกติดกับคลาสรูปธรรมเหล่านั้น และไม่สามารถปรับเปลี่ยนหรือนำไปทดสอบแยกจากส่วนอื่นได้

class Logger {
    func log(_ m: String) { print("LOG: \(m)") }
}
class Service {
    let logger = Logger() // hard-coded dependency
    func run() { logger.log("running") }
}
Service().run()

การเชื่อมโยงทำให้ทดสอบยาก

เนื่องจาก Service สร้าง Logger จริงขึ้นมาเสมอ การทดสอบจึงไม่สามารถบันทึกหรือจำลองผลลัพธ์การบันทึกได้ สิ่งพึ่งพานี้มองไม่เห็นจากภายนอก

class Logger { func log(_ m: String) { print(m) } }
class Service {
    let logger = Logger()
    func run() { logger.log("hello") }
}
// No way to swap Logger here.
Service().run()

แนวคิด: ฉีดสิ่งที่ต้องใช้

ให้ส่งสิ่งพึ่งพาเข้ามาแทน ผู้เรียกเป็นผู้ตัดสินใจว่าจะส่งการนำไปใช้แบบใด ทำให้ Service ไม่ต้องสนใจรายละเอียดอีกต่อไป

class Logger { func log(_ m: String) { print("LOG: \(m)") } }
class Service {
    let logger: Logger
    init(logger: Logger) { self.logger = logger }
    func run() { logger.log("running") }
}
Service(logger: Logger()).run()

ประโยชน์ของการลดการเชื่อมโยง

เมื่อใช้การฉีด Service เดิมสามารถทำงานร่วมกับตัวบันทึกหลายแบบ ทั้งในระบบจริงและการทดสอบ โดยไม่ต้องเปลี่ยนโค้ด

class Logger { var lines: [String] = []
    func log(_ m: String) { lines.append(m) } }
class Service {
    let logger: Logger
    init(logger: Logger) { self.logger = logger }
    func run() { logger.log("event") }
}
let l = Logger()
Service(logger: l).run()
print(l.lines)

ความรับผิดชอบเดียว

DI สนับสนุนหลักการรับผิดชอบเดียว ชนิดหนึ่งจึงมุ่งเน้นงานของตนเอง และมอบหมายข้อกังวลอื่นให้สิ่งที่ทำงานร่วมกันซึ่งถูกฉีดเข้ามา

struct Mailer { func send(_ to: String) { print("Mail to \(to)") } }
struct SignupFlow {
    let mailer: Mailer
    func register(_ email: String) { mailer.send(email) }
}
SignupFlow(mailer: Mailer()).register("a@b.com")

ความยืดหยุ่น

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

struct Engine { let power: Int }
struct Car {
    let engine: Engine
    func describe() { print("Power: \(engine.power)") }
}
Car(engine: Engine(power: 200)).describe()
Car(engine: Engine(power: 90)).describe()

สิ่งพึ่งพาที่ระบุอย่างชัดเจน

ตัวเริ่มต้นที่แสดงรายการสิ่งพึ่งพาจะบอกอย่างชัดเจนว่าชนิดนั้นต้องใช้อะไรบ้าง ส่วนสิ่งพึ่งพาที่ซ่อนอยู่และสร้างขึ้นเองจะปิดบังข้อตกลงดังกล่าว

struct Repo { func load() -> [Int] { [1, 2, 3] } }
struct Report {
    let repo: Repo // visible dependency
    func total() -> Int { repo.load().reduce(0, +) }
}
print(Report(repo: Repo()).total())

การประกอบแทนการสร้าง

DI สนับสนุนการประกอบอ็อบเจ็กต์จากภายนอก จุดประกอบขนาดเล็กจะรวบรวมกราฟของอ็อบเจ็กต์ ส่วนโค้ดที่เหลือเพียงรับสิ่งที่ต้องใช้

struct DB { func count() -> Int { 42 } }
struct Stats { let db: DB; func show() { print(db.count()) } }
// Composition root:
let app = Stats(db: DB())
app.show()

ไม่ใช่เฉพาะสำหรับ App ขนาดใหญ่

แม้แต่โปรแกรมขนาดเล็กก็ได้ประโยชน์ การฉีดสิ่งพึ่งพาทำให้เปลี่ยนพฤติกรรมได้ง่ายและสื่อเจตนาได้ชัดเจน โดยไม่ต้องใช้เฟรมเวิร์กเพิ่มเติม

struct Clock { func now() -> Int { 12 } }
struct Greeter {
    let clock: Clock
    func greet() { print(clock.now() < 12 ? "Morning" : "Afternoon") }
}
Greeter(clock: Clock()).greet()

ไม่จำเป็นต้องใช้เฟรมเวิร์ก

DI ใน Swift ไม่ต้องใช้ไลบรารี ตัวเริ่มต้นแบบ Plain และโปรโตคอลก็เพียงพอแล้ว บทเรียนถัดไปจะแสดงการฉีดผ่านตัวสร้าง โปรโตคอล และการจำลอง

struct Adder { func add(_ a: Int, _ b: Int) -> Int { a + b } }
struct Calc {
    let adder: Adder
    func run() { print(adder.add(2, 3)) }
}
Calc(adder: Adder()).run()

ตรวจสอบความเข้าใจ

แนวคิดหลักของการฉีดสิ่งพึ่งพาคืออะไร

สรุปทบทวน

การฉีดสิ่งพึ่งพา ส่งสิ่งที่ทำงานร่วมกันมาจากภายนอก แทนที่จะสร้างขึ้นภายใน จึงช่วยลดการเชื่อมโยง ทำให้สิ่งพึ่งพาชัดเจน และรองรับการทดสอบ Swift ไม่จำเป็นต้องใช้เฟรมเวิร์กสำหรับแนวทางนี้ บทถัดไปจะแสดงรูปแบบที่ใช้บ่อยที่สุด นั่นคือการฉีดผ่านตัวสร้าง

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

บทเรียน “เหตุผลที่ใช้การฉีดการพึ่งพา” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “เหตุผลที่ใช้การฉีดการพึ่งพา”

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

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

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

บทเรียน “เหตุผลที่ใช้การฉีดการพึ่งพา” ใช้เวลานานแค่ไหน

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

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

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

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

  1. เหตุผลที่ใช้การฉีดการพึ่งพา
  2. การฉีดผ่านตัวสร้าง
  3. นามธรรมที่อิงตามโพรโทคอล
  4. การจำลองการพึ่งพาในการทดสอบ
← กลับไปที่ Swift Academy