在学习编程的路上,相信你们这几个词必定很多听,什么 面相对象、封装继承多态、内功心法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, 小生在这边谢谢啦!!!