引言
上上上个月在图书馆淘到一本书叫《Effective Python - 编写高质量Python代码的59个有效方法》,虽然我不用 Python 写代码,但是好歹以前写过一点 Python 的皮毛。
豆瓣看了一下评分,就果断借了这本书。当看到第四条方法《第4条:用辅助函数来取代复杂的表达式 》结合自己最近几年编程经验,深有感触,于是就有了这篇文章。
为什么要用辅助函数?
在编程的时候,你肯定会遇到类似这样的事情:数据库中保存的商品单价单位是分,商品详情页需要你的商品价格,但是单位肯定是元。
那么我们可以怎么样实现呢?一般的做法肯定这样的,直接在视图页面要展示价格的地方这样写:
1
|
<?= round(($price / 100), 2) ?>
|
这样写虽然能实现效果,但是如果需求有变化,需要使用强制保留两位小数,那么你需要这样改:
1
|
<?= number_format(round(($price / 100), 2), 2, '.', ''); ?>
|
看上去虽然不多的代码,但是
- 阅读起来很困难,而且很上去也很乱。
- 如果涉及到很多东西的话,需要找到每个相应的地方然后做修改。同理,下次改需求的时候,修改也将会是一件很痛苦的事情。
如果使用辅助函数来实践的话,代码将会是这样的:
1
2
3
4
5
6
7
8
9
10
11
12
|
/**
* 分转元
* @param int $price 分
* @return float 元
*/
function fenToYuan($price)
{
$price = round(($price / 100), 2);
return number_format($price, 2, '.', '');
}
// 视图层使用方式
echo fenToYuan($price);
|
一旦这样使用之后,代码将变得非常清晰,而且以后重构起来也非常方便。以上是为了说明辅助函数的作用特意列举的一个小示例,实际项目中,可能会有大量需要你使用这种方式编程的地方,你需要养成这种思维模式才是最重要的。
PS:以上代码可以在这里查看并且运行。
Yii2 中是如何实践的?
Yii2 中有一个 helpers 文件夹,里面的代码推荐各位 PHP 工程师都应该去看看,注释都给了示例,非常的友好。
下面我来简单分享一些常用的 helpers:
ArrayHelper
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// 最基本的用法,获取数组中的某个键对应的值。好处是不必判断 username 是否存在
$username = \yii\helpers\ArrayHelper::getValue($_POST, 'username');
// 也可以获取对象中的某个值
$username = \yii\helpers\ArrayHelper::getValue($user, 'username');
// 也可以使用匿名函数
$fullName = \yii\helpers\ArrayHelper::getValue($user, function ($user, $defaultValue) {
return $user->firstName . ' ' . $user->lastName;
});
// 使用「.」获取关联对象的属性
$street = \yii\helpers\ArrayHelper::getValue($users, 'address.street');
// 获取数组键值的数组键值
$versions = ['date' => '2016年12月19日', '1.0' => ['date' => '2016年12月18日']];
$value = \yii\helpers\ArrayHelper::getValue($versions, ['1.0', 'date']); // $value 输出为 2016年12月18日
|
PS:以上代码可以在这里查看并且运行。
有点太花时间,以后再补充……
使用其他 helpers
据我了解,Yii2 的 helpers 在其他 PHP 框架中也是可以使用的,但是本人没有亲测,不作保证。
类似这种 helpers 是可以在网上找到的,比方说我就找到了phpfunct/funct
当然也可以自己根据需要,收集使用,比方说根据这篇文章收集到 UUID 的生成方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
class Sequence
{
const EPOCH = 1000000000000;
const TIME_BITS = 41;
const NODE_BITS = 10;
const COUNT_BITS = 10;
private $node = 0;
private $ttl = 10;
public function __construct($node)
{
$max = $this->max(self::NODE_BITS);
if (is_int($node) === false || $node > $max || $node < 0) {
throw new \InvalidArgumentException('node');
}
$this->node = $node;
}
public function generate($time = null)
{
if ($time === null) {
$time = (int)(microtime(true) * 1000);
}
return ($this->time($time) << (self::NODE_BITS + self::COUNT_BITS)) |
($this->node << self::COUNT_BITS) |
($this->count($time));
}
public function restore($id)
{
$binary = decbin($id);
$position = -(self::NODE_BITS + self::COUNT_BITS);
return array(
'time' => bindec(substr($binary, 0, $position)) + self::EPOCH,
'node' => bindec(substr($binary, $position, - self::COUNT_BITS)),
'count' => bindec(substr($binary, - self::COUNT_BITS)),
);
}
public function setTTL($ttl)
{
$this->ttl = $ttl;
}
private function time($time)
{
$time -= self::EPOCH;
$max = $this->max(self::TIME_BITS);
if (is_int($time) === false || $time > $max || $time < 0) {
throw new \InvalidArgumentException('time');
}
return $time;
}
private function count($time)
{
$key = "seq:count:{$time}";
while (!$count = apcu_inc($key)) {
apcu_add($key, mt_rand(0, 9), $this->ttl);
}
$max = $this->max(self::COUNT_BITS);
if ($count > $max) {
throw new \UnexpectedValueException('count');
}
return $count;
}
private function max($bits)
{
return -1 ^ (-1 << $bits);
}
}
|
最后总结
编写可读性,可维护性,可扩展性的代码应该是每个开发工程师去追求的目标。程序员可以说是80%的时间都是在维护代码和阅读代码(包括别人的和自己的),所以一定要重视这些小细节。
但实际上是很多人连最基本的单一职责原则都做不到,虽然有可能他们知道这个原则,但是不实践又有什么用呢?!
微信打赏
支付宝打赏