ห้องสมุดการจัดการการพึ่งพาแรงบันดาลใจจาก "สภาพแวดล้อม" ของ Swiftui
ห้องสมุดนี้ได้รับแรงบันดาลใจและได้รับการออกแบบตลอดระยะเวลาหลายตอนบน Point-Free ซีรีย์วิดีโอสำรวจการเขียนโปรแกรมที่ใช้งานได้และภาษา Swift ซึ่งจัดทำโดย Brandon Williams และ Stephen Celis
การพึ่งพาเป็นประเภทและฟังก์ชั่นในแอปพลิเคชันของคุณที่จำเป็นต้องโต้ตอบกับระบบภายนอกที่คุณไม่ได้ควบคุม ตัวอย่างคลาสสิกของสิ่งนี้คือไคลเอนต์ API ที่ส่งคำขอเครือข่ายไปยังเซิร์ฟเวอร์ แต่ดูเหมือนว่าสิ่งที่ไร้เดียงสาเช่น UUID
และ Date
การเข้าถึงไฟล์ค่าเริ่มต้นของผู้ใช้และแม้กระทั่งนาฬิกาและตัวจับเวลาทั้งหมด
คุณสามารถไปไกลในการพัฒนาแอปพลิเคชันโดยไม่เคยคิดถึงการจัดการการพึ่งพา (หรือบางคนชอบเรียกมันว่า "การฉีดพึ่งพา") แต่ในที่สุดการพึ่งพาที่ไม่สามารถควบคุมได้อาจทำให้เกิดปัญหามากมายในฐานรหัสและวงจรการพัฒนาของคุณ:
การพึ่งพาที่ไม่สามารถควบคุมได้ทำให้ ยากต่อการเขียนการทดสอบที่รวดเร็วและกำหนดได้ เนื่องจากคุณมีความไวต่อความหลากหลายของโลกภายนอกเช่นระบบไฟล์การเชื่อมต่อเครือข่ายความเร็วอินเทอร์เน็ตเวลาทำงานของเซิร์ฟเวอร์และอื่น ๆ
การพึ่งพาจำนวนมาก ไม่ทำงานได้ดีในตัวอย่าง Swiftui เช่นผู้จัดการสถานที่และผู้จดจำเสียงพูดและบางคน ไม่ทำงานแม้ในเครื่องจำลอง เช่นผู้จัดการการเคลื่อนไหวและอื่น ๆ สิ่งนี้จะช่วยป้องกันไม่ให้คุณสามารถทำซ้ำได้อย่างง่ายดายในการออกแบบคุณสมบัติหากคุณใช้ประโยชน์จากเฟรมเวิร์กเหล่านั้น
การพึ่งพาที่โต้ตอบกับบุคคลที่สามห้องสมุดที่ไม่ใช่แอปเปิ้ล (เช่น Firebase, Libraries เว็บซ็อกเก็ต, ไลบรารีเครือข่าย ฯลฯ ) มีแนวโน้มที่จะมีน้ำหนักมากและใช้ เวลานานในการรวบรวม สิ่งนี้สามารถชะลอวงจรการพัฒนาของคุณ
ด้วยเหตุผลเหล่านี้และอีกมากมายขอแนะนำให้คุณควบคุมการพึ่งพาของคุณแทนที่จะปล่อยให้พวกเขาควบคุมคุณ
แต่การควบคุมการพึ่งพาเป็นเพียงจุดเริ่มต้น เมื่อคุณควบคุมการพึ่งพาของคุณแล้วคุณจะต้องเผชิญกับปัญหาใหม่ทั้งหมด:
คุณจะ เผยแพร่การพึ่งพา ตลอดทั้งแอปพลิเคชันทั้งหมดของคุณในแบบที่มีการยศาสตร์มากกว่าการส่งผ่านไปทั่วทุกที่อย่างชัดเจน แต่ปลอดภัยกว่าการพึ่งพาทั่วโลก?
คุณ จะแทนที่การพึ่งพา เพียงส่วนเดียวของแอปพลิเคชันของคุณได้อย่างไร? สิ่งนี้มีประโยชน์สำหรับการพึ่งพาการพึ่งพาการทดสอบและตัวอย่าง Swiftui รวมถึงการไหลของผู้ใช้เฉพาะเช่นประสบการณ์การขึ้นเครื่องบิน
คุณจะแน่ใจได้อย่างไรว่าคุณ ใช้คุณสมบัติ ทั้งหมด ที่ใช้ในการทดสอบได้อย่างไร มันจะไม่ถูกต้องสำหรับการทดสอบเพื่อเยาะเย้ยการอ้างอิงบางอย่าง แต่ปล่อยให้คนอื่น ๆ มีปฏิสัมพันธ์กับโลกภายนอก
ห้องสมุดนี้กล่าวถึงคะแนนทั้งหมดข้างต้นและอีก มากมาย
ห้องสมุดช่วยให้คุณสามารถลงทะเบียนการพึ่งพาของคุณเอง แต่ก็มาพร้อมกับการพึ่งพาที่ควบคุมได้มากมายนอกกรอบ (ดู DependencyValues
สำหรับรายการทั้งหมด) และมีโอกาสที่ดีที่คุณสามารถใช้งานได้ทันที หากคุณใช้ Date()
, UUID()
, Task.sleep
หรือรวมตัวกำหนดเวลาโดยตรงในตรรกะของคุณลักษณะของคุณคุณสามารถเริ่มใช้ไลบรารีนี้ได้แล้ว
@ Observable
final class FeatureModel {
var items : [ Item ] = [ ]
@ ObservationIgnored
@ Dependency ( . continuousClock ) var clock // Controllable way to sleep a task
@ ObservationIgnored
@ Dependency ( . date . now ) var now // Controllable way to ask for current date
@ ObservationIgnored
@ Dependency ( . mainQueue ) var mainQueue // Controllable scheduling on main queue
@ ObservationIgnored
@ Dependency ( . uuid ) var uuid // Controllable UUID creation
// ...
}
เมื่อมีการประกาศการพึ่งพาของคุณแทนที่จะไปถึง Date()
, UUID()
ฯลฯ โดยตรงคุณสามารถใช้การพึ่งพาที่กำหนดไว้ในโมเดลของคุณลักษณะของคุณ:
@ Observable
final class FeatureModel {
// ...
func addButtonTapped ( ) async throws {
try await clock . sleep ( for : . seconds ( 1 ) ) // ? Don't use 'Task.sleep'
items . append (
Item (
id : uuid ( ) , // ? Don't use 'UUID()'
name : " " ,
createdAt : now // ? Don't use 'Date()'
)
)
}
}
นั่นคือทั้งหมดที่ใช้ในการเริ่มใช้การพึ่งพาที่ควบคุมได้ในคุณสมบัติของคุณ ด้วยการทำงานล่วงหน้าเล็กน้อยคุณสามารถเริ่มใช้ประโยชน์จากพลังของห้องสมุด
ตัวอย่างเช่นคุณสามารถควบคุมการพึ่งพาเหล่านี้ในการทดสอบได้อย่างง่ายดาย หากคุณต้องการทดสอบตรรกะภายในวิธี addButtonTapped
คุณสามารถใช้ฟังก์ชัน withDependencies
เพื่อแทนที่การพึ่งพาใด ๆ สำหรับขอบเขตของการทดสอบครั้งเดียว มันง่ายเหมือน 1-2-3:
@ Test
func add ( ) async throws {
let model = withDependencies {
// 1️⃣ Override any dependencies that your feature uses.
$0 . clock = . immediate
$0 . date . now = Date ( timeIntervalSinceReferenceDate : 1234567890 )
$0 . uuid = . incrementing
} operation : {
// 2️⃣ Construct the feature's model
FeatureModel ( )
}
// 3️⃣ The model now executes in a controlled environment of dependencies,
// and so we can make assertions against its behavior.
try await model . addButtonTapped ( )
#expect (
model . items == [
Item (
id : UUID ( uuidString : " 00000000-0000-0000-0000-000000000000 " ) ! ,
name : " " ,
createdAt : Date ( timeIntervalSinceReferenceDate : 1234567890 )
)
]
)
}
ที่นี่เราควบคุมการพึ่งพา date
เพื่อส่งคืนวันที่เดียวกันเสมอและเราควบคุมการพึ่งพา uuid
เพื่อส่งคืน UUID ที่เพิ่มขึ้นอัตโนมัติทุกครั้งที่มีการเรียกใช้และเรายังควบคุมการพึ่งพา clock
โดยใช้การ ImmediateClock
เพื่อสควอชตลอดเวลา ทันที. หากเราไม่ได้ควบคุมการพึ่งพาเหล่านี้การทดสอบนี้จะยากมากที่จะเขียนเนื่องจากไม่มีทางที่จะทำนายได้อย่างถูกต้องว่าจะส่งคืนสิ่งที่จะส่งคืนตาม Date()
และ UUID()
อย่างถูกต้องและเราต้องรอให้โลกแห่งความเป็นจริงผ่านไป ทำให้การทดสอบช้า
แต่การพึ่งพาที่ควบคุมได้ไม่เพียง แต่มีประโยชน์สำหรับการทดสอบเท่านั้น พวกเขายังสามารถใช้ในตัวอย่าง Xcode สมมติว่าคุณลักษณะด้านบนใช้นาฬิกาเพื่อนอนหลับเป็นระยะเวลานานก่อนที่จะมีอะไรเกิดขึ้นในมุมมอง หากคุณไม่ต้องการรอเวลาที่จะผ่านไปเพื่อดูว่าการเปลี่ยนแปลงของมุมมองคุณสามารถแทนที่การพึ่งพานาฬิกาเป็นนาฬิกา "ทันที" โดยใช้ .dependencies
#Preview (
traits : . dependencies {
$0 . continuousClock = . immediate
}
) {
// All access of '@Dependency(.continuousClock)' in this preview will
// use an immediate clock.
FeatureView ( model : FeatureModel ( ) )
}
สิ่งนี้จะทำให้มันดูตัวอย่างใช้นาฬิกาทันทีเมื่อทำงาน แต่เมื่อทำงานในเครื่องจำลองหรือบนอุปกรณ์มันจะยังคงใช้ Live ContinuousClock
สิ่งนี้ทำให้สามารถแทนที่การพึ่งพาเพียงเพื่อดูตัวอย่างโดยไม่ส่งผลกระทบต่อวิธีการผลิตแอปของคุณ
นั่นคือพื้นฐานในการเริ่มต้นใช้งานห้องสมุด แต่ยังมีอีกมากที่คุณสามารถทำได้ คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับห้องสมุดได้โดยการสำรวจเอกสารและบทความ:
เริ่มต้นอย่างรวดเร็ว (เหมือนกับข้อมูลด้านบน) : เรียนรู้พื้นฐานของการเริ่มต้นใช้งานกับห้องสมุดก่อนที่จะดำน้ำลึกเข้าไปในคุณสมบัติทั้งหมด
การพึ่งพาคืออะไร? : เรียนรู้ว่าการพึ่งพาคืออะไรวิธีที่พวกเขาซับซ้อนโค้ดของคุณและทำไมคุณต้องการควบคุมพวกเขา
การใช้การพึ่งพา : เรียนรู้วิธีการใช้การพึ่งพาที่ลงทะเบียนกับห้องสมุด
การลงทะเบียนการพึ่งพา : เรียนรู้วิธีลงทะเบียนการพึ่งพาของคุณเองกับห้องสมุดเพื่อให้สามารถใช้งานได้ทันทีจากส่วนใดส่วนหนึ่งของฐานรหัสของคุณ
การพึ่งพาการแสดงตัวอย่างสดและทดสอบ : เรียนรู้วิธีการใช้งานที่แตกต่างกันของการพึ่งพาการพึ่งพาของคุณเพื่อใช้ในแอปพลิเคชันสดรวมถึงในตัวอย่าง Xcode และแม้แต่ในการทดสอบ
การทดสอบ : หนึ่งในเหตุผลหลักในการควบคุมการพึ่งพาคือเพื่อให้การทดสอบง่ายขึ้น เรียนรู้เคล็ดลับและกลเม็ดสำหรับการเขียนการทดสอบที่ดีขึ้นกับห้องสมุด
การออกแบบการพึ่งพา : เรียนรู้เทคนิคในการออกแบบการพึ่งพาของคุณเพื่อให้มีความยืดหยุ่นมากที่สุดสำหรับการฉีดเข้าไปในคุณสมบัติและการเอาชนะสำหรับการทดสอบ
การพึ่งพาการแทนที่ : เรียนรู้วิธีการพึ่งพาสามารถเปลี่ยนแปลงได้ในเวลารันไทม์เพื่อให้บางส่วนของแอปพลิเคชันของคุณสามารถใช้การพึ่งพาที่แตกต่างกัน
อายุการใช้งานการพึ่งพา : เรียนรู้เกี่ยวกับอายุการใช้งานของการพึ่งพาวิธีการยืดอายุการใช้งานของการพึ่งพาและวิธีการสืบทอดการพึ่งพา
ระบบจุดเริ่มต้นเดียว : เรียนรู้เกี่ยวกับระบบ "จุดเริ่มต้นเดียว" และทำไมพวกเขาถึงเหมาะที่สุดสำหรับไลบรารีการพึ่งพานี้แม้ว่าจะเป็นไปได้ที่จะใช้ไลบรารีกับระบบจุดเข้าที่ไม่ใช่รูปแบบ
เราสร้างแอปพลิเคชั่นสาธิต Scrumdinger ของ Apple ใหม่โดยใช้แนวทางปฏิบัติที่ทันสมัยและดีที่สุดสำหรับการพัฒนา Swiftui รวมถึงการใช้ไลบรารีนี้เพื่อควบคุมการพึ่งพาการเข้าถึงระบบไฟล์ตัวจับเวลาและ API การรู้จำเสียง การสาธิตนั้นสามารถพบได้ที่นี่
เอกสารล่าสุดสำหรับ APIs การพึ่งพามีให้ที่นี่
คุณสามารถเพิ่มการพึ่งพาโครงการ XCode โดยเพิ่มลงในโครงการของคุณเป็นแพ็คเกจ
https://github.com/pointfreeco/swift-dependencies
หากคุณต้องการใช้การพึ่งพาในโครงการ SwiftPM มันง่ายเหมือนการเพิ่มลงใน Package.swift
ของคุณ Swift:
dependencies: [
. package ( url : " https://github.com/pointfreeco/swift-dependencies " , from : " 1.0.0 " )
]
จากนั้นเพิ่มผลิตภัณฑ์ไปยังเป้าหมายใด ๆ ที่ต้องการเข้าถึงไลบรารี:
. product ( name : " Dependencies " , package : " swift-dependencies " ) ,
หากคุณต้องการหารือเกี่ยวกับห้องสมุดนี้หรือมีคำถามเกี่ยวกับวิธีการใช้เพื่อแก้ปัญหาเฉพาะมีหลายสถานที่ที่คุณสามารถพูดคุยกับผู้ที่ชื่นชอบจุดที่ไม่มีจุด:
ห้องสมุดนี้ควบคุมจำนวนการพึ่งพาออกจากกล่อง แต่ยังเปิดให้ขยาย โครงการต่อไปนี้สร้างขึ้นด้านบนของการพึ่งพา:
มีห้องสมุดฉีดพึ่งพาอาศัยกันอื่น ๆ อีกมากมายในชุมชน Swift แต่ละชุดมีลำดับความสำคัญและการแลกเปลี่ยนที่แตกต่างจากการพึ่งพา นี่คือตัวอย่างที่รู้จักกันดี:
ห้องสมุดนี้เปิดตัวภายใต้ใบอนุญาต MIT ดูใบอนุญาตสำหรับรายละเอียด