敏捷风水之代码命名的艺术-Certified Scrum Developer认证课直播实录

2018年4月Scrum中文公开课上海CSM认证培训成功-优普丰敏捷
2018年6月1日
敏捷实践中开Daily Scrum站会的思考
2018年6月8日
本文根据《会说话的代码》一书作者王洪亮的直播进行整理。敏捷风水师,社区知名技术大牛,资深软件开发及敏捷咨询师,精益创业导师,Scrum认证CSP。十余年软件行业从业经验,精通日语和英语。多年来一直致力于软件代码开发方法和技巧的研究,是国内“自表达代码”方面的权威,并著有《会说话的代码》一书。擅长极限编程(XP)、测试驱动开发(TDD)、持续集成(CI)、重构(Refactor)、演进式设计(Evolutionary Design)以及降低代码的复杂度(Cyclomatic Complexity)。通过重构、重写,将代码量大幅度缩减,并且提高可读性、可扩展性、可变更性,从而大幅度降低开发成本。对测试用例设计、划分等有深入研究,对如何提高测试的稳定性以及测试覆盖率有丰富的经验。他也是北京和天津敏捷软件社区的活跃组织者和分享者。长期担任戴姆勒-奔驰创新实验室的精益创业导师和敏捷教练等。

1、命名的重要性

软件开发的命名是团队合作的基础。代码是写给人类阅读的。越容易阅读的代码,越容易维护,越容易接手。结构的设计良好会让代码的调用变得容易阅读。结构设计不仅仅是考虑对象的职责和关系,也要考虑调用时的阅读。

编程语言中有很多约定俗成的习惯,应当遵守。

每个团队应该形成自己的编程习惯,不要各种不同的习惯混杂在一起。

让代码读起来像句子是非常实用的设计实践。

2、基本要领

a.采用英文命名。不要有拼音命名,或者其他语言的,比如日语,韩语,法语…比如:orderState,而不是dingDanZhuangTai。

b.有明确的分割识别,比如驼峰命名或者下划线分割。不要用没有分割的命名。

c.常量或者枚举值采用全部大写字母,下划线分割。

d.注意语法错误,例如:例如lengthOfTime表示时间长度,timeLength是语法错误。建议不要出现of,改为

class TimeRange {
    public int length();
}

则调用为:timeRange.length();可以用点号很好的替代Of。

e.词汇的选择,例如:auth表示认证,而doLogin是词穷的表现。当准备用do, execute, process,run等开头的时候,表示应该选取合适的词汇了。

edit表示编辑,而save表示保存。弄清楚词汇的含义有助于更好地设计流程。

3、词汇的使用

a.名词

i. 一般用于表示物理对象和抽象对象

1.物理对象例如:Book

2.抽象对象例如:State

ii. 单数形式

1.单数形式表示单独的对象

iii. 复数形式

1.复数形式表示多个对象的结合

2.如果没有复数形式,可以用~List,~Map,~Array等形式表示多个数据。

iv. 名词用作方法名,有助于理解

1.比如:TimeRange.days()表示时间范围的天数。Length.max表示最大长度(用于校验的注解)

b.动词

i. 动词作为方法名,例如:configure()

ii. 动名词,用作对象定义Movement,Configuration

iii. 动词和名词组合表示某个具体动作,但是注意,名词有可能出现在参数中。比如:makeOrder()下订单的调用形式可能是makeOrder(order);读起来比较怪,改为make(order);可能更容易其阅读

iv. 第三人称形式,为什么text.matches(regExp)要用第三人称表达?因为读起来符合语法习惯。同样的还有string.equals(another)

c.形容词

i. Cloneable

1.采用~able结尾命名的形容词,表示具备某种能力

ii. Configurable

iii. @Transactional

d.介词

i. on

1.用于前缀,表示在发生某件事情的时候的动作。例如:onChange,onClick,onKeyDown, onKeyUp

ii. at

1.表示时间

2.表示地点

iii. with

1.表示附加

例如:

public class Render {

    public void with(Renderer renderer) {}

}

调用时可能表现为:

picture.render().with(Rederer.BOLD_BRUSH);

e.代词

i. what

1.用于表示判定条件。比如:swtich(message.what)

ii. this

1.默认关键词

iii. that

1.和this结合表示对比,例如compareTo(that);

2.assertThat(actual, matcher)是改变assertEquals两个参数类型一样,会被调反的一种设计。例如:

assertThat(2 + 3, is(5));

iv. self

1.用于替代this,在某些场景使用,比如js语言中,this对象要发生变化之前,用self代替this。

v. one,another。

1.表示对比,比如compare(one, another)

vi. other

1.表示对比,比如compareTo(other)

f. 情态动词

i. is,作为开头表示,是否的判断。一般is不要用作变量的开头,仅做方法的开头,如果打算用作变量的开头,尝试改下变量的名字。比如:isEnough,表示足够,改为enough试试。你可以得到一个isEnough()的getter,而不是getIsEnough()。同样的你可以判断if(isEnough()) {}。并且在复制的时候协作enough = amount > expense;比较符合阅读习惯。

ii. can,作为开头词,表示是否有某种能力

iii. has,表示有。注意,不要用isHave  这个错误比较常见

g. 生命周期修饰语

i. should           表示某事情应该发生

ii. will                 表示某事情将要发生

ii. did         表示事情已经发生

iv. util         表示直到某事情发生

h. 其他固定词用法

