良好的语义表达是团队合作高效迭代的润滑剂,良好的语义表达是在线未知代码排查的指南针。这篇文章很长,如果你“偷懒”,我来告诉你(更多详情在直播中)播放地址看完还不满意?学习使你快乐?还想学?上车,不要让别人看不懂你的代码,一周后别人可能就是你。永远用“如果你写的代码失败了,陌生人接管你的代码来处理这个bug需要多长时间”来监控自己。日常生活中,刻意改善自己的语义表达,有益无害。那么我们应该做哪些细节才能很好地表达语义呢?以下代码均为本人艺术创作,不属于任何实际项目命名案例1functiongetGoods($query,$shopId){$goodsId=Goods::add($query["uid"],$query["name"]);returnShop::add($goodsId,$shopId);}classGoods{publicstaticfunctionadd($uid,$name){$id=mt_rand(1,100000);return$id;}}classShop{publicstaticfunctionadd($goodsId,$shopId){$id=mt_rand(1,100000);return$id;}}Case2functiongetUserInfo($teamId,$youId=[]){}如果只有这个函数名和参数名,谁能猜到参数的含义?案例3classDb{/***@paramstring$table数据库表名*@paramarray$data新增数据**@returnint新增主键*/publicstaticfunctioninsert(string$table,array$data){$id=mt_rand(1,1000);return$id;}}classViewLogStore{private$table="view_log";functionsetHistory($data){Db::insert($this->table,$data);}}案例4如果有这些classesclassWechatUserModel{业务代码中的}classWechatGroupModel{}classWechatMessageModel{}和我们查询数据库,发现我们根据业务代码查找对应的表非常不方便,而且当其他人接手我们的项目时,他们也会感到困惑。也就是说,这可能是三个人的三个迭代开发导致的,所以没有参考对方的命名规则。灵魂拷问笔记命名完了,下面说说笔记。评论里还学到了什么?你在开玩笑吧?一个数组对象成员,你知道怎么写吗?你知道怎么写类的魔术方法调用的注释吗?对象数组/***@varAds[]*/public$adsList=[];$blocks=[];/**@var$blocksBlock[]**/@method的使用/***@linkhttp://manual.phpdoc.org/HTMLframesConverter/default/**@methodstaticintsearch(string$query,$limit=10,$offset=0)*/classSearchServiceProxy{publicstaticfunction__callStatic($method,$arguments){if(!method_exists("SearchService",$method)){thrownew\LogicException(__CLASS__."::".$method."notfound");}try{$data=call_user_func_array(["SearchService",$method],$arguments);}catch(\Exception$e){error_log($e->getMessage());returnfalse;}return$data;}}@deprecateduseclassSearchService{/***@paramstring$query*@paramint$limit*@paramint$offset**@returnarray*@deprecated*/publicstaticfunctionsearch(string$query,$limit=10,$offset=0){返回[["id"=>1,"aaa"],["id"=>2,"bbb"],];}}NotesOtherNotes,方法名更新,方法的函数业务注释不更新;复制别人的代码,把@author字母资料也抄了,写错了,只能怪别人评论了。更多参考http://manual.phpdoc.org/HTML...功能与方法案例1先说明一下,糟糕的代码并不妨碍它成为一款优秀的软件。PHP和MySQL中有很多错误代码。我在一个开源软件里找到了代码,功能很抢手,但是这个方法内容太多,我标记了一些不足之处。案例2上面以我为例。还记得下面这张图吗?优化方案1classArrayUtils{publicstaticfunctionfetch($arr,$keys,$setNull=false){$ret=array();foreach($keysas$key){if($setNull){$ret[$key]=$arr[$key];}else{isset($arr[$key])&&$ret[$key]=$arr[$key];}}return$ret;}}classViewLogStore{private$table="view_log";functionrecord($data){$fields=array('uid','url','referer','created_time');$data=ArrayUtils::fetch($data,$fields);Db::insert($this->table,$data);}}优化方案2classDb{/***@paramstring$table数据库表名*@paramEntity$data新建对象**@returnint新主键*/publicstaticfunctioninsert(string$table,Entity$data){$array=$data->toArray();var_export($array);//test$id=mt_rand(1,1000);return$id;}}classArrayUtils{/***对于成员都是私有属性的对象**@param$obj*@parambool$removeNull删除空值*@parambool$camelCase**@returnarray*/publicstaticfunctionObj2Array($obj,$removeNull=true,$camelCase=true){$reflect=new\ReflectionClass($obj);$props=$reflect->getProperties(\ReflectionProperty::IS_PUBLIC|\ReflectionProperty::IS_PRIVATE|\ReflectionProperty::IS_PROTECTED);$array=[];foreach($propsas$prop){$prop->setAccessible(true);$key=$prop->getName();//如果不是驼峰命名方式,就把对象里面的createTime转成create_timeif(!$camelCase){$key=preg_replace_callback("/[A-Z]/",function($matches){return"_".strtolower($matches[0]);},$key);$key=ltrim($key,"_");}$value=$prop->getValue($obj);if($removeNull==true&&$value===null){继续;}如果(is_object($value)){$value=self::Obj2Array($value);}$array[$key]=$value;}return$array;}}classEntity{publicfunctiontoArray(){returnArrayUtils::Obj2Array($this);}}classViewLogEntityextendsEntity{/***@varint*/private$uid;/***@varstring*/private$url;/***@varstring*/private$referer;/***@varstring*/private$createdTime;/***@paramint$uid*/publicfunctionsetUid(int$uid){$this->uid=$uid;}/***@paramstring$url*/publicfunctionsetUrl(string$url){$this->url=$url;}/***@paramstring$referer*/publicfunctionsetReferer(string$referer){$this->referer=$referer;}/***@paramstring$createdTime*/publicfunctionsetCreatedTime(string$createdTime){$this->createdTime=$createdTime;}}classViewLogStore{private$table="view_log";functionrecord(ViewLogEntity$viewLogEntity){Db::insert($this->table,$viewLogEntity);}}//测试$viewLogEntity=newViewLogEntity();$viewLogEntity->setUid(1);$viewLogEntity->setReferer("https://mengkang.net");$viewLogEntity->setUrl("https://segmentfault.com/l/1500000018225727");$viewLogEntity->setCreatedTime(date("Y-m-dH:i:s",time()));$viewLogStore=newViewLogStore();$viewLogStore->record($viewLogEntity);案例3这还是函数吗?(不只是语言,属于错误)/***@methodmixedfetchList(string$sql,array$argv);*/classModel{publicfunction__construct($table){}}functiongetUserList($startId,$lastId,$limit=100){if($lastId>0){$startId=$lastId;}$sql="select*from`user`whereid>?orderbyidasclimit?,?";$model=newModel('user');return$model->fetchList($sql,[intval($startId),intval($limit)]);}$startId和$lastId两个参数重复case4最小化参数引用functionbad($input1,$input2,&$input3){//...logic$input3="xxx";returntrue;}Case5参数类型明确,返回值类型明确,不要出现混用,我直接拿官方函数举例,对权威持怀疑态度。纯属个人意见。案例6在上面的例子中,你会发现这个addUser并不是写成一个函数(方法)而是写成一个远程api接口。而右边的代码中,每次使用的时候都需要用is_array来判断。这是一种非常不友好的语义表达。PHP、Java等高级语言都有异常,我们要好好利用异常。良好的语义表达是团队合作高效迭代的润滑剂,良好的语义表达是排查线上未知代码问题的指南针。这篇博客就到这里了,不知道大家有没有收获呢?
