返回总目录


本小节目录:

1、Extract Method(提炼函数)

2、Inline Method(内联函数)

3、Inline Temp(内联临时变量)


1 Extract Method(提炼函数)

概要

你有一段代码可以被组织在一起并独立起来。

将这段代码放进一个独立函数中,并让函数名称解释该函数的作用。

动机

如果有一个过长的函数或者需要一段注释才能让人理解用途的代码,那么就将这段代码放进一个独立函数中。

简短而且命名良好的函数的好处:

  • 函数粒度小,被复用的机会大
  • 使高层函数读起来像注释
  • 函数都是细粒度,更易被复写

还记得在第二种坏味道——Long Method中说的函数到底有多长吗?作者如是说:“在我看来,长度不是问题,关键在于函数名称和函数本体之间的语义距离。如果提炼可以强化代码的清晰度,那就去做,就算函数名称比提炼出来的代码还长也无所谓。”

范例

    public class Receipt
{
private List<decimal> Discounts { get; set; }
private List<decimal> ItemTotals { get; set; } public decimal CalculateGrandTotal()
{
decimal subTotal = 0m;
//计算subTotal 的总和
foreach (decimal itemTotal in ItemTotals)
{
subTotal += itemTotal;
}
//subTotal 要循环减去discount,也就是计算Discount
if (Discounts.Count > )
{
foreach (decimal discount in Discounts)
{
subTotal -= discount;
}
}
//计算Tax
decimal tax = subTotal * 0.065m;
subTotal += tax;
return subTotal;
} }

重构后代码如下:

 public class Receipt
{
private List<decimal> Discounts { get; set; }
private List<decimal> ItemTotals { get; set; } public decimal CalculateGrandTotal()
{
decimal subTotal = CalculateSubTotal(); subTotal = CalculateDiscounts(subTotal); subTotal = CalculateTax(subTotal); return subTotal;
}
//计算subTotal 的总和
private decimal CalculateSubTotal()
{
decimal subTotal = 0m;
foreach (decimal itemTotal in ItemTotals)
{
subTotal += itemTotal;
}
return subTotal;
}
//计算折扣
private decimal CalculateDiscounts(decimal subTotal)
{
if (Discounts.Count > )
{
foreach (decimal discount in Discounts)
{
subTotal -= discount;
}
}
return subTotal;
}
//计算Tax
private decimal CalculateTax(decimal subTotal)
{
decimal tax = subTotal * 0.065m;
subTotal += tax;
return subTotal;
} }

小结

这个重构手法是不是很简单。我相信这个手法大多数人用的非常多,或许你潜意识里就是这么做的。

我不知道大家的公司有没有在代码编写规范里面把这个作为参考,比如一个方法最多不能超过多少行等等。这在一定程度上也能使程序员把这些复杂的逻辑剥离成意义很清楚的小方法。

2 Inline Method(内联函数)

概要

一个函数的本体与名称同样清楚易懂。

在函数调用点插入函数主体,然后移除该函数。

动机

使用间接层可以让函数通俗易懂,但是如果这个函数本体本就通俗易懂,那这个间接层就是无用的间接层,可以将其去除。

范例

int GetRating()
{
return MoreThanFiveLateDeliveries() ? : ;
} bool MoreThanFiveLateDeliveries()
{
return _numberOfLateDeliveries > ;
}

对于这个函数来说,MoreThanFiveLateDeliveries这个方法就是一个无用的间接层。因为原函数本就很清晰,此处将其去除。

重构后代码如下:

int GetRating()
{
return _numberOfLateDeliveries > ? : ;
}

小结

这个手法是比较简单的。但是不要因为简单就不注意它。在内联函数的时候,要确定该函数不具有多态性,因为子类无法覆写一个根本不存在的函数。

3 Inline Temp(内联临时变量)

概要

你有一个临时变量,只被一个简单表达式赋值一次,而它妨碍了其他重构手法。

将所有对该变量的引用动作,替换为对它赋值的那个表达式自身。

动机

这个手法多半是作为下一个要讲的手法Replace Temp with Query的一部分来使用的。

单独使用的情况是:某个临时变量被赋予某个函数调用的返回值,而这个临时变量妨碍了其他重构手法。

范例

bool GetBasePrice()
{
double basePrice = anOrder.GetBasePrice();
return basePrice > ;
}

重构后代码如下:

bool GetBasePrice()
{
return anOrder.GetBasePrice() > ;
}

小结

在将临时变量替换为表达式自身的时候要注意,这个临时变量在该函数内是否只被赋值一次。如果不是一次,那么就不要这么做。

To Be Continued...