i. contains       表示包含(注意和has的区别,has表示集合,contains表示一个对象和另外一个对象的关系)

ii. get         表示获取

iii. put        表示放入

iv. set        表示设置

4、时态的使用

a. 原形

i.用于方法定义。例如:create表示创建

b. 过去式

i. 表示过去发生的事情,例如:CreatedTime(创建这个动作发生的时间),而不是createTime(去创建时间这个对象)

ii. 用于表示发生的状态:

c. 进行时

i. 例如:running用于线程的执行情况判定

d. 被动式

i. 例如:selected表示被选中的对象集合

ii. 例如:deleted表示对象是否已经逻辑删除

5、点的使用

a.点的基本作用

i. 所有格

1.对象的属性

a. 例如:user.name

2. 对象的行为

a. 例如:emailAddress.verify();

ii. 类型

1.对象的属性定义

a.比如:Order.State.CREATED

b. FluenAPI

i. 一般常见的是Builder模式,比如:

AlertDialog.Builder.create().setTitle().setMessage().setPositiveButto().setNegativeButton().setNeuturalButton().show();

6、同义词

a. delete和remove是否会同时出现?

b. start和begin有什么区别?

c. generate和create有什么区别?和build有什么区别?

d. length,size,count有什么区别?

e. category和type有什么区别?

f. Status(技术状态)和State(业务状态)有什么区别?

g. find,query和search有什么区别?

h. verify和valid有什么区别?

7、反义词

a.start(开始执行某件事情) – end(结束某件事情)

b.previous(前一个)- next(下一个)

8、时间的命名

a. current       – 当前的,不是当前时间,比如currentOrder

b. timestamp – 时间戳,可以附带形容词,表示时间戳。

c. now             – 当前时间。

d. date             – 不太适合用于表示日期

e. time             – 不太适合用于表示时间

f. at         – 表示发生的时间

g. from            – 表示来自,例如copyFrom

h. to         – 表示去向,例如toString(), toJson()

i. timeRange – 表示时间范围

1. 例如:exam.range().isInside(now);

9、容器命名

a. Container     表示容器(里面往往放置同样的东西)

b. Wrapper     表示包装(往往是外层装饰)

c. Tuple        表示数据的组合,参考自swift

d. Range      表示范围

10、缩写(直播时未说明部分)

a. 因为IDE支持自动补全,尽量不用缩写

比如:msg并不比message好多少。

b. 如果特别特别特别长的命名,可以考虑通过点号等形式来逐步缩短命名

c. 如果遇到众所周知的术语可以采用缩写。比如:eof(文件结尾)。

11、否定式(直播时未说明部分)

a. 不要直接用否定式命名,比如:keyboardNotConnected不利于理解。

b.可以采用否定含义的词汇命名错误或者异常,例如:InvalidOrderStateException

c.主要看应用场景,一般用于if判定的变量最好不要用否定形式表达。

12、前缀,后缀(直播时未说明部分)

a.常用固定前缀后缀

i. 比如:I~表示接口

ii.比如:~Impl表示实现

b. 内部变量不要用类名作为前缀,例如order.state,而不是order.orderState

13、Spring的层的命名(Service,Dao, DTO, BO, process/business)

service,dao,bo(也是entity)采用直接对应的名字命名即可

DTO参考容器部分

process/business主要在于业务逻辑的代码结构设计,不应该是按照流程图来的,而是按照设计模式来的。

14、枚举的命名

a.枚举的类型名要能够表征意思

b.枚举的值名不要带有类型前缀

15、空及空白的表述

a. empty         – 清空  empty()

b. empty         – 为空   isEmpty()

c. null              – 空对象

d. none           没有特定值

e. n/a               无效

f. unknown   未知

 

16、设计模式的命名

a. State——状态模式

b. Strategy——策略模式

c. Builder——构建者模式

d. Proxy——代理模式

e. Adapter——适配器模式

f. Factory——工厂模式

17、专业术语的命名

a. 采用术语表

18、和关键词重复的意思的词汇选取(直播时未说明部分)

a. 尝试  (try)                attempt

b. 类或者班级(class) clazz

19、同一对象的不同形式的区分

a. getCreatedTime()获取创建时间;getFormattedCreatedTime()获取格式化后的创建时间。

b. String paramPageIndex –来自网页参数的页号;Integer pageIndex = 实际的页号。

20、通用对象的命名(直播时未说明部分)

a. entity,object等可以用作通用对象的命名。一般通用的命名用于基础框架设计。

21、其他注意事项(直播时未说明部分)

a. flag是个没有意义的名字,尽量不要用。教科书的误导。用有意义的词汇替代,比如found表示找到了,matched表示一致了。

b. sex表示性,不是性别,性别要用gender

c. from和form不要拼写错误

d. 数字开头定义的内容,比如404,可以做_404,也可以做notFound,因为这个往往用于HTTP状态判定,参考HttpStatus的定义

e. 避免出现xxx2的命名

22、防止词穷(直播时未说明部分)

a. 掌握正确的词汇

positive(正面), negative(负面), neutral (中立)

而不是yes, no, middle

b. 熟知细微差别

Email(包含subject,body,multiparts, from, to,cc, bcc等)和EmailAddress(包含姓名和地址)

想学习了解更多XP极限编程和软件匠艺?来参加Certified Scrum Developer国际认证(CSD)课程吧~ (https://www.uperform.cn/csd-technical-engineering-practice/)

拨打免费咨询电话 021-63809913