فرض کنید ما چند نوع داده داریم که میخواهیم به json تبدیل کنیم و توسط کافکا بفرستیم
case class Person(name: String, age: Int)
case class Book(name: String, author: String)
راه حل OO:
ساختن interface و inheritance
trait Encoder {
def toJson: Json
}
case class Person(name: String, age: Int) extends Encoder {
def toJson = " { \"name\": \"${name}\", age: ${age}
}
"
}
object KafkaPublisher {
def publish(encoder: Encoder): Unit = {
KafkaProducer.send("topic" encoder.toJson)
}
}
مشکل ها با این روش:
۱. پیچیدگی ارث بری
۲. خیلی مواقع ما به داده دسترستی نداریم که interface برایش بنویسیم و باید در object دیگه بصورت مصنوعی ابجکت رو بپوشینیم
۳. داده و عملکرد خیلی به هم coupling دارند
راه حل functional:
داده رو از عملکرد موردنظر جدا میکنیم
و به صورت generic برای هر تایپ تعریف میکنیم
trait Encoder[A] {
def toJson(a: A): Json
}
object KafkaPublisher {
def publish[A](a: A)(implicit encoder: Encoder[A]): Unit = {
KafkaProducer.send("topic" encoder.toJson(a))
}
}
حالا برنامه کافکا برای همه ی داده ها کار میکنه تا زمانی که Encoder برای آنها تعریف بشه این داده میتونه در کتابخانه ای باشه که ما اصلا تا به حال ندیدیم
اما هروقت نیاز داشته باشیم کافیه که Encoder برای آن تعریف کنیم