ခဏလေး ဒီလိုပဲ စဉ်းစားကြည့်
Part 3 က ဒီ project ရဲ့ နောက်ဆုံးအဆင့် ဖြစ်ပါတယ်။ Empty title ထည့်တာ၊ non-existent id ကို complete လုပ်ခိုင်းတာလို misuse case တွေကို graceful ဖြစ်စေဖို့ TaskError ဆိုတဲ့ custom Error enum ကို သတ်မှတ်ပြီး throws function တွေ ရေးမယ်။ addTask ကို validation ပါတဲ့ throwing function အဖြစ် ပြောင်းလဲပြီး do-catch ကို caller side မှာ သုံးပါမယ်။ နောက်ဆုံးအနေနဲ့ printSummary() method တစ်ခု ထည့်ပြီး done/pending count ကို priority အလိုက် group လုပ်ကာ report format ထုတ်ပေးမယ်။ ဒီအဆင့်ပြီးရင် error-handling, closures, struct/class, enum topic အားလုံးကို တစ်ပါတည်း ပေါင်းစပ်ထားတဲ့ project တစ်ခု ပြီးစီးသွားပါလိမ့်မယ်။
လက်တွေ့ ဆောက်ကြည့်မယ်
TaskError enum ကို emptyTitle, taskNotFound(id: Int) case နှစ်ခုနဲ့ Error protocol conform လုပ်ပြီး define ပါ။ addTask(title:priority:) ကို throws function ပြောင်းပြီး title.isEmpty ဖြစ်ရင် TaskError.emptyTitle throw ပါ။ completeTask(id:) ကိုလည်း throws ပြောင်းပြီး matching task မတွေ့ရင် TaskError.taskNotFound throw ပါ။ printSummary() method ရေးပြီး total, done, pending count နဲ့ priority တစ်ခုချင်းစီရဲ့ pending count ကို print ထုတ်ပါ။ main code ထဲမှာ do-catch block သုံးပြီး error case နှစ်ခုစလုံးကို handle ပြီး error message user-friendly ဖြစ်အောင် print ပါ။
Code နမူနာ
enum TaskError: Error {
case emptyTitle
case taskNotFound(id: Int)
}
extension TaskManager {
func addTask(title: String, priority: Priority) throws {
guard !title.trimmingCharacters(in: .whitespaces).isEmpty else {
throw TaskError.emptyTitle
}
let newTask = Task(id: tasks.count + 1, title: title, priority: priority)
tasks.append(newTask)
}
func completeTask(id: Int) throws {
guard let index = tasks.firstIndex(where: { $0.id == id }) else {
throw TaskError.taskNotFound(id: id)
}
tasks[index].isDone = true
}
func printSummary() {
print("===== Summary =====")
print("Total: \(tasks.count), Done: \(tasks.count - pendingCount), Pending: \(pendingCount)")
for p in [Priority.high, .medium, .low] {
let count = tasks.filter { $0.priority == p && !$0.isDone }.count
print("\(p.rawValue) pending: \(count)")
}
}
}
do {
try manager.addTask(title: "Error handling ကျက်မယ်", priority: .high)
try manager.completeTask(id: 99)
} catch TaskError.emptyTitle {
print("Title လွတ်နေလို့ task ထည့်လို့ မရပါ")
} catch TaskError.taskNotFound(let id) {
print("Task id #\(id) ကို ရှာမတွေ့ပါ")
} catch {
print("Unknown error: \(error)")
}
manager.printSummary()id #99 ကို ရှာမတွေ့လို့ "Task id #99 ကို ရှာမတွေ့ပါ" ဆိုတဲ့ message print ထွက်ပြီး၊ printSummary() ကနေ priority အလိုက် pending count ပါတဲ့ report ကို ထုတ်ပေးပါမယ်။၅ မိနစ် စမ်းကြည့်
TaskError မှာ duplicateTitle case တစ်ခု ထပ်ထည့်ပြီး addTask မှာ title တူညီတဲ့ task ရှိပြီးသားဆိုရင် error throw ဖြစ်အောင် ကိုယ်တိုင် ရေးကြည့်ပါ- 5 minute လောက် စမ်းကြည့်ပါ။
သတိလေးတစ်ချက်
catch block တွေရေးတဲ့အခါ order အရေးကြီးပါတယ် - general catch { } ကို အမြဲနောက်ဆုံးမှာပဲ ထားရပါမယ်၊ မဟုတ်ရင် specific error case တွေကို ဘယ်တော့မှ မရောက်ဘဲ compile error တောင် ထွက်နိုင်ပါတယ်။