การสร้างแบบจำลองโดเมนเชิงฟังก์ชันด้วยชนิดหลักของ Arrow
สร้างแบบจำลองโดเมนที่ซับซ้อนโดยใช้ Either, NonEmptyList และการสะสมข้อผิดพลาดที่ผ่านการตรวจสอบ
การสร้างแบบจำลองโดเมนเชิงฟังก์ชันด้วยชนิดหลักของ Arrow เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน
การสร้างแบบจำลองโดเมนเชิงฟังก์ชันคืออะไร
การสร้างแบบจำลองโดเมนเชิงฟังก์ชันใช้ชนิดพีชคณิต (Either, Option, คลาสปิดผนึก) เพื่อเข้ารหัสกฎทางธุรกิจลงในชนิดข้อมูล สถานะที่ไม่ถูกต้องจะไม่สามารถแสดงแทนได้ตั้งแต่เวลาคอมไพล์ และข้อผิดพลาดจะแสดงอย่างชัดเจนในลายเซ็นของฟังก์ชัน — ไม่มีข้อยกเว้นที่ซ่อนอยู่
ออบเจ็กต์ค่าโดยใช้คลาสแบบอินไลน์/คลาสค่า
ใช้คลาสค่าของ Kotlin เพื่อห่อหุ้มชนิดพื้นฐานและป้องกันการยึดติดกับชนิดพื้นฐาน ระบบชนิดข้อมูลจะปฏิเสธการส่ง UserId ในตำแหน่งที่คาดว่าจะเป็น PostId:
@JvmInline value class UserId(val value: Long)
@JvmInline value class PostId(val value: Long)
fun findUser(id: UserId): Either<UserError, User> = TODO()
// findUser(PostId(1L)) // Compile error!คลาสปิดผนึกสำหรับข้อผิดพลาดของโดเมน
สร้างแบบจำลองข้อผิดพลาดเป็นลำดับชั้นของคลาสปิดผนึก คลาสย่อยแต่ละคลาสจะเก็บเฉพาะข้อมูลที่เกี่ยวข้องกับกรณีข้อผิดพลาดนั้น:
sealed class UserError {
data class NotFound(val id: UserId) : UserError()
data class EmailTaken(val email: String) : UserError()
data class ValidationFailed(val field: String, val reason: String) : UserError()
}Validated: การรวบรวมข้อผิดพลาดหลายรายการ
เมื่อคุณต้องการรายงานข้อผิดพลาดจากการตรวจสอบความถูกต้องทั้งหมดในครั้งเดียว (ไม่ใช่แค่รายการแรก) ให้ใช้ Validated ของ Arrow (หรือ zipOrAccumulate ใน DSL ของ Raise) ซึ่งจะรวบรวมข้อผิดพลาดไว้ใน NonEmptyList:
import arrow.core.Validated
import arrow.core.valid
import arrow.core.invalid
fun validateName(name: String): Validated<String, String> =
if (name.isNotBlank()) name.valid() else "Name is blank".invalid()การประกอบการตรวจสอบความถูกต้อง
ใช้ zip() เพื่อรวมผลลัพธ์ Validated หลายรายการเข้าด้วยกัน หากรายการใดเป็น Invalid ข้อผิดพลาดทั้งหมดจะถูกรวบรวมไว้:
val result: Validated<NonEmptyList<String>, User> =
validateName(name).zip(validateEmail(email)) { n, e -> User(n, e) }
.mapLeft { it }ทำให้สถานะที่ไม่ถูกต้องไม่สามารถแสดงแทนได้
แทนที่จะใช้ User ที่มี email ซึ่งอาจเป็นค่าว่างและมีแฟล็ก isVerified ให้ใช้คลาสย่อยแบบปิดผนึก เพื่อให้ระบบชนิดข้อมูลป้องกันไม่ให้เข้าถึงอีเมลของผู้ใช้ที่ยังไม่ได้ยืนยัน:
sealed class User {
data class Unverified(val id: UserId, val pendingEmail: String) : User()
data class Verified(val id: UserId, val email: String) : User()
}ตัวสร้างอัจฉริยะ
ใช้ฟังก์ชันโรงงานของออบเจ็กต์คู่หูที่ส่งคืน Either หรือ Option แทนตัวสร้างสาธารณะ วิธีนี้ทำให้มั่นใจได้ว่าอินสแตนซ์จะอยู่ในสถานะที่ถูกต้องเสมอ:
class Email private constructor(val value: String) {
companion object {
fun of(raw: String): Either<String, Email> =
if (raw.contains("@") && raw.length <= 255) Email(raw).right()
else "Invalid email format".left()
}
}การผสานชนิดอีเทอร์และออปชันในกระบวนการประมวลผล
การดำเนินการกับโดเมนจริงมักเชื่อมโยงการค้นหาจากคลังข้อมูล (Option) เข้ากับการตรวจสอบความถูกต้อง (Either) ให้ใช้บล็อก either { } ของ Arrow ร่วมกับ .bind() เพื่อประกอบการทำงานเหล่านี้อย่างต่อเนื่อง:
fun createPost(authorId: UserId, title: String, body: String): Either<PostError, Post> = either {
val author = userRepo.findById(authorId).toEither { PostError.AuthorNotFound }.bind()
val validTitle = validateTitle(title).bind()
postRepo.save(Post(author, validTitle, body))
}ความไม่เปลี่ยนแปลงและการคัดลอก
เอนทิตีของโดเมนควรไม่เปลี่ยนแปลง ใช้คลาสข้อมูลและ copy() เพื่อสร้างสถานะใหม่ Arrow's Lens (จาก arrow-optics) ช่วยให้ปรับปรุงข้อมูลที่ซ้อนกันได้อย่างสะดวกโดยไม่ต้องกลายพันธุ์ข้อมูล:
val updated = user.copy(email = "new@example.com")
// Arrow Optics:
val emailLens = User.email
val updatedWithLens = emailLens.set(user, "new@example.com")การกำหนดค่าที่ปลอดภัยด้านชนิดข้อมูลด้วยคลาสปิดผนึก
สร้างแบบจำลองรูปแบบต่าง ๆ ของการกำหนดค่าแอปพลิเคชันด้วยคลาสปิดผนึก เพื่อให้คอมไพเลอร์บังคับให้คุณจัดการกับทุกกรณี:
sealed class DbConfig {
data class Postgres(val url: String, val user: String, val pass: String) : DbConfig()
data class InMemory(val dbName: String = "test") : DbConfig()
}ประโยชน์โดยสรุป
การสร้างแบบจำลองโดเมนเชิงฟังก์ชันด้วยชนิดหลักของ Arrow มอบประโยชน์ดังนี้:
- ไม่มีข้อยกเว้นตัวชี้ว่างในโค้ดโดเมน
- ข้อผิดพลาดแสดงให้เห็นในลายเซ็นของฟังก์ชัน
- การตรวจสอบ
whenอย่างครบถ้วนในลำดับชั้นของคลาสปิดผนึก - ฟังก์ชันบริสุทธิ์ที่ทดสอบได้
- โค้ดที่อธิบายตัวเอง
แบบทดสอบสั้น ๆ
ประโยชน์หลักของการใช้ลำดับชั้น sealed class สำหรับข้อผิดพลาดของโดเมน เมื่อเทียบกับการโยนข้อยกเว้นคืออะไร
สรุป: การสร้างแบบจำลองโดเมนเชิงฟังก์ชันด้วยชนิดหลักของ Arrow
ประเด็นสำคัญ:
- คลาสค่าช่วยป้องกันการยึดติดกับชนิดพื้นฐาน
- ลำดับชั้นข้อผิดพลาดแบบปิดผนึกทำให้กรณีล้มเหลวครอบคลุมทั้งหมดและปลอดภัยด้านชนิดข้อมูล
- ตัวสร้างอัจฉริยะรับประกันว่าอินสแตนซ์ถูกต้อง
either { }.bind()ช่วยประกอบการดำเนินการที่อาจล้มเหลวได้อย่างเป็นระเบียบ- ข้อมูลที่ไม่เปลี่ยนแปลงร่วมกับ
copy()/ ออปติกส์ของ Arrow ช่วยให้การเปลี่ยนสถานะปลอดภัย
คำถามที่พบบ่อย
บทเรียน “การสร้างแบบจำลองโดเมนเชิงฟังก์ชันด้วยชนิดหลักของ Arrow” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การสร้างแบบจำลองโดเมนเชิงฟังก์ชันด้วยชนิดหลักของ Arrow” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การสร้างแบบจำลองโดเมนเชิงฟังก์ชันด้วยชนิดหลักของ Arrow”
สร้างแบบจำลองโดเมนที่ซับซ้อนโดยใช้ Either, NonEmptyList และการสะสมข้อผิดพลาดที่ผ่านการตรวจสอบ คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การสร้างแบบจำลองโดเมนเชิงฟังก์ชันด้วยชนิดหลักของ Arrow” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม
ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- Either : การจัดการข้อผิดพลาดตามชนิดโดยไม่ใช้ Exception
- Arrow Raise DSL: การประกอบข้อผิดพลาดแบบมีชนิด
- Option และ Nullable: ควรใช้แต่ละแบบเมื่อใด
- การสร้างแบบจำลองโดเมนเชิงฟังก์ชันด้วยชนิดหลักของ Arrow