Это больше вопрос дизайна, чем что-либо еще...
Мне очень нравятся кейс-классы Scala, и я часто их использую. Однако я обнаружил, что часто включаю свои параметры в Options
(или, скорее, Boxes
в Lift) и устанавливаю значения по умолчанию, чтобы обеспечить гибкость и учесть, что пользователь может не всегда указывать все параметры. Я думаю, что я перенял эту практику от.
Мой вопрос в том, является ли это разумным подходом? Учитывая, что все может быть необязательным, может быть много шаблонов и проверок, вплоть до того, задаюсь ли я вопросом, не использую ли я просто свои классы case, такие как Map[String, Any]
, и задаюсь вопросом, не лучше ли мне просто использовать Map
.
Приведу реальный пример. Здесь я моделирую денежный перевод:
case class Amount(amount: Double, currency: Box[Currency] = Empty)
trait TransactionSide
case class From(amount: Box[Amount] = Empty, currency: Box[Currency] = Empty, country: Box[Country] = Empty) extends TransactionSide
case class To(amount: Box[Amount] = Empty, currency: Box[Currency] = Empty, country: Box[Country] = Empty) extends TransactionSide
case class Transaction(from: From, to: To)
Относительно просто для понимания, я думаю. В самом простом случае мы можем объявить Transaction
так:
val t = Transaction(From(amount=Full(Amount(100.0)), To(country=Full(US)))
Я уже могу представить, что вы думаете, что это многословно. А если указать все:
val t2 = Transaction(From(Full(Amount(100.0, Full(EUR))), Full(EUR), Full(Netherlands)), To(Full(Amount(150.0, Full(USD))), Full(USD), Full(US)))
С другой стороны, несмотря на то, что вам приходится везде разбрасывать Full
, вы все равно можете сделать хорошее сопоставление с образцом:
t2 match {
case Transaction(From(Full(Amount(amount_from, Full(currency_from1))), Full(currency_from2), Full(country_from)), To(Full(Amount(amount_to, Full(currency_to1))), Full(currency_to2), Full(country_to))) if country_from == country_to => Failure("You're trying to transfer to the same country!")
case Transaction(From(Full(Amount(amount_from, Full(currency_from1))), Full(currency_from2), Full(US)), To(Full(Amount(amount_to, Full(currency_to1))), Full(currency_to2), Full(North_Korea))) => Failure("Transfers from the US to North Korea are not allowed!")
case Transaction(From(Full(Amount(amount_from, Full(currency_from1))), Full(currency_from2), Full(country_from)), To(Full(Amount(amount_to, Full(currency_to1))), Full(currency_to2), Full(country_to))) => Full([something])
case _ => Empty
}
Это разумный подход? Будет ли мне лучше обслуживаться с помощью Map
? Или я должен использовать case-классы, но по-другому? Возможно, использовать целую иерархию классов дел для представления транзакций с различным количеством указанной информации?