「リファクタリング 第2版」Swiftでコーディング その17
リファクタリング 第2版
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)