代码简洁之二:函数只做一件事儿

函数应该做一件事。做好这件事。只做这一件事。

所以我们简化代码的一个简单方式就是不断拆分函数(Extract Method),一直拆分,拆分到不能再分出一个函数为止。

拆函数的过程就是一个概括目的、步骤,提取抽象层次动名词的过程。不要做只是解释代码的简单概括,要让函数中的语句处于一个相同抽象层次,如果是更细节的事儿,请再进一步拆分出一个函数出来。
让代码拥有自顶向下的阅读顺序。

以我之前写的一个列表显示的action(MVC框架里面的某个控制器里面的一个方法),最开始代码是这样的:

// 接收查询的参数
$minDate = trim($this->input->get_post('startDate', true));
$maxDate = trim($this->input->get_post('endDate', true));
$gameId = trim($this->input->get_post('gameId', true));
$adPositionId = trim($this->input->get_post('adPositionId', true));
$orderField = trim($this->input->get_post('orderField', true));
$order = trim($this->input->get_post('order', true));
$page = intval($this->input->get_post('page', true));
$pageSize = intval($this->input->get_post('pageSize', true));

if (!$order || !in_array($order, array('asc', 'desc'))) {
    $order = 'desc';
}

if (!$orderField || !isset($this->_fieldsMappingArray[$orderField])) {
    $searchParam['sort_by'] = 'date';
} else {
    $searchParam['sort_by'] = $this->_fieldsMappingArray[$orderField];
}

if (!$minDate) {
    $minDate = date('Y-m-d', strtotime('-1 day'));
}

if (!$maxDate) {
    $maxDate = date('Y-m-d');
}

if (strtotime($minDate)) {
    $searchParam['minDate'] = strtotime($minDate . ' 00:00:00');
}

if (strtotime($maxDate)) {
    $searchParam['maxDate'] = strtotime($maxDate . ' 23:59:59');
}
// .......一系列的判断

// 开始调用查询
$this->load->model('webgame_model');
$result = $this->webgame_model->getStatisData();
// 一系列组装数据
$this-view('users/webgameStatisList.php', $data);

这些代码写得很”质朴“,但是也很冗余,在这个function里面干了太多的事儿,杂乱无章,随着传入参数越来越多,接收部分和处理部分的代码会越来越长。虽然我不想轻易的狗带,但是容我做一个悲伤的表情,好么?
而且其实很多列表的action都是类似的,完全可以封装一些公共处理的方法,让代码抽象层次变得低一些,最终落地。

不过,首先我们得整理一下思路和步骤,把思路写越详细越好,细到不能再分出一个步骤。我借鉴《代码简洁之道》里面的建议,用TO 的那种引导方式来梳理。

1.要获取查询结果,先拿处理查询参数,然后再判断参数合法性,然后再进行查询。 (这是最大的思路步骤)
2.要处理查询参数,要先拿到传过来的参数做一些逻辑处理。 ---->getSearchFileds()
3.要判断参数合法性,要进行一系列业务逻辑的判断,最后返回错误信息,统一处理。 ----> checkParam()
4.要进行查询获取结果,要先把引入model,然后处理组装数据,最后返回。把所有组装细节都放在查询获取里面。 ----> _searchWebGameStatis()
最终代码简化如下:

// 接收处理查询参数
$params = $this->getSearchFileds($this->searchFiledOptions, $_REQUEST);

// 判断参数合法性
if ($tips = $this->checkParam()) {
    $this->message->tips($tips);
}

// 查询获取游戏统计数据
$statis = $this->_searchWebGameStatis($params);

$statis['searchs'] = $params;

// 其他导航信息组装
$this->template->cpView('users/webGameStatis', $statis);

关于getSearchFieds等的内部实现等,因为每个人的思路不同,我就不细表了。(以后单独开一篇文章细表也可以哒)但是整个简化思路就是这样。

当我们明确自己的目标和单一职责的步骤,世界都给我们让步。好的代码就是每一行都是函数的调用,而函数都只做一件事儿。读代码就像读一篇短小的文章,简单易懂,出了任何问题,责任链明确,直接去找那个function就好了。


古人没有骗我:不积跬步无以至千里。

原文地址:https://www.cnblogs.com/freephp/p/5094979.html