重构手法之Extrct Method(提炼函数)的更多相关文章

  1. 重构改善既有代码设计--重构手法01:Extract Method (提炼函数)

    背景: 你有一段代码可以被组织在一起并独立出来.将这段代码放进一个独立函数,并让函数名称解释该函数的用途. void PrintOwing(double amount) { PrintBanner() ...

  2. 重构改善既有代码设计--重构手法08:Replace Method with Method Object (以函数对象取代函数)

    你有一个大型函数,其中对局部变量的使用,使你无法釆用 Extract Method. 将这个函数放进一个单独对象中,如此一来局部变量就成了对象内的值域(field) 然后你可以在同一个对象中将这个大型 ...

  3. 重构改善既有代码设计--重构手法16:Introduce Foreign Method (引入外加函数)&& 重构手法17:Introduce Local Extension (引入本地扩展)

    重构手法16:Introduce Foreign Method (引入外加函数)你需要为提供服务的类增加一个函数,但你无法修改这个类.在客户类中建立一个函数,并以第一参数形式传入一个服务类实例. 动机 ...

  4. 重构改善既有代码设计--重构手法10:Move Method (搬移函数)

    你的程序中,有个函数与其所驻类之外的另一个类进行更多的交流:调用后者,或被后者调用.在该函数最常用引用的类中建立一个有着类似行为的新函数.将旧函数编程一个单纯的委托函数,或是将旧函数完全移除. 动机: ...

  5. 重构手法之Replace Temp with Query(以查询取代临时变量)

    返回总目录 6.4Replace Temp with Query(以查询取代临时变量) 概要 你的程序以一个临时变量保存某一表达式的运算结果. 将这个表达式提炼到一个独立函数中.将这个临时变量的所有引 ...

  6. 重构手法之Introduce Explaining Variable(引用解释性变量)

    返回总目录 6.5Introduce Explaining Variable(引用解释性变量) 概要 你有一个复杂的表达式. 将该复杂表达式(或其中一部分)的结果放进一个临时变量,以此变量名称来解释表 ...

  7. 重构改善既有代码设计--重构手法05:Introduce Explaining Variable (引入解释性变量)

      发现:你有一个复杂的表达式. 解决:将该复杂的表达式(或其中的部分)的结果放进一个临时变量,并以此变量名称来解释表达式用途. //重构前 if((platform.toUpperCase().in ...

  8. 重构改善既有代码设计--重构手法04:Replace Temp with Query (以查询取代临时变量)

    所谓的以查询取代临时变量:就是当你的程序以一个临时变量保存某一个表达式的运算效果.将这个表达式提炼到一个独立函数中.将这个临时变量的所有引用点替换为对新函数的调用.此后,新函数就可以被其他函数调用. ...

  9. 重构手法之Split Temporary Variable(分解临时变量)

    返回总目录 本小节目录 Split Temporary Variable(分解临时变量) Remove Assignments to Parameters(移除对参数的赋值) 6.6Split Tem ...

随机推荐

  1. Java高级工程师进阶路线

    第一部分:宏观方面 一. JAVA.要想成为JAVA(高级)工程师肯定要学习JAVA.一般的程序员或许只需知道一些JAVA的语法结构就可以应付了.但要成为JAVA(高级) 工程师,您要对JAVA做比较 ...

  2. Asp.Net MVC4 系列-- 进阶篇之路由(1)

    创建一个路由 打开 RouteConfig.cs  ,发现已经创建了一个默认路由 : routes.MapRoute( name:"Default", url:"{con ...

  3. springboot使用zookeeper(curator)实现注册发现与负载均衡

    最简单的实现服务高可用的方法就是集群化,也就是分布式部署,但是分布式部署会带来一些问题.比如: 1.各个实例之间的协同(锁) 2.负载均衡 3.热删除 这里通过一个简单的实例来说明如何解决注册发现和负 ...

  4. 比较两个文件不同以及生成SQL插入语句

    Tips 做一个终身学习的人! 日拱一卒,功不唐捐. 今天有个小小的需求,具体需求是这样的: 有两个文本文件,每个文件都有一些字符串文本: 比较第一个文件中,在第二个文件中,不存在的字符串文本: 把这 ...

  5. 使用Jquery.cookie.js操作cookie

    query.cookie.js是一个基于jquery的插件,点击下载! 创建一个会话cookie: $.cookie(‘cookieName’,'cookieValue’); 注:当没有指明cooki ...

  6. win10 uwp 获得焦点改变

    本文讲的是当我们应用失去焦点时,我们获得事件,当我们应用获得焦点,同样获得事件.同时,在应用不可以见时,我们也可以获得. 上面一张图,开始是应用启动,获得焦点,应用显示.然后我们打开另一个应用,切换, ...

  7. 解题笔记-洛谷-P1010 幂次方

    0 题面 题目描述 任何一个正整数都可以用2的幂次方表示.例如 137=2^7+2^3+2^0 同时约定方次用括号来表示,即a^b 可表示为a(b). 由此可知,137可表示为: 2(7)+2(3)+ ...

  8. A low-cost wear-leveling algorithm for block-mappingsolid-state disks

    [] Li-Pin Chang,Li-Chun Huang.A low-cost wear-leveling algorithm for block-mapping solid-state disks ...

  9. JQuery-基础学习1

    1)JQuery语法 jquery语法是为HTML元素的选取编制,可以对元素执行某些操作. 基础语法是:$(selector).action() 美元符号定义JQuery 选择符(selector)& ...

  10. 基于itchat的微信群聊小助手基础开发(一)

    前段时间由于要管理微信群,基于itchat开发了一个简单的微信机器人 主要功能有: 图灵机器人功能 群聊昵称格式修改提示 消息防撤回功能 斗图功能 要开发一个基于itchat的最基本的聊天机器人,在g ...