Как бороться с классом, который имеет слишком много параметров в конструкторе - Scala? - PullRequest
0 голосов
/ 05 ноября 2018

Я моделирую некоторые типы данных, которые по своей природе имеют много полей.

Тогда у меня есть ужасный код , где конструктор класса имеет длинный список аргументов, а также все его подклассы.

Я сомневаюсь, является ли BuilderPattern хорошим решением для этого.

Например, это универсальный класс Transaction:

class Transaction(
    source: String,
    format: String,
    id: String,
    amount: Double,
    currency: String,
    senderAccount: String,
    senderName: String,
    receiverAccount: String,
    receiverName: String,
    execDate: LocalSate,
    createdDateTime: Instant)

Это подкласс A TxTypeA, который имеет некоторые специальные поля, специфичные для типа A:

class TxTypeA(
    source: String,
    format: String,
    id: String,
    amount: Double,
    currency: String,
    senderAccount: String,
    senderName: String,
    receiverAccount: String,
    receiverName: String,
    execDate: LocalSate,
    createdDateTime: Instant,
    typeAField1: String,
    typeAField2: String,
    typeAField3: String
) extends Transaction(
    source,
    format,
    id,
    amount,
    currency,
    senderAccount,
    senderName,
    receiverAccount,
    receiverName,
    execDate,
    createdDateTime)

Это подкласс B TxTypeB, который имеет некоторые специальные поля, специфичные для типа B:

class TxTypeB(
    source: String,
    format: String,
    id: String,
    amount: Double,
    currency: String,
    senderAccount: String,
    senderName: String,
    receiverAccount: String,
    receiverName: String,
    execDate: LocalSate,
    createdDateTime: Instant,
    typeBField1: String,
    typeBField2: String,
    typeBField3: String,
    typeBField4: String,
    typeBField5: String,
    typeBField6: String,
    typeBField7: String
) extends Transaction(
    source,
    format,
    id,
    amount,
    currency,
    senderAccount,
    senderName,
    receiverAccount,
    receiverName,
    execDate,
    createdDateTime)

У кого-нибудь есть лучшее решение для этого?

UPDATE:

В моем проекте я создал еще один класс под названием Party, который обернул Account и Name, но это просто избавляет от боли, а не решает проблему в ядре.

case class Party(account: String, name: String)

class Transaction(
    source: String,
    format: String,
    id: String,
    amount: Double,
    currency: String,
    senderParty: Party,
    receiverParty: Party,
    execDate: LocalSate,
    createdDateTime: Instant)

Ответы [ 3 ]

0 голосов
/ 05 ноября 2018

В подобных случаях я собираюсь объединить поля в другие классы.

Например, Транзакция может быть составом из Отправителя, Получателя, Суммы и т. Д.

0 голосов
/ 05 ноября 2018

Вы можете немного привести в порядок это, сделав Transaction чертой:

trait Transaction {
  val source: String
  val format: String
  val id: String
  val amount: Double
  val currency: String
  val senderAccount: String
  val senderName: String
  val receiverAccount: String
  val receiverName: String
  val execDate: LocalState
  val createdDateTime: Instant
}

case class TxTypeA(
  source: String,
  format: String,
  id: String,
  amount: Double,
  currency: String,
  senderAccount: String,
  senderName: String,
  receiverAccount: String,
  receiverName: String,
  execDate: LocalState,
  createdDateTime: Instant,
  typeAField1: String,
  typeAField2: String,
  typeAField3: String
) extends Transaction

case class TxTypeB(
  source: String,
  format: String,
  id: String,
  amount: Double,
  currency: String,
  senderAccount: String,
  senderName: String,
  receiverAccount: String,
  receiverName: String,
  execDate: LocalState,
  createdDateTime: Instant,
  typeBField1: String,
  typeBField2: String,
  typeBField3: String,
  typeBField4: String,
  typeBField5: String,
  typeBField6: String,
  typeBField7: String
) extends Transaction

Если вы хотите, вы можете даже объединить эти значения в меньшие классы падежей, содержащие связанные поля, что-то вроде этого:

case class Party(account: String, name: String)

trait Transaction {
  val source: String
  val format: String
  val id: String
  val amount: Double
  val currency: String
  val sender: Party
  val receiver: Party
  val execDate: LocalState
  val createdDateTime: Instant
}

case class TxTypeA(
  source: String,
  format: String,
  id: String,
  amount: Double,
  currency: String,
  sender: Party,
  receiver: Party,
  execDate: LocalState,
  createdDateTime: Instant,
  typeAField1: String,
  typeAField2: String,
  typeAField3: String
) extends Transaction

case class TxTypeB(
  source: String,
  format: String,
  id: String,
  amount: Double,
  currency: String,
  sender: Party,
  receiver: Party,
  execDate: LocalState,
  createdDateTime: Instant,
  typeBField1: String,
  typeBField2: String,
  typeBField3: String,
  typeBField4: String,
  typeBField5: String,
  typeBField6: String,
  typeBField7: String
) extends Transaction

Или вы можете пойти дальше, передав Транзакцию как параметр, а не расширяя ее:

case class Party(account: String, name: String)

case class Transaction (
  val source: String,
  val format: String,
  val id: String,
  val amount: Double,
  val currency: String,
  val sender: Party,
  val receiver: Party,
  val execDate: LocalState,
  val createdDateTime: Instant
)

case class TxTypeA(
  transaction: Transaction,
  typeAField1: String,
  typeAField2: String,
  typeAField3: String
)

case class TxTypeB(
  transaction: Transaction,
  typeBField1: String,
  typeBField2: String,
  typeBField3: String,
  typeBField4: String,
  typeBField5: String,
  typeBField6: String,
  typeBField7: String
)

Это зависит от вашего варианта использования и того, что возможно. Если вы делаете что-то вроде форматирования Json, я бы рекомендовал расширить его, чтобы поля Json совпали (или создать определенные операции чтения и т. Д.).

0 голосов
/ 05 ноября 2018

Почему бы не использовать классы случаев для моделирования связанной информации? например отправитель и получатель в транзакции могут быть смоделированы как отдельные классы дел;

case class Account(id: String, name: String)


class Transaction(
    source: String,
    format: String,
    id: String,
    amount: Double,
    currency: String,
    sender: Account
    reciever: Account
    execDate: LocalSate,
    createdDateTime: Instant)

Таким образом вы уменьшаете количество параметров в конструкторе. Затем вы можете добавить вспомогательные методы в класс Transaction или реализовать шаблон построителя, например, TransactionBuilder.withSender (senderName, senderAccountId)

...