1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

「リファクタリング 第2版」Swiftでコーディング その17

Posted at

25-29頁 第1章 計算とフォーマットにフェーズ分割「フェーズの分離(p.160)」「関数の移動(p.206)」

JavaScriptとSwiftの差を埋めています。
Struct「StatementData」「PerormanceMapPlay」を新規作成しています。

Swift版 main.swift

データ生成、結果表示付き。

import Foundation

makeData()

struct PerormanceMapPlay {
    let performance: Performance
    let play: Play
    var amount: Int = 0
    var volumeCredits: Int = 0
}

struct StatementData {
    let customer: String
    let performances: [PerormanceMapPlay]
    var totalAmount: Int = 0
    var totalVolumeCredits: Int = 0
}

func playFor(aPerformance:Performance) -> Play {
    return plays[aPerformance.playID]!
}

func volumeCreditsFor(aPerformance:Performance) -> Int {
    var result = 0
    result += max(aPerformance.audience - 30, 0)
    if "comedy" == playFor(aPerformance: aPerformance).type {
        result += Int(aPerformance.audience / 5)
    }
    return result
}

func usd(aNumber:Int) -> String {
    let format = NumberFormatter()
    format.numberStyle = .currency
    format.locale = Locale(identifier: "en_US")
    return format.string(from: NSNumber(value: aNumber / 100))!
}

func totalVolumeCredits(data:StatementData) -> Int {
    var result = 0
    for perf in data.performances {
        result += perf.volumeCredits
    }
    return result
}

func totalAmount(data:StatementData) -> Int {
    var result = 0
    for perf in data.performances {
        result += perf.amount
    }
    return result
}

func amountFor(aPerformance:PerormanceMapPlay) -> Int {
    var result = 0

    switch aPerformance.play.type {
    case "tragedy":
        result = 40000
        if aPerformance.performance.audience > 30 {
            result += 1000 * (aPerformance.performance.audience - 30)
        }
    case "comedy":
        result = 30000
        if aPerformance.performance.audience > 20 {
            result += 10000 + 500 * (aPerformance.performance.audience - 20)
        }
        result += 300 * aPerformance.performance.audience
    default:
        print("error")
    }
    return result
}

func enrichPerfoemance(aPerformance:[Performance], plays:Dictionary<String, Play>) -> [PerormanceMapPlay] {
    var result: [PerormanceMapPlay] = []
    for perf in aPerformance {
        var perormanceMapPlay = PerormanceMapPlay(performance: perf, play: playFor(aPerformance: perf))
        perormanceMapPlay.amount = amountFor(aPerformance: perormanceMapPlay)
        perormanceMapPlay.volumeCredits = volumeCreditsFor(aPerformance: perf)
        result.append(perormanceMapPlay)
    }
    return result
}

func statement(invoice:Invoice, plays:Dictionary<String, Play>) -> String {
    var statementData = StatementData(customer: invoice.customer, performances: enrichPerfoemance(aPerformance: invoice.performances, plays: plays))
    statementData.totalAmount = totalAmount(data: statementData)
    statementData.totalVolumeCredits = totalVolumeCredits(data: statementData)
    return renderPlainText(data: statementData, plays: plays)
}

func renderPlainText(data:StatementData, plays:Dictionary<String, Play>) -> String {
    var result = "Statement for \(data.customer)\n"

    for perf in data.performances {
        result += "  \(perf.play.name): " + usd(aNumber: perf.amount) + " (\(perf.performance.audience) seats)\n"
    }
    result += "Amount owed is " + usd(aNumber: data.totalAmount) + "\n"
    result += "You earned \(data.totalVolumeCredits) credits\n"
    return result
}

let result = statement(invoice: invoices[0], plays: plays)
print(result)
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?