>

저는 스칼라의 초보자입니다. 리팩토링을 잘하는 방법을 모르겠습니다. 현재 읽을 때 지루하기 때문입니다. BidWinPostData와 BidEventPostData라는 2 개의 클래스가 있습니다. getSelectorAndModifier를 호출 할 때 2와 다른 것은 modifier와 비슷합니다.

에서 사용하고 있습니다

bidEventRDD.foreach { line =>
        println("bidEventRDD => " + line)
        implicit val formats = Serialization.formats(NoTypeHints)
        val bidEventPostList = parse(line).extract[List[BidEventPostData]]
        for (event <- bidEventPostList) {
          val selector, modifier = BidEventPostData.getSelectorAndModifier(event)
          if (event.isPerCampaign || event.isPerChannel) {
            aggregationCol.findAndUpdate(selector, modifier, upsert = true)
          }
          else if (event.isDailyWin) {
            dailyWinCol.findAndUpdate(selector, modifier, upsert = true)
          }
        }
      }
      bidWinRDD.foreach { line =>
        implicit val formats = Serialization.formats(NoTypeHints)
        println("bidWinRDD => " + line)
        val bidWinList = parse(line).extract[List[BidWinPostData]]
        for (event <- bidWinList) {
          val selector, modifier = BidWinPostData.getSelectorAndModifier(event)
          if (event.isPerCampaign || event.isPerChannel) {
            aggregationCol.findAndUpdate(selector, modifier, upsert = true)
          }
          else if (event.isDailyWin) {
            dailyWinCol.findAndUpdate(selector, modifier, upsert = true)
          }
        }
      }

이 수업은 2 개입니다

case class BidWinPostData(width: Option[Int], height: Option[Int], cid: String, host: Option[String],
                          per_channel: Option[Boolean], per_campaign: Option[Boolean],
                          totalBudgetSpent: Long, totalAuctionSpent: Long, totalWin: Long,
                          startOfDayTs: Option[Long], wid: String){
  def isValidEvent: Boolean = {
    this.wid != null || this.cid != null
  }
  def isPerCampaign: Boolean = {
    this.per_campaign != null && this.per_campaign.nonEmpty
  }
  def isPerChannel: Boolean = {
    this.per_channel != null && this.per_channel.nonEmpty
  }
  def isDailyWin: Boolean = {
    this.startOfDayTs != null && this.startOfDayTs.nonEmpty
  }
}
object BidWinPostData {
  def getSelectorAndModifier(event: BidWinPostData): (BSONDocument, BSONDocument) = {
    var selector = BSONDocument()
    var modifier = BSONDocument()
    if (event.isValidEvent) {
      if (event.isPerCampaign) {
        if (event.wid != null) {
          selector = BSONDocument(
            "per_campaign" -> true,
            "wid" -> event.wid,
            "cid" -> event.cid)
        }
        else {
          selector = BSONDocument(
            "per_campaign" -> true,
            "cid" -> event.cid)
        }
        modifier = BSONDocument("$inc" -> BSONDocument(
          "totalBudgetSpent" -> event.totalBudgetSpent,
          "totalAuctionSpent" -> event.totalAuctionSpent,
          "totalWin" -> event.totalWin))      }
      else if (event.isPerChannel) {
        if (event.wid != null) {
          selector = BSONDocument(
            "width" -> event.width.get,
            "height" -> event.height.get,
            "host" -> event.host.get,
            "per_channel" -> true,
            "wid" -> event.wid,
            "cid" -> event.cid)
        }
        else {
          selector = BSONDocument(
            "width" -> event.width.get,
            "height" -> event.height.get,
            "host" -> event.host.get,
            "per_channel" -> true,
            "cid" -> event.cid)
        }
        modifier = BSONDocument("$inc" -> BSONDocument(
          "totalBudgetSpent" -> event.totalBudgetSpent,
          "totalAuctionSpent" -> event.totalAuctionSpent,
          "totalWin" -> event.totalWin))
      }
      else if (event.isDailyWin) {
        if (event.wid != null) {
          selector = BSONDocument(
            "timestamp" -> event.startOfDayTs.get,
            "widgetid" -> event.wid,
            "campaignid" -> event.cid)
        }
        else {
          selector = BSONDocument(
            "timestamp" -> event.startOfDayTs.get,
            "campaignid" -> event.cid)
        }
        modifier = BSONDocument("$inc" -> BSONDocument("total_win" -> event.totalWin))
      }
    }
    (selector, modifier)
  }
}

