מימוש חלקי בסקאלה דרך מיקסינים

08/07/2024

התבנית הבאה עזרה לי לארגן מחדש קצת קוד (נו, הרבה קוד) ולחלק אותו מקובץ אחד להרבה קבצים קטנים יותר, מה שגם עזר בבדיקות. נתחיל עם דוגמה פשוטה ונתבונן בקוד הבא:

class MyBigHandler {
  def handle(message: String): String =
    message match
      case "error" => "Handling error"
      case "warning" => "Handling warning"
      case "info" => "Handling info"
      case "zzz" => "MyHandler"
      case _ => "Unhandled message"
}

אז זה קל יש בסך הכל פונקציה אחת שמטפלת בכל מיני סוגים של הודעות. אבל נדמיין שההודעות מחולקות לקבוצות ושיש המון הודעות וקוד הטיפול בכל קבוצה צריך פונקציות עזר משותפות ואין ממש קשר בין הקבוצות. במצב כזה נרצה לפצל את ה match לקבצים וכל קובץ יהיה אחראי על קבוצת הודעות. ופה באים לעזרתנו ה Mixins. זה הקוד אחרי אירגון מחדש:

trait MessageHandler {
  def handle(message: String): String = "Unhandled Message"
}

trait ErrorHandler extends MessageHandler {
  abstract override def handle(message: String): String = message match {
    case "error" => "Handling error"
    case _ => super.handle(message)
  }
}

trait WarningHandler extends MessageHandler {
  abstract override def handle(message: String): String = message match {
    case "warning" => "Handling warning"
    case _ => super.handle(message)
  }
}

trait InfoHandler extends MessageHandler {
  abstract override def handle(message: String): String = message match {
    case "info" => "Handling info"
    case _ => super.handle(message)
  }
}

class MyHandler extends MessageHandler
  with ErrorHandler
  with WarningHandler
  with InfoHandler {

  override def handle(message: String): String =
    message match
      case "zzz" => "MyHandler"
      case _ => super.handle(message)
}

כל trait מטפל בהודעות שרלוונטיות עבורו ויכול לשבת בקובץ נפרד עם אוביקט של פונקציות עזר. ה Handler הוא פשוט הרכבה של כל המיקסינים ויכול להוסיף מימוש משלו לדברים שלא היה להם מקום באף מיקסין ועכשיו הרבה יותר קל לשלב את הטיפול בכל קבוצת הודעות גם במחלקות אחרות או לכתוב בדיקות לכל קבוצה בנפרד.