Swift Academy · บทเรียน

รูปแบบกรณีใช้งานและคลังข้อมูล

กำหนดกรณีใช้งานเป็นโพรโทคอล Swift และใช้งานอินเทอร์เฟซของคลังข้อมูล

บทเรียน 2 จาก 413 ขั้นตอน

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

กรณีการใช้งานคืออะไร

กรณีการใช้งาน (ตัวประสานงาน) จะห่อหุ้มการดำเนินการทางธุรกิจเพียงอย่างเดียว และประสานงานเอนทิตีของโดเมนกับรีโพซิทอรี

struct PlaceOrderUseCase {
  let cart: CartRepository
  let payment: PaymentService
  let orders: OrderRepository
  func execute(userId: Int) async throws -> Order {
    let items = try await cart.items(for: userId)
    let receipt = try await payment.charge(items: items)
    return try await orders.create(receipt: receipt)
  }
}

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

กรณีการใช้งานแต่ละรายการทำหน้าที่เพียงอย่างเดียว หากมีหลายความรับผิดชอบ ควรแยกเป็นหลายกรณีการใช้งาน

// One use case per business action:
struct FetchUserUseCase { ... }
struct UpdateUserUseCase { ... }
struct DeleteUserUseCase { ... }

กรณีการใช้งานในรูปแบบโปรโตคอล

กำหนดโปรโตคอลสำหรับกรณีการใช้งาน เพื่อให้สามารถสร้างสิ่งจำลองในการทดสอบชั้นการนำเสนอได้

protocol PlacingOrder {
  func execute(userId: Int) async throws -> Order
}
struct PlaceOrderUseCase: PlacingOrder { ... }

รีโพซิทอรีคืออะไร

รีโพซิทอรีทำหน้าที่เป็นนามธรรมให้แหล่งข้อมูล ผู้เรียกใช้งานจะติดต่อผ่านโปรโตคอลของสวิฟต์ ส่วนการนำไปใช้งานอาจใช้เครือข่าย Core Data หรือหน่วยความจำ

protocol OrderRepository {
  func create(receipt: PaymentReceipt) async throws -> Order
  func list(userId: Int) async throws -> [Order]
  func cancel(orderId: Int) async throws
}

การนำรีโพซิทอรีไปใช้งาน

รีโพซิทอรีที่เป็นรูปธรรมจะแปลงการเรียกจากโดเมนให้เป็นการดำเนินการกับเครือข่ายหรือฐานข้อมูล

struct RemoteOrderRepository: OrderRepository {
  func create(receipt: PaymentReceipt) async throws -> Order {
    let dto = receipt.toDTO()
    let data = try await api.post("/orders", body: dto)
    return try JSONDecoder().decode(OrderDTO.self, from: data).toDomain()
  }
  func list(userId: Int) async throws -> [Order] { ... }
  func cancel(orderId: Int) async throws { ... }
}

รีโพซิทอรีในหน่วยความจำสำหรับการทดสอบ

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

final class InMemoryOrderRepo: OrderRepository {
  var orders: [Order] = []
  func create(receipt: PaymentReceipt) async throws -> Order {
    let order = Order(id: orders.count + 1, items: receipt.items)
    orders.append(order)
    return order
  }
  func list(userId: Int) async throws -> [Order] { orders }
  func cancel(orderId: Int) async throws { orders.removeAll { $0.id == orderId } }
}

การประกอบกรณีการใช้งาน

กรณีการใช้งานสามารถเรียกกรณีการใช้งานอื่นเพื่อดำเนินการย่อยที่ใช้ร่วมกัน ทำให้แต่ละรายการยังคงมุ่งเน้นหน้าที่ของตน

struct CheckoutUseCase {
  let validateCart: ValidateCartUseCase
  let placeOrder: PlaceOrderUseCase
  let notifyUser: NotifyUserUseCase
  func execute(userId: Int) async throws -> Order {
    try await validateCart.execute(userId: userId)
    let order = try await placeOrder.execute(userId: userId)
    try await notifyUser.execute(order: order)
    return order
  }
}

รีโพซิทอรีกับบริการ

รีโพซิทอรี: ดำเนินการสร้าง อ่าน แก้ไข และลบกับชนิดเอนทิตีเดียว บริการ: ประสานงานเอนทิตีหลายรายการหรือเรียกส่วนติดต่อโปรแกรมประยุกต์ภายนอกโดยไม่จัดเก็บข้อมูลโดยตรง

// Repository: single entity
protocol UserRepository { func getUser(id: Int) async throws -> User }
// Service: cross-entity operation
protocol AuthService { func login(email: String, password: String) async throws -> Session }

การแคชในรีโพซิทอรี

รีโพซิทอรีสามารถแคชผลลัพธ์ไว้เบื้องหลังได้โดยที่กรณีการใช้งานไม่จำเป็นต้องทราบรายละเอียดการนำไปใช้งาน

struct CachedUserRepository: UserRepository {
  private var cache: [Int: User] = [:]
  private let remote: UserRepository
  func getUser(id: Int) async throws -> User {
    if let cached = cache[id] { return cached }
    let user = try await remote.getUser(id: id)
    cache[id] = user
    return user
  }
  func saveUser(_ user: User) async throws { try await remote.saveUser(user) }
}

ความสามารถในการทดสอบ

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

let repo = InMemoryOrderRepo()
let sut = PlaceOrderUseCase(orders: repo, ...)
let order = try await sut.execute(userId: 1)
XCTAssertEqual(repo.orders.count, 1)

การแปลงข้อผิดพลาด

รีโพซิทอรีควรแปลงข้อผิดพลาดจากชั้นข้อมูล เช่น เครือข่ายและฐานข้อมูล ให้เป็นข้อผิดพลาดของโดเมนก่อนส่งกลับ

func getUser(id: Int) async throws -> User {
  do {
    let data = try await api.get("/users/\(id)")
    return try decode(data)
  } catch let e as URLError where e.code == .notConnectedToInternet {
    throw DomainError.offline
  }
}

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

ความแตกต่างสำคัญระหว่างรีโพซิทอรีกับบริการในสถาปัตยกรรมแบบสะอาดคืออะไร

สรุปบทเรียน

กรณีการใช้งานจะห่อหุ้มการดำเนินการทางธุรกิจเพียงอย่างเดียวและพึ่งพาโปรโตคอลของรีโพซิทอรี รีโพซิทอรีทำให้แหล่งข้อมูลเป็นนามธรรมผ่านโปรโตคอล ใช้รีโพซิทอรีในหน่วยความจำเพื่อการทดสอบที่รวดเร็ว รีโพซิทอรีแปลงข้อผิดพลาดของโครงสร้างพื้นฐานให้เป็นข้อผิดพลาดของโดเมน ส่วนบริการประสานงานการดำเนินการกับเอนทิตีหลายรายการ

เริ่มต้นได้ฟรี

เรียนรู้ Swift ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
122
บทเรียน
409

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

บทเรียน “รูปแบบกรณีใช้งานและคลังข้อมูล” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “รูปแบบกรณีใช้งานและคลังข้อมูล”

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

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

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

บทเรียน “รูปแบบกรณีใช้งานและคลังข้อมูล” ใช้เวลานานแค่ไหน

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

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

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

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

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