case class BidEventPostData(width: Option[Int], height: Option[Int], cid: String, host: Option[String],
                            per_channel: Option[Boolean], per_campaign: Option[Boolean], auction: Long, startOfDayTs: Option[Long],
                            wid: String) {
  def isValidEvent: Boolean = {
    this.wid != null || this.cid != null
  }
  def isPerCampaign: Boolean = {
    this.per_campaign != null && this.per_campaign.nonEmpty
  }
  def isPerChannel: Boolean = {
    this.per_channel != null && this.per_channel.nonEmpty
  }
  def isDailyWin: Boolean = {
    this.startOfDayTs != null && this.startOfDayTs.nonEmpty
  }
}
object BidEventPostData {
  def getSelectorAndModifier(event: BidEventPostData): (BSONDocument, BSONDocument) = {
    var selector = BSONDocument()
    var modifier = BSONDocument()
    if (event.isValidEvent) {
      if (event.isPerCampaign) {
        if (event.wid != null) {
          selector = BSONDocument(
            "per_campaign" -> true,
            "wid" -> event.wid,
            "cid" -> event.cid)
        }
        else {
          selector = BSONDocument(
            "per_campaign" -> true,
            "cid" -> event.cid)
        }
        modifier = BSONDocument("$inc" -> BSONDocument("totalAuction" -> event.auction))
      }
      else if (event.isPerChannel) {
        if (event.wid != null) {
          selector = BSONDocument(
            "width" -> event.width.get,
            "height" -> event.height.get,
            "host" -> event.host.get,
            "per_channel" -> true,
            "wid" -> event.wid,
            "cid" -> event.cid)
        }
        else {
          selector = BSONDocument(
            "width" -> event.width.get,
            "height" -> event.height.get,
            "host" -> event.host.get,
            "per_channel" -> true,
            "cid" -> event.cid)
        }
        modifier = BSONDocument("$inc" -> BSONDocument("totalAuction" -> event.auction))
      }
      else if (event.isDailyWin) {
        if (event.wid != null) {
          selector = BSONDocument(
            "timestamp" -> event.startOfDayTs.get,
            "widgetid" -> event.wid,
            "campaignid" -> event.cid)
        }
        else {
          selector = BSONDocument(
            "timestamp" -> event.startOfDayTs.get,
            "campaignid" -> event.cid)
        }
        modifier = BSONDocument("$inc" -> BSONDocument("auction_count" -> event.auction))
      }
    }
    (selector, modifier)
  }

  • 답변 # 1

    솔직히 말해서이 코드에는 몇 가지 나쁜 습관이 있습니다.

    쉽고 사소한 것이 불일치의 이름을 짓고있다 : per_channel totalBudgetSpent . 일반적인 관습이 scala/java 세계이기 때문에 후자를 선택하십시오.

    가장 주목할만한 문제는 특정 데이터 표현과 밀접한 관련이있는 비즈니스 로직을 포함한다는 것입니다.

    와이즈 비즈  Type-safety가 Scala에 유리한 주요 논거 인 경우 비 유형 안전 방식으로 많은 비즈니스 로직을 포함합니다. 이 논리의 출력은 원하는 데이터가 포함 된 강력한 형식의 사례 클래스 여야합니다. 그런 다음이 클래스는 간단한 방법으로 BSONDocument로 변환해야합니다.

    두 클래스 사이에는 어느 정도 중복이 있지만 리팩토링에는 도메인 지식이 필요하다 : BidWin getSelectorAndModifier 의 경우  BidEvent 또는 반대의 경우 하나는 다른 하나를 인수로 포함해야합니까? 일대일입니까? 서로 관련이 없지만 has-a 에 기록 될 수있는 일부 정보를 공유하고 있습니다.  그들이 물려받을 계급? 이 답변은 데이터 표현과 직접 관련이 없으며 성능 저하로 구성 될 수 있습니다.

    마침내, BidInfo isPerCampaign isPerChannel 메소드는 계층 구조의 존재를 강력하게 제안합니다. 이러한 사례를 다른 클래스로 표현하면 코드 명확성과 형식 안전성을 모두 구매할 수 있습니다. 다시 한 번 계층 구조 생성 결정이 데이터 표현과 관련되어서는 안됩니다. 실제로, Scala의 대소 문자 비교 구문은 계층 구조에서 평면 표현 또는 그 반대로 이동하는 매우 우아한 방법입니다.

    isDailyWin

  • 이전 c - 특정 숫자로 숫자 계산
  • 다음 javascript - 스크롤 할 때 컨테이너 안에있을 때 div를 고정하십시오