《重构-改善既有代码设计》案例之C#版(4)

书接上文...

这把要干个大的了,大神要把计算阶段与格式化阶段完全分离....为什么呢,因为目前这个结果是文本字符串,如果将来要新增一个需求,输出html格式的结果。那就只用新增格式化html的结果就行了。计算阶段的代码直接用就行了

这种分离的手法,叫做拆分阶段

那怎么做呢?

思路是:引入了中间数据,把代码分成2个部分,一部分计算详单所需的数据生成中间数据。一部分把中间数据渲染成想要的结果 比如文本或html

 至于手法,我太笨。。直接照抄了

要开始拆分阶段,大神先对组成第二阶段的代码引用提炼方法。这部分代码就是打印详单的代码。其实也就是statement的内容。大神把他提炼出来放在和statement同一层,新建了一个StatementData类,这个类目前没有任何内容。随着重构的过程慢慢添加

StatementData.cs

1     public class StatementData
2     {
3         public StatementData()
4         {
5         }
6     }
View Code

目前Statement及新提炼的方法如下(勘误:总金额不用再除100了)

 1         public string Statement()
 2         {
 3             StatementData statementData = new StatementData();
 4             return RenderPlainText(statementData);
 5         }
 6 
 7         private string RenderPlainText(StatementData statementData)
 8         {
 9             string result = $"Statement for {_invoice.Customer} \n";
10             foreach (var perf in _invoice.performances)
11             {
12                 result += $"{PlayFor(perf).name}: {Usd(AmountFor(perf))}({perf.audience}seats)\n";
13             }
14 
15             result += $"Amount owed is {Usd(TotalAmount() / 100)}\n";
16             result += $"You earned {TotalVolumeCredits()} credits \n";
17             return result;
18         }
View Code

 观察一下RenderPlainText,这个方法其实用到了customer,performances,以及调用了AmountFor(perf),TotalAmount(),TotalVolumeCredits()方法.

 所以StatementData需要填充这些内容

 1     public class StatementData
 2     {
 3         public string Customer;
 4         public List<Performance> Performances =new List<Performance>();
 5         public int TotalAmount;
 6         public int TotalVolumeCredits;
 7 
 8         public StatementData()
 9         {
10         }
11     }
View Code

你是不是发现了AmountFor(perf)这个没解决啊。确实,每一个Performance的金额不好搞。所以我想到的方法是,给Performane类一个Amount属性,然后用一个方法给每个Performance的Amount赋值。如下

Performance.cs

1     public class Performance
2     {
3         public string playID;
4 
5         public int audience;
6 
7         public int amount;
8 
9     }
View Code
1         private void EnrichStatementData(StatementData statementData)
2         {
3             foreach (var perf in statementData.Performances)
4             {
5                 perf.amount = AmountFor(perf);
6             }
7             statementData.TotalAmount = TotalAmount();
8             statementData.TotalVolumeCredits = TotalVolumeCredits();
9         }
View Code

这时候RenderPlainText是不是完全和计算无关了(其实PlayFor(perf)也可以去掉,给Performance类一个加一个Play字段,然后在EnrichStatementData方法里给他赋值)

 1         private string RenderPlainText(StatementData statementData)
 2         {
 3             string result = $"Statement for {statementData.Customer} \n";
 4             foreach (var perf in statementData.Performances)
 5             {
 6                 result += $"{perf.play.name}: {Usd(perf.amount)}({perf.audience}seats)\n";
 7             }
 8 
 9             result += $"Amount owed is {Usd(statementData.TotalAmount)}\n";
10             result += $"You earned {statementData.TotalVolumeCredits} credits \n";
11             return result;
12         }
View Code

现在的Statement如下

1         public string Statement()
2         {
3             StatementData statementData = new StatementData();
4             statementData.Customer = _invoice.Customer;
5             statementData.Performances = _invoice.performances;
6             EnrichStatementData(statementData);
7             return RenderPlainText(statementData);
8         }
View Code

对此可以继续提炼方法

 1         public string Statement()
 2         {
 3             StatementData statementData = CreateStatementData();
 4             return RenderPlainText(statementData);
 5         }
 6 
 7         private StatementData CreateStatementData()
 8         {
 9             StatementData statementData = new StatementData();
10             statementData.Customer = _invoice.Customer;
11             statementData.Performances = _invoice.performances;
12             EnrichStatementData(statementData);
13             return statementData;
14         }
View Code

这时候完成新增输出html格式的需求就十分简单了

 1         private string RenderHtml(StatementData statementData)
 2         {
 3             string result = $"<h1>Statement for {statementData.Customer} </h1>\n";
 4             result += "<table>\n";
 5             result += "<tr><th>play</th><th>seats</th><th>cost</th></tr>\n";
 6             foreach (var perf in statementData.Performances)
 7             {
 8                 result += $"<tr><td>{perf.Play.name}</td><td>{perf.audience}</td><td>{Usd(perf.Amount)}</td></tr>";
 9             }
10 
11             result += "</table>\n";
12             result += $"<p>Amount owed is <em>{Usd(statementData.TotalAmount)}</em></p>\n";
13             result += $"<p>You earned <em>{statementData.TotalVolumeCredits}</em> credits </p>\n";
14             return result;
15         }
View Code

 

效果如下

 

 

 本篇完成...待续...

上一篇:《重构-改善既有代码设计》案例之C#版(3) 下一篇:《重构-改善既有代码设计》案例之C#版(5)

posted @ 2023-03-11 18:15  吾乃零陵上将军邢道荣  阅读(23)  评论(0编辑  收藏  举报