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

การสร้างแบบจำลองโดเมนเชิงฟังก์ชันด้วยชนิดหลักของ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

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

  1. Either : การจัดการข้อผิดพลาดตามชนิดโดยไม่ใช้ Exception
  2. Arrow Raise DSL: การประกอบข้อผิดพลาดแบบมีชนิด
  3. Option และ Nullable: ควรใช้แต่ละแบบเมื่อใด
  4. การสร้างแบบจำลองโดเมนเชิงฟังก์ชันด้วยชนิดหลักของ Arrow
← กลับไปที่ Kotlin Academy