php方法的参数是数组吗,参数用一个数组还是分开几个

常用知识 - 参数用一个数组还是分开几个 ¶

作者:KK

发表日期:2016.8.23

要点速读 ¶就算定义成一个$params参数,函数增加了新key的处理,那调用的地方传的参数没新key也是要编写新key的赋值代码

不定义成一个$params的话除了调整函数的处理,还要调整传参的代码,也是要改两处

该不该将参数定义成数组,要看这些参数是不是同一个类型的集合,是的话就从概念上将它定义为一个整体,就用数组,不能参与到这个整体中的就单独定义

问题的起源 ¶

做了一两年的程序员通常都会遇到这样情况:原来有个获取某时间段新用户列表的函数function getNewUserList($startTime, $endTime),后来因为需求说要支持获取的人数,导致要加多个参数,变成了function getNewUserList($startTime, $endTime, $nums),不止定义函数的地方改了,而且到处的调用代码都要找出来修改,导致有改漏的情况,调用出错了

于是出现了数组参数的设计 ¶

有一部分人开始学聪明了,他直接这样设计函数:

function getNewUserList($where){}

这个$where是一个含有startTime、endTime和nums下标的数组,可是我个人觉得这还是有问题的

调用的地方还是要改的

虽然函数的调用代码不用改,依然是getNewUserList($where)这样调用,可是调用的地方的$where也不一定具备新元素的nums,于是还是有一部分调用的代码附近要做$where['nums'] = $limitNums这样的赋值处理,不然函数收到的$where根本不会有新数据嘛对不对

11992a81077747b4dac6a0ad9c69c035.gif

所以要变需求时,除了变动函数对key值的处理逻辑,还有一部分调用代码附近的逻辑要改,补充赋值才行

要么改函数调用参数表,要么改附近的赋值,其实这成本还是一样

产生了对命名和阅读的纠结,代码好像不像从前那么美了

不仅如此,这时候导致函数也不是很限阅读的样子,无论是定义的地方还是调用的地方都不好阅读。

你看嘛参数命名为$where,没错如果说在sql里where start_time > xx and end_time < yy这逻辑肯定说得过去,是where部分,可是限制数量nums却不属于条件,而是对筛选结果的进一步挑选,在sql里就是limit呢

不说限制数量吧,以后需求再说要排序控制,分组控制,这全部扔在$where里那你就会开始觉得这个参数不叫where而统一叫params了对吧?

一旦这样发展下来,你就会慢慢嗅到一股怪味道:咋发现人家外面的程序不带这样设计的,你就偏偏往这条路子钻下去呢?你又有没有观察过成员们在调用函数方面的编程苦恼?

至少,外界没有一个流行开来的开源程序和框架用一个$params的设计,我也从没听说哪个大牛认可这个设计,除非在特定应用场合,比如WebService

放心讲这么多话不是说你犯了什么十恶不赦的大罪,只是在分析后果,其实我曾经也苦恼这个参数设计问题,差点陷入了这个深渊,但喜欢探索的我在各大论坛不断发帖求知+请大神吃饭交流,最终解除了这个疑惑

同类的参数集合设计成数组,不同类的单独一个 ¶

这是我在网上找到的答案,也是一些有10多年经验的老程序员指点的经验

关于阅读的问题

以上面说的function getNewUserList($startTime, $endTime, $nums)为例子,其实startTime和endTime是同类参数来的,它们都表达了一个时间,并且作用是在查询条件上,所以我们可以将它定义为一个整体,这个整体所扮演的角色就是条件,于是我们可以说条件是会存在很多种的,此时条件既然是一个整体,我们可以用数组表达:

function getNewUserList($where, $nums)

这样阅读也挺顺的

关于调整的问题

将同类参数定义成一个整体后,可以解决一部分调整的问题,当需求说“除了时间以外要增加一个条件,就是性别”,那没事,函数里增加对$where['sex']的处理,并且调用函数的地方给$where赋值sex

可是按照我这样说其实也是会遇到调整问题,比如需求又要分组了咋办。。。

但再往深一层想:一个项目假设有20个类,每个类平均有10个方法,难道这20*10=200个方法都要重构?

按照经验,3年时间内要调整参数位的函数/方法超不过50个左右,有的甚至就20个以内,除非设计这个函数+代码审核人员的水平都比较差,否则函数的返修率通常都是很低的,不然你看PHP的函数从PHP4到PHP7期间,有多少函数说要增加参数位,更换参数位的,设计这些参数的人都有丰富的编程经验,绝大部分函数都已经尽可能将返修率降到最低了,我们应该关注的是降低返修率这个能力,这样才能让我们更加进步,设计函数时更加小心

好了最终还是有一部分要返修的,咋办?修就修,你想哦,要是把全部参数揉合成一个$params数组,光是它带来的代码阅读和维护成本,都比你分开一个个参数重构麻烦,至少它根本不能做到只修改函数处理,不用修改外部调用代码的境界,因为还是要为新的key赋值的嘛

阅读问题

其实无论是只用一个$params参数还是说分开参数(分开后,个别参数也可能是数组),都会有阅读问题,初次接触这个函数的新成员会疑惑地思考:”我怎么知道这个数组参数还能不能添加更多key做更多控制,或者减少某个key也能正常工作?“

这其实要靠文档,比如先在定义函数的地方编写phpdoc注释(参考下面例子):

/**

* 获取新注册的用户列表

* @param array $where 条件

* 必须包含`startTime`和`endTime`,其它可选,根据数据表的实际字段增加就可以

* @param int $nums 要获取的用户个数

*/

function getNewUserList($where, $nums){}

最近的案例 ¶

最近我们项目有个计算两个用户间距离的方法设计,负责这个事的是一位1年经验的程序员,他的设计是这样的:

/**

* 获取两个用户的距离

* @param float $user1X 用户1的经度

* @param float $user1Y 用户1的纬度

* @param float $user2X 用户2的经度

* @param float $user2Y 用户2的纬度

* @return int 距离(米)

*/

function getDistance($user1X, $user1Y, $user2X, $user2Y){}

以上4个参数分别代表用户1的经纬度(X和Y)和用户2的经纬度

我指导他调整这样的:

/**

* 获取两个坐标之间的距离

* @param array $position1 第一个坐标

* 必须包含`x`和`y`

* @param array $position2 第二个坐标

* 必须包含`x`和`y`

* @return int 距离(米)

*/

function getDistance($position1, $position2){}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值