名字的重要性实在是再怎么强调都不为过的。
为什么名字这么重要呢?我的看法是,构建维护系统过程中最重要的事情之一就是同时建立并维护系统的一致性概念模型。无论通过何种手段进行沟通,如语言,文档,代码,注释,最重要的是有一套沟通的基石。即沟通各方对概念的理解是相同的,当提及一个概念时,大家所指的事物是相同的,没有二义性,没有模糊性。最怕张三在说西瓜,李四以为是个芝麻,鸡同鸭讲。倘若如此,好的结果是沟通过程中就发现了问题,花掉些时间,大家重新讨论各自概念的所指,最终达成了一致。运气差的话,沟通过程中并没有发现问题,各方都以为对方理解了自己的想法,于是大家都欢欢喜喜的做事情去了,终于在某一个时间点,才会惊喜的发现事情做的和预想的不一样,一些埋怨,指责,沟通后又重新开工了,可惜的是这个债务还起来是比较痛苦的,因为利息是驴打滚的。
概念是一个高度抽象的东西,看不见摸不着,难以把握,可以具化概念的一个工具就是给她命名,方便大家记忆理解。该命名代表了该概念,因此,命名应该是精确清晰的。如在一个系统中,有用户这样一个概念,那么我们既然已经命名了它的名字为user,那么请不要用诸如people,customer等等相似的名字来混淆视听。
概念的搭建并不是一件容易的事情,各个群体,业务方,开发方,测试方,运维方都有自己的方言。如果是跨团队跨公司合作的话,问题就更严重了。在软件开发的各个阶段,为了建立维护一套概念模型,都是要花费一定的时间的。
当一个系统搭建维护好了一个一致性概念模型后,对于以后的开发维护都是有着巨大的好处。
了解一个大型系统,一行行的读代码从时间上看是远远不够的,同时,系统代码又是不停动态变化的,因此该方法实际上不可行。概念模型相对比较稳定一些,先了解一个系统的概念模型(通过关键代码或者架构文档),然后在适当的时候深入一些细节,这样的方式更为可行一些。
常见的维护概念模型的工具有如下几种:文档,和人交流,代码注释,可执行代码。归根结底,代码才是一切的根本,和代码的距离越远,信息越容易不同步。这也是一直以来,业界认为自解释代码是最佳实践的原因之一。
另外,良好的概念模型和真实世界总是有着紧密关联的,有一个好名字,虽然并不意味着所有的代码都不需要一层层的深究到最底层,但是好的名字可以使开发维护时,凭借常识进行合理的猜测,更容易理解该命名背后的概念。如在一个People类的定义中有一个实例变量的名字是address,那么一个合理的猜测是该实例变量存储的是People的一个地址,而不是该People的手机号码。
如果有一行code是这样的:
那么我们会对这行代码做出什么样的判断呢?
我对这行代码的判断是从一个用户信息的模型中取出了用户的email。我相信大部分的人和我的猜测应该一致的。
但是很遗憾,这个猜测是错误的。同事给我指出在数据库中email的字段的存储值并不是该用户的email,该字段的说明是这样写的。如果该用户是用email注册的话,则该字段存储email值,否则存储该用户的手机号(系统目前只支持用email和手机号注册)。
有没有抓狂的感觉,我有。拜托,能不能让我的合理猜测是正确的。
还有另一个小例子。这个方法的功能是把一个大的列表划分为指定大小的一个子列表集合。
从代码可以明显看出,当时写这个方法的程序员是知道该方法的应用场景的,于是,在方法体中不自觉的就用该场景中的概念去命名一个变量。问题是,该方法作为一个通用的工具方法,和任何业务场景应该是无关的,在该方法的概念空间中,只有传入的一个大列表,指定的子列表大小和需要返回的子列表这些概念。
我见过最让人抓狂的一个命名的例子就是,在一个类体系中,一个类的名字和其父类,父类的父类是完全一样的,除了包命名不一样,同时,这些代码还是同一个程序员写的。好大一个坑。
经常听到的一个比喻是,程序是程序员的孩子,那么,给程序中任何元素命名的时候,是否应该如同给自己小孩起名一样小心谨慎呢?
为什么名字这么重要呢?我的看法是,构建维护系统过程中最重要的事情之一就是同时建立并维护系统的一致性概念模型。无论通过何种手段进行沟通,如语言,文档,代码,注释,最重要的是有一套沟通的基石。即沟通各方对概念的理解是相同的,当提及一个概念时,大家所指的事物是相同的,没有二义性,没有模糊性。最怕张三在说西瓜,李四以为是个芝麻,鸡同鸭讲。倘若如此,好的结果是沟通过程中就发现了问题,花掉些时间,大家重新讨论各自概念的所指,最终达成了一致。运气差的话,沟通过程中并没有发现问题,各方都以为对方理解了自己的想法,于是大家都欢欢喜喜的做事情去了,终于在某一个时间点,才会惊喜的发现事情做的和预想的不一样,一些埋怨,指责,沟通后又重新开工了,可惜的是这个债务还起来是比较痛苦的,因为利息是驴打滚的。
概念是一个高度抽象的东西,看不见摸不着,难以把握,可以具化概念的一个工具就是给她命名,方便大家记忆理解。该命名代表了该概念,因此,命名应该是精确清晰的。如在一个系统中,有用户这样一个概念,那么我们既然已经命名了它的名字为user,那么请不要用诸如people,customer等等相似的名字来混淆视听。
概念的搭建并不是一件容易的事情,各个群体,业务方,开发方,测试方,运维方都有自己的方言。如果是跨团队跨公司合作的话,问题就更严重了。在软件开发的各个阶段,为了建立维护一套概念模型,都是要花费一定的时间的。
当一个系统搭建维护好了一个一致性概念模型后,对于以后的开发维护都是有着巨大的好处。
了解一个大型系统,一行行的读代码从时间上看是远远不够的,同时,系统代码又是不停动态变化的,因此该方法实际上不可行。概念模型相对比较稳定一些,先了解一个系统的概念模型(通过关键代码或者架构文档),然后在适当的时候深入一些细节,这样的方式更为可行一些。
常见的维护概念模型的工具有如下几种:文档,和人交流,代码注释,可执行代码。归根结底,代码才是一切的根本,和代码的距离越远,信息越容易不同步。这也是一直以来,业界认为自解释代码是最佳实践的原因之一。
另外,良好的概念模型和真实世界总是有着紧密关联的,有一个好名字,虽然并不意味着所有的代码都不需要一层层的深究到最底层,但是好的名字可以使开发维护时,凭借常识进行合理的猜测,更容易理解该命名背后的概念。如在一个People类的定义中有一个实例变量的名字是address,那么一个合理的猜测是该实例变量存储的是People的一个地址,而不是该People的手机号码。
如果有一行code是这样的:
String email=userInfo.getEmail();
那么我们会对这行代码做出什么样的判断呢?
我对这行代码的判断是从一个用户信息的模型中取出了用户的email。我相信大部分的人和我的猜测应该一致的。
但是很遗憾,这个猜测是错误的。同事给我指出在数据库中email的字段的存储值并不是该用户的email,该字段的说明是这样写的。如果该用户是用email注册的话,则该字段存储email值,否则存储该用户的手机号(系统目前只支持用email和手机号注册)。
有没有抓狂的感觉,我有。拜托,能不能让我的合理猜测是正确的。
还有另一个小例子。这个方法的功能是把一个大的列表划分为指定大小的一个子列表集合。
public static List<List<String>> splitBigListBySize(List<String> list,
final int size) {
List<List<String>> packageList = new ArrayList<List<String>>();
// 逐一分切
List<String> bookList = null;
// do something
return packageList;
}
从代码可以明显看出,当时写这个方法的程序员是知道该方法的应用场景的,于是,在方法体中不自觉的就用该场景中的概念去命名一个变量。问题是,该方法作为一个通用的工具方法,和任何业务场景应该是无关的,在该方法的概念空间中,只有传入的一个大列表,指定的子列表大小和需要返回的子列表这些概念。
我见过最让人抓狂的一个命名的例子就是,在一个类体系中,一个类的名字和其父类,父类的父类是完全一样的,除了包命名不一样,同时,这些代码还是同一个程序员写的。好大一个坑。
经常听到的一个比喻是,程序是程序员的孩子,那么,给程序中任何元素命名的时候,是否应该如同给自己小孩起名一样小心谨慎呢?