美文网首页
go代码演示:重构 改善既有代码的设计(第2版)重构第一版

go代码演示:重构 改善既有代码的设计(第2版)重构第一版

作者: 春天的尐熊 | 来源:发表于2021-11-06 11:38 被阅读0次

    重构前代码:https://www.jianshu.com/p/e5a3ba308aca

    theatre.go

    type Play struct {
        Name string
        Type string
    }
    
    type Plays map[string]Play
    
    type Performance struct {
        PlayID   string
        Audience int
    }
    
    type Invoices struct {
        Customer     string
        Performances []Performance
    }
    
    func statement(invoices Invoices, plays Plays) (result string) {
        param := NewStatementParam(invoices, plays)
        data := NewStatementDate(param)
        return data.packTxt()
    }
    

    theatre_data.go

    type statementDate struct {
        Customer     string
        PerfDataList []PerformanceData
        TotalAmount  float64
        TotalCredits int
    }
    
    func NewStatementDate(param *statementParam) *statementDate {
        s := &statementDate{}
        s.Customer = param.invoices.Customer
        s.PerfDataList = param.buildPerfDataList()
        s.TotalAmount = s.totalAmount()
        s.TotalCredits = s.totalCredits()
        return s
    }
    
    func (s *statementDate) totalAmount() (totalAmount float64) {
        for _, perf := range s.PerfDataList {
            totalAmount += perf.ThisAmount
        }
        return totalAmount
    }
    
    func (s *statementDate) totalCredits() (totalCredits int) {
        for _, perf := range s.PerfDataList {
            totalCredits += perf.ThisCredits
        }
        return totalCredits
    }
    
    type PerformanceData struct {
        PlayName    string
        ThisAmount  float64
        ThisCredits int
        Audience    int
    }
    
    func NewPerformanceData(playName string, thisAmount float64, thisCredits, audience int) PerformanceData {
        return PerformanceData{
            PlayName:    playName,
            ThisAmount:  thisAmount,
            ThisCredits: thisCredits,
            Audience:    audience,
        }
    }
    

    theatre_pack.go

    func (s *statementDate) packTxt() (result string) {
        result = fmt.Sprintf("Statement for %s\n", s.Customer)
        for _, data := range s.PerfDataList {
            result += fmt.Sprintf("    %s: $%.2f(%d seats)\n", data.PlayName, data.ThisAmount, data.Audience)
        }
        result += fmt.Sprintf("Amount Owed is $%.2f\n", s.TotalAmount)
        result += fmt.Sprintf("You earned %d credits\n", s.TotalCredits)
        return result
    }
    
    func (s *statementDate) packHTML() (result string) {
        return result
    }
    
    func (s *statementDate) packXML() (result string) {
        return result
    }
    

    theatre_param.go

    type statementParam struct {
        invoices Invoices
        plays    Plays
    }
    
    func NewStatementParam(invoices Invoices, plays Plays) *statementParam {
        return &statementParam{
            invoices: invoices,
            plays:    plays,
        }
    }
    
    func (s *statementParam) buildPerfDataList() []PerformanceData {
        perfDataList := make([]PerformanceData, 0, len(s.invoices.Performances))
        for _, perf := range s.invoices.Performances {
            perfDataList = append(perfDataList, s.buildPerformanceData(perf))
        }
        return perfDataList
    }
    
    func (s *statementParam) buildPerformanceData(perf Performance) PerformanceData {
        var (
            playName    = s.NameFor(perf)
            thisAmount  = s.thisAmountFor(perf)
            thisCredits = s.thisCreditsFor(perf)
            audience    = perf.Audience
        )
        return NewPerformanceData(playName, thisAmount, thisCredits, audience)
    }
    
    func (s *statementParam) thisAmountFor(perf Performance) float64 {
        var thisAmount int
        switch s.TypeFor(perf) {
        case "tragedy":
            thisAmount = 40000
            if perf.Audience > 30 {
                thisAmount += 1000 * (perf.Audience - 30)
            }
            break
        case "comedy":
            thisAmount = 30000
            if perf.Audience > 20 {
                thisAmount += 10000 + 500*(perf.Audience-20)
            }
            thisAmount += 300 * perf.Audience
            break
        default:
            panic(fmt.Sprintf("unknow type: %s", s.TypeFor(perf)))
        }
        return float64(thisAmount) / 100
    }
    
    func (s *statementParam) thisCreditsFor(perf Performance) (thisCredits int) {
        thisCredits = util.Max(perf.Audience-30, 0)
        if s.TypeFor(perf) == "comedy" {
            thisCredits += perf.Audience / 5
        }
        return thisCredits
    }
    
    func (s *statementParam) TypeFor(perf Performance) string {
        return s.plays[perf.PlayID].Type
    }
    
    func (s *statementParam) NameFor(perf Performance) string {
        return s.plays[perf.PlayID].Name
    }
    

    相关文章

      网友评论

          本文标题:go代码演示:重构 改善既有代码的设计(第2版)重构第一版

          本文链接:https://www.haomeiwen.com/subject/yuqjzltx.html