很幸运,我又给自己创造了一个bug。
就是原本一直正常的功能,突然被用户4月6号发现了一个bug:
设备一直全部都是运行状态,有一台设备却调皮地“灰“头土脸了。
但奇妙的是,我压根儿就不知道自己是怎么创造出这个bug的。
费了一番功夫,最终找出问题出在下面这段代码上:
代码中的问题,我将在文末揭晓。如果你有兴趣找bug的话,可以先瞅瞅。
本文是翟码农个人博客PHP分类下的原创文章,转载请注明出处:http://www.zhai14.com/blog/why-I-made-a-bug-again-1.html,我怎么又给自己创造了一个bug系列(一)
不过本文的重点,我不是要跟大家分享我怎么找到bug的,而是和大家分享:
我是怎么不知不觉给自己创造了bug?
经过日志追溯,发现2023年3月3号本人改动了上面那段代码。改动之前的代码如下所示:
//批量获取设备当前数据 public function getMultiDeviceCurrentInfo($arrDeviceId){ $model = new EquipmentMongo(); return $model->getCurrentInfoByDeviceIds($arrDeviceId); } //批量获取设备当前状态 public function getMultiDeviceCurrentStatus($arrDeviceId) { $deviceInfo = $this->getMultiDeviceCurrentInfo($arrDeviceId); $newList = []; foreach($deviceInfo as $item){ if(isset($item['status']) && false === strpos($item['device_id'], 'GTRY_')){ //电表采集status暂时有误,用connection_status $status = $item['status']; }else{ $status = $item['connection_status']; } $statusInfo = $this->getRunStatus($status); //电这块没有status属性数据 $newList[] = array( 'device_id' => $item['device_id'], 'status_run_text' => $statusInfo['status_run_text'], 'status_run' => $statusInfo['status_run'] ); } //模拟数据 foreach($arrDeviceId as $deviceId){ if( in_array($deviceId, array('SH-PD-01', 'SH-PD2-01', '729-11SY', 'SH-PD-099'))){ $item = []; $item['device_id'] = $deviceId; $item['status_run_text'] = 'run'; $item['status_run'] = 1; $newList[] = $item; } } return array_column($newList, 'status_run_text', 'device_id'); }
改动之后如下所示:
//批量获取设备当前数据 public function getMultiDeviceCurrentInfo($arrDeviceId){ $model = new EquipmentMongo(); $list = $model->getCurrentInfoByDeviceIds($arrDeviceId); $currentTime = strtotime(DateUtil::getCurrentDatetime()); foreach($list as &$item){ if(isset($item['status']) && false === strpos($item['device_id'], 'GTRY_')){ if($currentTime - strtotime($item['time']) > 300){ //超过5分钟没更新数据,暂认为数据采集中断 $status = "interrupt"; }else{ $status = $item['status']; } }else{ //电表采集status暂时有误,用connection_status $status = $item['connection_status']; } $statusInfo = $this->getRunStatus($status); $item['status_run_text'] = $statusInfo['status_run_text']; $item['status_run'] = $statusInfo['status_run']; } //模拟数据 foreach($arrDeviceId as $deviceId){ if( in_array($deviceId, array('SH-PD-01', 'SH-PD2-01', '729-11SY', 'SH-PD-099'))){ $item = []; $item['device_id'] = $deviceId; $item['status_run_text'] = 'run'; $item['status_run'] = 1; $list[] = $item; } } return $list; } //批量获取设备当前状态 public function getMultiDeviceCurrentStatus($arrDeviceId) { $deviceInfo = $this->getMultiDeviceCurrentInfo($arrDeviceId); return array_column($deviceInfo, 'status_run_text', 'device_id'); }
可以看出,正是我将设备状态status_run这个数据,转移到getMultiDeviceCurrentInfo这个方法里,然后一不小心,就不知不觉给自己埋藏了bug。
我的bug就是:
第二个foreach中重置$item变量,会将第一个foreach中最后一个$item元素给重置为空,因为恰巧$item用了引用,所以最终$list里就少了一台设备数据
这也就是为何用户从界面上发现有台设备状态为离线(程序给了默认值,如果不是运行状态,就默认为离线)。
本人貌似犯了好几次这种白白耽误自己功夫的错误,今天特记之,希望日后能多加注意:
写多个foreach循环遍历时,尽量用不同命名的$item变量
除非你特意需要这么做,例如:我要给自己的明天任务留一个bug。