-

前言

我们初学编程时,教程上基本都会用下面的方式对变量进行命名

1
2
int a = 13;
int b = 15;

这种命名方式显然是不好的,它没有表达具体的含义,工作中也基本见不到有人会这样命名。

但前阵子我发现项目工程里关于变量使用的一个问题,请看下面两个示例。

一、示例

1
2
3
4
示例一:
if(self.pictureView && !self.pictureView.isHidden && self.headView && !self.headView.isHidden) {
// doSomething...
}
1
2
3
4
5
示例二:
BOOL canDoSomething = self.pictureView && !self.pictureView.isHidden && self.headView && !self.headView.isHidden;
if(canDoSomething) {
// doSomething...
}

二、分析

上面两个示例从代码优雅性来说,都是有优化的空间的。

(一)条件要拆解明确

1
2
3
4
示例一:
if(self.pictureView && !self.pictureView.isHidden && self.headView && !self.headView.isHidden) {
// doSomething...
}

比如这一个例子,开发过程中我们经常看到 if 中塞了N个条件,只有N个条件同时满足时,才允许 doSomething ,而把 N个条件 塞到 if 语句这种做法,不仅让 debug 调试起来非常麻烦(需要打出每个条件的值),而且表意不清晰,不要说新接手业务的同学,就是自己写的代码过一段时间可能也会被if中那么多的条件搞迷糊,心想:我当时加这些条件是为了干什么来的?

所以不要在 if 中夹杂太多逻辑,要把逻辑前置给局部bool变量,通过bool命名来说明这些条件的意义。

(二)变量命名应表示客观事实,而非推导的结论

1
2
3
4
5
示例二:
BOOL canDoSomething = self.pictureView && !self.pictureView.isHidden && self.headView && !self.headView.isHidden;
if(canDoSomething) {
// doSomething...
}

通过我们对示例一的分析,很有可能你会想到示例二的代码,但这个代码也是有优化空间的。

我们先来看这些条件:

self.pictureView && !self.pictureView.isHidden && self.headView && !self.headView.isHidden

这里表述的是 self.pictureViewself.headView 存在且显示,但变量bool却命名为canDoSomething

self.pictureViewself.headView 存在且显示」是客观事实,但canDoSomething是基于「self.pictureViewself.headView 存在且显示」推论出的结果,实际上「self.pictureViewself.headView 存在且显示」的客观条件在不附加潜在逻辑的条件下并不能决定canDoSomething ,客观条件是既有现实,基于客观条件能做出什么样的事情应该是 if 来决定的。

所以这里的写法应该被优化为:

1
2
3
4
5
BOOL pictureViewIsShow = self.pictureView && !self.pictureView.isHidden 
BOOL headViewIsShow = self.headView && !self.headView.isHidden;
if(pictureViewIsShow && headViewIsShow) {
// doSomething...
}

(三)方法命名依照通用原则

聊到变量命名规范,突然想起来很久之前被leader review提出的一个方法命名的问题,也记录一下。

背景是viewModel触发了uploadSuc事件,需要回调delegate告诉viewController去执行[self.tableView reloadData]

这里的 delegate 回调方法我最初命名是:

- (void)dataItemUploadSuc

leader 提出建议,说这样写不够通用,因为我要做的是告诉 viewController 去执行 [self.tableView reloadData] 行为,而这个行为是通用的,所以要新增的回调应该是:

- (void)updateTableViewReload

也就是说,除非你的方法有某些特殊的逻辑,否则都应该面向通用进行命名。