iT邦幫忙

2024 iThome 鐵人賽

DAY 10
0

新生方法

重構前

假如有個類別TransactionGate, 用來處理每個交易的日期設定, 並賦予manager做處理.

public class TransactionGate
{
	public void PostEntries(List<Entry> entries)
	{
		foreach(var entry in entries)
		{
			entry.PostDate();
		}
		transactionBundle.GetListManager().Add(entries);
	}
}

此時我們要修改流程, 驗證是否有重複的交易時, 改成這樣

public class TransactionGate
{
	public void PostEntries(List<Entry> entries)
	{
		List<Entry> entriesToAdd = new List<Entry>();
		foreach(var entry in entries)
		{
			if(!transactionBundle.GetListManager().Contains(entry))
			{
				entry.PostDate();
				entriesToAdd.Add(entry);
			}
		}
		transactionBundle.GetListManager().Add(entriesToAdd);
	}
}

重構後

new List<Entry>()開始的驗證邏輯, 抽成一個新的方法UniqueEntries(函數)來處理.

public class TransactionGate
{
	public void PostEntries(List<Entry> entries)
	{
		List<Entry> entriesToAdd = UniqueEntries(entries) ;
		foreach(var entry in entriesToAdd)
		{
			entry.PostDate();
		}
		transactionBundle.GetListManager().Add(entriesToAdd);
	}
	
	private List<Entry> UniqueEntries(List<Entry> entries)
	{
		List<Entry> result = new List<Entry>();
		foreach(var entry in entries)
		{
			if(!transactionBundle.GetListManager().Contains(entry))
			{
				result.Add(entry);
			}
		}
		
		return result;
	}
}

新生類別

重構前

假如有個類別QuarterlyReportGenerator, 用來產生每季報表:

public class QuarterlyReportGenerator
{
    public string Generate()
    {
        string result = "<html><head>...";
        result += "content";
        result += "content";
        result += "content";
        result += "content";
        result += "content";

        return result;
    }
}

重構後

這時要多新的報表header, 我們將它放在新的類別QuarterlyReportTableHeaderProducer
並放到QuarterlyReportGenerator使用

public class QuarterlyReportTableHeaderProducer
{
    public string MakeHeader()
    {
        return "header....";
    }
}

public class QuarterlyReportGenerator
{
    public string Generate()
    {
        string result = "<html><head>...";
        result += "content";
        result += "content";
        result += "content";
        result += "content";
        result += "content";
        QuarterlyReportTableHeaderProducer producer = new QuarterlyReportTableHeaderProducer();
        result += producer.MakeHeader();

        return result;
    }
}

為了讓概念一致, 讓命名都改成Generate, 也能同時抽出共通的類別或介面

public abstract class HTMLGenerator
{
    public abstract string Generate();
}

public class QuarterlyReportGenerator : HTMLGenerator
{
    public override string Generate()
    {
        string result = "<html><head>...";
        result += "content";
        result += "content";
        result += "content";
        result += "content";
        result += "content";
        HTMLGenerator producer = new QuarterlyReportTableHeaderProducer();
        result += producer.Generate();

        return result;
    }
}

public class QuarterlyReportTableHeaderProducer : HTMLGenerator
{
    public override string Generate()
    {
        return "header....";
    }
}

需用到新生類別的兩種情境

  1. 迫使為某個類別新增某個職責時
    1. 比如TaxCalculator要增加驗證日期的功能, 則驗證日期應該要放新的類別來完成
  2. 跟範例一樣, 在一個既有的巨大類別增加小小功能, 但這巨大類別又不可測時.

上一篇
程式接縫 Seam
下一篇
外覆(Wrap) 方法與類別
系列文
程式淨化計畫:痛苦是重構的起源!31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言