当前位置: 首页 > 后端技术 > PHP

PHP代码简洁之道-函数部分

时间:2023-03-29 22:31:38 PHP

函数参数不要超过两个限制一个函数的参数个数非常重要,因为这样可以让你的函数更容易测试。超过三个参数会导致参数组合过多,您必须为每个单独的参数测试很多不同的情况。没有一个参数是理想的,一个或两个参数是可以接受的,应该避免超过三个。这个非常重要。如果你有两个以上的参数,那么你的函数可能试图做太多,如果没有,你可能需要传入一个更高级别的对象作为参数。坏:functioncreateMenu($title,$body,$buttonText,$cancellable){//...}好:classMenuConfig{public$title;公共$正文;公共$buttonText;public$cancellable=false;}$config=newMenuConfig();$config->title='Foo';$config->body='Bar';$config->buttonText='Baz';$config->cancellable=true;functioncreateMenu(MenuConfig$config){//...}一个函数只做一件事这是软件工程中的一个重要原则。这将使您的代码清晰,易于理解和重用。坏:functionemailClients($clients){foreach($clientsas$client){$clientRecord=$db->find($client);如果($clientRecord->isActive()){电子邮件($client);}}}好:函数emailClients($clients){$activeClients=activeClients($clients);array_walk($activeClients,'email');}functionactiveClients($clients){returnarray_filter($clients,'isClientActive');}functionisClientActive($client){$clientRecord=$db->find($client);}return$clientRecord->isActive();}函数名必须能够解释它的作用Bad:classEmail{//...publicfunctionhandle(){mail($this->to,$this->subject,$this->正文);}}$message=newEmail(...);//这是什么?消息句柄?还想写文件?(读者提问)$message->handle();Good:classEmail{//...publicfunctionsend(){mail($this->to,$this->subject,$this->body);}}$message=newEmail(...);//一目了然$message->send();函数应该只做一层抽象当你有多层抽象时,你的函数已经做的太多了。将这些功能拆分出来可以使代码更易于重用并且更易于测试。错误:functionparseBetterJSAlternative($code){$regexes=[//...];$statements=explode('',$code);$代币=[];foreach($regexesas$regex){foreach($regexesas$regex){foreach($statementsas$statement){//...}}$ast=[];foreach($tokensas$token){//lex...}foreach($astas$node){//parse...}}也很糟糕:我们将一些工作移出了函数,但是parseBetterJSAlternative()功能仍然太复杂,无法测试。functiontokenize($code){$regexes=[//...];$statements=explode('',$code);$代币=[];foreach($regexesas$regex){foreach($statementsas$statement){$tokens[]=/*...*/;}}返回$tokens;}functionlexer($tokens){$ast=[];foreach($tokensas$token){$ast[]=/*...*/;}return$ast;}functionparseBetterJSAlternative($code){$tokens=tokenize($code);$ast=词法分析器($tokens);foreach($astas$node){//parse...}}Good:最好的解决方案是移去parseBetterJSAlternative函数的依赖classTokenizer{publicfunctiontokenize($code){$regexes=[//..];$statements=explode('',$code);$代币=[];foreach($regexesas$regex){foreach($statementsas$statement){$tokens[]=/*...*/;}}返回$tokens;}}classLexer{公共函数lexify($tokens){$ast=[];foreach($tokensas$token){$ast[]=/*...*/;}返回$ast;}}类BetterJSAlternative{私人$tokenizer;私人$词法分析器;公共函数__construct(Tokenizer$tokenizer,Lexer$lexer){$this->tokenizer=$tokenizer;$this->lexer=$lexer;}publicfunctionparse($code){$tokens=$this->tokenizer->tokenize($code);$ast=$this->lexer->lexify($tokens);foreach($astas$node){//parse...}}}Donotusetokensasfunctionargumentswhen当你在函数中使用标志作为参数时,你的函数不只做一件事,这是相反的遵循每个函数只做我们之前说过的一件事的原则,所以不要使用标志作为函数参数错误:functioncreateFile($name,$temp=false){if($temp){touch('./temp/'.$name);}else{touch($name);}}Good:functioncreateFile($name){touch($name);}functioncreateTempFile($name){touch('./temp/'.$name);}避免副作用value并返回一个值或多个值”,那么这个函数可能会产生副作用,可能会被意外写入文件、修改全局变量或向陌生人汇款。现在假设你真的想在你的函数中做一些可能有副作用的事情。比如你要写一个文件,你需要做的是把写文件的操作集中在一个地方,而不是在几个函数或者类中对同一个文件进行操作,实现一个服务(函数或者类)来操作它。而且只有一个。关键是要能够避免常见的陷阱:比如在没有结构的对象之间共享状态,使用可以写入任何值的可变数据类型,不关注可能有副作用的操作。如果你能做到这一点,你会比大多数程序员更快乐。Bad://Globalvariablereferencedbyfollowingfunction.//如果我们有另一个函数使用这个名称,现在它是一个数组,它可能会破坏它。$name='RyanMcDermott';functionsplitIntoFirstAndLastName(){global$name;$name=explode('',$name);}splitIntoFirstAndLastName();var_dump($name);//['Ryan','McDermott'];Good:functionsplitIntoFirstAndLastName($name){returnexplode('',$name);}$name='RyanMcDermott';$newName=splitIntoFirstAndLastName($name);var_dump($名称);//'RyanMcDermott';var_dump($newName);//['瑞安','麦克德莫特'];不要修改全局变量污染全局变量在许多编程语言中是一种不好的做法,因为你的库可能会与另一个库发生冲突,但是你的库的用户不知道,直到在生产环境中发生了异常。让我们考虑一个例子:如果你想得到配置数组怎么办?您可以编写像config()这样的全局函数,但它可能会与另一个试图做同样事情的库发生冲突。坏:functionconfig(){return['foo'=>'bar',]}好:classConfiguration{private$configuration=[];公共函数__construct(array$configuration){$this->configuration=$configuration;}publicfunctionget($key){returnisset($this->configuration[$key])?$this->配置[$键]:空;}}$configuration=newConfiguration(['foo'=>'bar',]);避免条件判断人们会问“没有if语句怎么办?”答案是在很多情况下,可以使用多态来达到同样的效果。那么这样做有什么好处呢,还是那句话:“Afunctionshouldonlydoonething”,当你的类或函数中有if语句时,你的函数不会只做一件事。错误:飞机类{//...publicfunctiongetCruisingAltitude(){switch($this->type){case'777':return$this->getMaxAltitude()-$this->getPassengerCount();案例“空军一号”:返回$this->getMaxAltitude();case'Cessna':返回$this->getMaxAltitude()-$this->getFuelExpenditure();}}}Good:interfaceAirplane{//...publicfunctiongetCruisingAltitude();}classBoeing777implementsAirplane{//...publicfunctiongetCruisingAltitude(){返回$this->getMaxAltitude()-$this->getPassengerCount();}}classAirForceOneimplementsAirplane{//...publicfunctiongetCruisingAltitude(){return$this->getMaxAltitude();}}classCessnaimplementsAirplane{//...publicfunctiongetCruisingAltitude(){返回$this->getMaxAltitude()-$this->getFuel支出();}}更多好文,关注公众号获取

猜你喜欢