在學習編程的路上,相信你們這幾個詞必定很多聽,什麼 面相對象、封裝繼承多態、內功心法21種設計模式 等等 。可是卻不多用到,或者說用到的都是被動使用。大牛們在寫代碼前早就構思好了,接口,基類等等。本身寫代碼的時候,不多有把面向對象想的面很全,很容易在趕上不夠優秀的代碼,這時候就須要重構了。前端
可是咱們卻不多去重構,可能緣由有不少,好比很重要的一點:不想改出Bug;不想增長工做量(我是要5點半下班的男人,女友還在等我作飯);時間很緊,先實現功能先;代碼是82年的不敢動!!!git
其實重構能夠寫出更健壯的代碼、減小後面的工做量、讓開發者更好閱讀。看了不少重構的文章,發現不少是一些基本的,命名規範或者拆函數什麼的。這篇文章寫下我重構的一些思路和重構以前代碼對比。好了,廢話很少說,上項目。威武、威武、威武........github
簡單介紹一下項目,項目就是一個客戶端小工具用來審覈編寫遞交的說明是否規範。這裏說下,面向對象是一種思想,和語言無關。只要是面嚮對象語言,不管你是C#、Java、TypeScript、Python,都是能夠用這種思想重構的。正則表達式
上圖就是小工具了一個部分截圖,有若干個欄,每一個欄都是填寫一些對應的修改內容,在審覈校驗時,會檢查寫的內容是否符合標準。編程
前輩已經完成一些欄的校驗,個人任務是完成剩下欄:寫正則表達式,而後在不標準的時候提示就行了,是否是以爲根本沒有必要重構,依葫蘆畫瓢就行了在我拿到代碼的時候,是這樣的代碼:設計模式
// 下面變量是和界面綁定的變量,RaisePropertyChanged做用在變量改變的時候通知前端從新渲染
// 不熟悉C#代碼的,只用知道這些變量就是和前臺綁定的就是了
private string _editDescription;
/// <summary>
/// 修改說明內容
/// </summary>
public string EditDescription
{
get { return _editDescription; }
set
{
_editDescription = value;
RaisePropertyChanged(() => EditDescription);
}
}
private string _editDescriptionRules;
/// <summary>
/// 修改說明校驗規則
/// </summary>
public string EditDescriptionRules
{
get { return _editDescriptionRules; }
set
{
_editDescriptionRules = value;
RaisePropertyChanged(() => EditDescriptionRules);
}
}
private bool _editDescriptionHasValidationError;
/// <summary>
/// 修改說明校驗標誌
/// </summary>
public bool EditDescriptionHasValidationError
{
get { return _editDescriptionHasValidationError; }
set
{
_editDescriptionHasValidationError = value;
RaisePropertyChanged(() => EditDescriptionHasValidationError);
}
}
private string _integratedNote;
/// <summary>
/// 集成注意內容
/// </summary>
public string IntegratedNote
{
get { return _integratedNote; }
set
{
_integratedNote = value;
RaisePropertyChanged(() => IntegratedNote);
}
}
private string _integratedNoteRules;
/// <summary>
/// 集成注意規則
/// </summary>
public string IntegratedNoteRules
{
get { return _integratedNoteRules; }
set
{
_integratedNoteRules = value;
RaisePropertyChanged(() => IntegratedNoteRules);
}
}
private bool _integratedNoteHasValidationError;
/// <summary>
/// 集成注意校驗標誌
/// </summary>
public bool IntegratedNoteHasValidationError
{
get { return _integratedNoteHasValidationError; }
set
{
_integratedNoteHasValidationError = value;
RaisePropertyChanged(() => IntegratedNoteHasValidationError);
}
}
// 這裏隨便舉了兩欄的變量,後面還有若干欄。
複製代碼
依葫蘆畫瓢之後呢,我發現原來是這樣的。每一欄用了單獨三個變量直接去綁定:編寫的內容、是否標準的標誌、不標準提示語。我是一個懶人啊,在我畫了兩個瓢之後,就很煩(一直在那複製變量,在那改來改去),這些個變量都是差很少一個意思。爲啥讓我重複在複製,修改呢?bash
明顯每欄有相同項啊,對不對,一個是內容,一個狀態,一個是錯誤提示語啊,咆哮!!!函數
這時候,我想起了書本上的一句話: "早重構,常重構"工具
我已經安奈不住我那顆懶惰的內心,由於下面還有「狠多狠多」欄,每一行有三個相似的變量,我這依葫蘆畫瓢,這個星期加班,就在複製粘貼去了。我是要上進,要天天進步的人,不能這樣!學習
我爲啥不能將這相同的共性抽象出來呢?是不咯,這個時候,我想起了《葵花寶典》的第一頁的第一句:「萬物皆對象」,因而本能的告訴我,每一欄看作一個對象,只是每欄的值不同。而後我就寫了一個」雞肋「(基類),代碼以下:
/// <summary>
/// 欄 基類
/// </summary>
public class Base: ObservableObject
{
private string _content;
/// <summary>
/// 內容
/// </summary>
public virtual string Content
{
get { return _content; }
set
{
_content = value;
RaisePropertyChanged(() => Content);
}
}
private string _errorTip;
/// <summary>
/// 錯誤提示
/// </summary>
public virtual string ErrorTip
{
get { return _errorTip; }
set
{
_errorTip = value;
RaisePropertyChanged(() => ErrorTip);
}
}
private bool _isError;
/// <summary>
/// 是否錯誤
/// </summary>
public virtual bool IsError
{
get { return _isError; }
set
{
_isError = value;
RaisePropertyChanged(() => ErrorTip);
}
}
}
複製代碼
virtual是爲了讓子類可以重寫get和set(若是有需求的話,爲後面擴展作準備),而後字段從3個變到了1個了。
/// <summary>
/// 修改說明欄
/// </summary>
public class EditDescription : Base { }
private EditDescription _editDescriptions;
/// <summary>
/// 修改說欄綁定變量
/// </summary>
public EditDescription EditDescriptions
{
get { return _editDescriptions; }
set
{
_editDescriptions = value;
RaisePropertyChanged(() => EditDescriptions);
}
}
// 其餘的同樣,我就很少寫了
複製代碼
那,咱們來算一下帳,原先的變量,每一欄有3個變量,一個變量有6行代碼的話,假如我這個有100欄,就是:
重構前: 100(欄)x3x6 = 1800 行代碼 (阿西吧!!!)。
重構後: 100(欄)x1x6 = 600 行代碼 。
小學算數: 1800 - 600 = 1200 (1200行,你說乾點啥很差啊)
那秀兒們算下,你花這麼多時間,在那複製粘貼,不敢去動前輩們的代碼,仍是勇敢一點呢?
而後是否是感受到一個繼承就簡單了不少呢,這只是一個面向對象的簡單運用,就讓咱們少寫了這麼多代碼。
前輩和我說,寫代碼就像練武功,就像你會了「九陽神功」或者"吸星大法",學其餘武功看一眼就會。也就是說,當你理解了面向對象之後呢,你天然而然的就會寫出很精簡的代碼了。阿西吧,又扯遠了。
變量好了,擡頭一看函數,個人臉便有點抽搐,啊!!這函數有毒!函數是這樣的:
// 此處函數用來設置每一欄報錯時邊框變紅
private void SetValidateFlag()
{
// 綁定的實體類判斷狀態
if (tsEntity.EditDescriptionHasValidationError)
{
// 控件邊框改顏色
EditDescriptionHsExpander.BorderThickness = new Thickness(1);
EditDescriptionHsExpander.BorderBrush = _readBrush;
}
if (tsEntity.TestSuggestionHasValidationError)
{
TestSuggestionHsExpander.BorderThickness = new Thickness(1);
TestSuggestionHsExpander.BorderBrush = _readBrush;
}
if (tsEntity.IntegratedNoteHasValidationError)
{
IntegratedNoteHsExpander.BorderThickness = new Thickness(1);
IntegratedNoteHsExpander.BorderBrush = _readBrush;
}
// 此處省略一萬個if,每一個欄都有一個if
}
複製代碼
而後你們懂的嘛,在我改了兩欄之後,我又耐不住性子了。再一看,感受似曾相識燕歸來的感受啊!有沒有,每一個if中都有三個相似的東西。我那個心啊,又忍不住悸動了起來,像是等初戀的感受,想她來,來了又不知道要幹哈。而後我發現其實if中判斷的就是每欄的狀態,括號裏面是對控件欄的設置。而後想嘛,能不能搞個相似循環的東西,只要寫一個for就行了呢。
思考之後,是這樣的,我把控件也變成了欄的一個屬性了,這樣if判斷裏面就都是判斷一個類了。代碼就變成了這樣:
public class Base: ObservableObject
{
/// <summary>
/// 模塊控件(新增)
/// </summary>
public object Control { get; set; }
//其餘的和上面的Base同樣
}
複製代碼
而後 SetValidateFlag() 函數就變成了這樣:
/// <summary>
/// 設置校驗界面效果
/// </summary>
private void SetValidateFlag()
{
// listBase 全部欄實體集合
foreach (var item in listBase)
{
if (item.IsError)
{
var control = item.Control as HsExpander;
if (control == null)
continue;
// 將控件的邊框變成紅色
control.BorderThickness = new Thickness(1);
control.BorderBrush = _readBrush;
}
}
}
複製代碼
好了嘞,好好的一個if的葫蘆瓢給咱給整沒了。這時候咱們來算算咱們這個重構,省了多少事。老樣子:
原先的一個if算5行代碼,我這個有100欄,就是:
重構前: 100(欄)x 5 = 500 行代碼 (全是if啊)。
重構後: 我數了一下,沒有錯的話應該是:14行代碼 。
重構一下之後,變量獲得了減小且對外統一。感受一顆心獲得了小小知足,感受靈魂獲得了昇華,不知道是本身太容易知足,仍是代碼世界裏給個人成就感。感受「乾坤大挪移」瞬間上了兩層。
這就是我在寫代碼的時候一個小小的重構思路,但願可以幫助到你們一點。而後這個是個人Github,若是有幫助到你們的項目,能夠給我點個star, 小生在這邊謝謝啦!!!