ARTS 是 左耳朵耗子 提出来的一个打卡任务。每周一个 Algorithm,Review 一篇英文文章,总结一个工作中的技术 Tip,以及 Share 一个传递价值观的东西!我希望这个事可以给大家得到相应的算法、代码、技术和影响力的训练。
这是我的第十七周打卡。
🤖 Algorithm
📖 Review
这篇文章虽然是一篇很老的文章,但对于我来说是非常有价值的。因为在公司的 php 遗留系统中,我发现太多的乱用references
的情况,而开发人员对此毫无感觉。
文章的作者 Johannes 是 php 的发布经理,它提到一点我非常赞同:
Now a third thing which is done with references is bad API design by returning via reference parameters.
也就是说通过引用来完成返回值是一个非常不好的API设计。为什么这么说,比如我们的一个函数如下:
function check_project_exist($project_id , &$project_info) {
$project_info = $this->get_from_db($project_id);
return !empty ($project_info);
}
检查项目是否存在,传入一个project_id
和project_info
,而project_info
的作用仅仅是为了得到该返回值。
然后调用方需要先初始化一个project_info
才可以调用该方法
$project_info = [];
if ($this->check_project_exist($project_id, $project_info)) {
return;
}
//后面的分支需要用到$project_info
这种方式真的很糟糕,首先一个函数应该只做一件事情。check_project_exist
应该做的就是检查项目是否存在,返回检查的结果,根据方法的命名,它应该是返回一个布尔值。
但是这个方法做了另外一件事情,将project_info
给改变了,这是我们期望的结果吗?在复杂的程序中,如果到处都是这种代码,我们无法追踪一个变量到底是在哪里被修改了,对程序的理解变得及其困难。
如果我们仅仅是为了返回不同的结果,我们完全不需要通过这种方式。比如 Elixir 语言是这样实现的:
{:ok, project_info}
{:error, "错误信息"}
通过返回一个元组,元组的第一个元素用一个原子来表示操作是否成功,这种方式规范了方法的返回值。
在 php 中,我们也可以用一个对象或数组来实现,所以这个方法应该叫get_project
,因为我们本来就是要得到它然后进行一些操作,调用方就很简单了。而且整个流程都是很顺畅的,所见即所得。
function get_project(project_id){
$project_info = $this->get_from_db($project_id);
if(empty($project_info)){
return ["error", "错误信息"]
}
return ["success", $project_info]
}
💡 Tip
这篇文章是 Elixir 的 Protocols(协议) 的学习总结。协议是在 Elixir 中实现多态性的机制, 任何数据类型都可以调度协议,只要它实现协议即可。