小酌重构系列[18]——重命名

Posted keepfool

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小酌重构系列[18]——重命名相关的知识,希望对你有一定的参考价值。

概述

代码是从命名开始的,我们给类、方法、变量和参数命名,我们也给解决方案、工程、目录命名。在编码时,除了应该遵守编程语言本身的命名规范外,我们应该提供好的命名。好的命名意味着良好的可读性,读你代码的人无需太多的注释,就能通过名称知道它是什么,它能做什么事儿,以及它应该怎么用。

我们命名、命名,不断地命名。既然有这么多命名要做,我们不妨做好他。

关于命名

取名字的成本

取个名字很简单,取个好的名字就不那么容易了。快速随意地取个名字,还不如花点时间取个好名字,因为好名字省下来的时间要比花掉的多。

假设你在程序中使用了不好的命名,将来有人读到你的程序时,他人可能会难以理解,于是去询问你。由于时间有点久远了,你需要花时间回忆当时的场景和逻辑。也许你能想起来,也许你忘记了它的确切含义,以至于最终你给到他人的答复是模糊不清的。
仔细算算吧,你们为了理解这些不好命名的含义,已经花了太多的时间了。

好的命名的关键是有意义

可以从以下几点出发,去取个有意义的名字。(以下内容,总结自《Clean code》)

  • 名副其实:名称本身应该告诉了你“它是谁?它是做什么的?它该怎么用”,如果名称需要注释来补充,则是名不副实的。
  • 避免误导:提防使用差异较小的名称,例如:你在ProductService中提供了3个方法,GetProducts,GetProductInfo和GetProductList。这3个名字可能是在不同场景下使用的,调用者要获取产品信息时,到底该用哪个名字呢?如果你通过注释来描述这3个方法的使用场景,那就是名不副实。
  • 做有意义的区分:如果缺少明确的约定,GetProducts,GetProductInfo和GetProductList是没有区别的。在程序中最好制定一个规则,例如通过“Get + 名词复数”的方式获取批量信息,那么在ProductService中就应该只能出现GetProducts方法。
  • 使用可搜索的名称:可搜索的名称,意味着在修改代码时,你可以通过全文搜索找到它们。例如:订单审批的状态,你通过1、2、3、4这些数字来表示,还不如通过NewCreated、Approving、Approved、Rejected来表示,它们既有实际意义,也更容易搜索。
  • 每个概念对应一个词:Fetch, Retrieve和Get都表示“获取”,如果你用这些词为同种方法命名,请取其一,并作为命名规则贯彻实行下去。
  • 添加有意义的语境:很少有名称是能自我说明的,你需要用良好命名的类、函数或命名空间来放置名称,给读者提供语境。如果没有这么做,则可以给名称添加前缀。假设你有firstName、lastName、street、houseNumber、state这些变量,当它们放一起的时候,很明确地构成了一个地址。但当你在某个方法中看到单独state变量时,state既能表示“状态”,又能表示“州”,你能推算出它的含义吗?你可以为变量添加前缀,addrFirstName, addrLastName和addrState等,这样就提供了明确且有意义的语境。

以上这些point,是除了编程语言本身的命名规范之外,你需要额外考虑的。不好的命名能混淆程序员的认知,给开发带来很多困扰。好的命名也不是一刻就能实现的,有时候限于你对系统和业务的理解,你可能难以给定一个“精确”的名称,但随着你掌握更深的业务,那些不好的名称你应该再反复推敲并调整。

示例

前面讲了那么多关于“命名”的事儿,都是为本文要讲的重构策略“重命名”做铺垫。

如果你使用Visual Studio开发程序,你可以借助一些工具来重命名,例如Resharper,这个工具还提供了良好的命名建议。

重构前

下面的代码为了描述员工的姓名和计算小时收入的方法。

public abstract class Person
{
    public string FN { get; set; }

    public decimal ClcHrlyPR()
    {
        // code to calculate hourly payrate
        return 0m;
    }
}

很显然,这段代码提供了难以理解的命名。

重构后

于是对这段代码做了3处重构:

  • 将Person类重命名为Employee。"Person"的含义太宽泛,"Employee"则能体现员工的概念。
  • 将FN属性重命名为FirstName。"FN"没有提供确切的语义,它是什么单词的缩写?是"File Number"(档案编号),还是Frost Nova(霜冻新星)?
  • 将ClcHrlyPR()方法重命名为CalculateHourlyPay()。"ClcHrlyPR()",如果没有注释,我们无从知道Clc、Hrly和PR所代表的含义。
// Changed the class name to Employee
public class Employee
{
    public string FirstName { get; set; }

    public decimal CalculateHourlyPay()
    {
        // code to calculate hourly payrate
        return 0m;
    }
}

小结

命名是程序员的基本功,很多程序员显然没有完全掌握这个基本功。如果你想成为一个优秀的程序员,良好的命名是必备的素质,它虽然不会体现出你会什么技术,但它会纵贯你整个编程生涯。
做好编程,从命名开始。

以上是关于小酌重构系列[18]——重命名的主要内容,如果未能解决你的问题,请参考以下文章

小酌重构系列[16]——引入契约式设计

小酌重构系列[17]——提取工厂类

小酌重构系列[20]——用条件判断代替异常

小酌重构系列[24]——封装集合

小酌重构系列[23]——封装条件

小酌重构系列[21]——避免双重否定