编程注意规范

1.命名非常重要

2.适当的使用注释

3.变量需要初始化

4.1==$a

5.防御式编程

6.可控的环境参数

7.PHP结束标记

8.if的使用技巧之“给定初始值”

9.if的使用技巧之“用"&&" 替换 if

10.if的使用技巧之“用三元运算符替换if

11.if的使用技巧之“去掉多此一举的if

12.表驱动法

13.使用更精悍短小的代码

14.避免使用幻数

15.中间结果赋值给变量

16.复杂的逻辑表达式做成布尔函数

17.永远不要复制粘贴雷同的代码

18.备份源代码文件

一·命名非常重要

对代码名称进行有意义命名,而不是随意使用字母或无意义或容易产生奇异的英文进行命名,例如:

function a($a,$b){
   if(is_numeric($a)){
      return intval($a);
   }
   $c=explode(‘#’,$a);
   if(isset($c[$b])){
      return intval($c[$b]);
   }else{
      return intval($c[count($c)-1]);
   }
}

这段代码的命名没有意义,直接看代码没有办法知道这个方法具体要做什么,更不知道需要传入的参数有哪些,分别是什么意思,而且当代码长度变长之后变量数量增多,自己容易记混变量名意义,给自己编码造成很大的错误概率。另外在过一段时间后再看代码无法记起当时所想,不利于后期维护。如果代码和他人交接,想想你和一个编码命名毫无意义的人交接的情景吧,好吧,你肯定想到了,你的无意义的命名肯定会让你的代码被交接人维护时候问候你无数次的。

function get_int_whit_vip($str,$vip){

        if(is_numeric($str)){

            return intval($str);

        }

        $str_arr = explode('#',$str);

        if(isset($str_arr[$vip])){

            return intval($str_arr[$vip]);

        }else{

            return intval($str_arr[count($str_arr)-1]);

        }

}

 

这段代码和刚刚的代码是相同的效果,但是命名会让你很容易知道这是一个根据vip等级获得一个次数数字的方法,传入的参数是一个字符串和vip等级,字符串格式为#分割的数字,也有可能就是一个单一的数字。这样子很容易就能看出来这个代码的作用。日后维护和自己编写的时候都会比较容易处理。

命名注意事项:1.有实际意义。2.使用统一编码规范,是$str_arr下划线风格还是$strArr驼峰风格,项目中保持编码的一直规范性。3.不使用拼音作为名称,使用有意义的英文。4.不使用语言的关键字,虽然在php中类似于$error_log,$count这样的命名是支持的,但是不要使用。

 

二·适当的使用注释

注释加的要合理,最好的注释就是代码本身,通过使用有意义的命名,使代码自身可读性增强,在逻辑非常复杂难以理解的地方加上注释说明来达到可以通过注释了解算法设计的目的。在函数开始处增加注释信息,使函数可以只是看注释信息就知道函数作用,方便调用。在类的功能和使用方法上增加注释,写清用处和维护人,以方便使用以及出问题后可以快速找到对应的维护人信息,对于一个文件多人维护的情况,方法注释就很重要了,最好方法注释上可以写上这个方法的维护人,以方便出问题时修改。但是过多的注释会使代码混乱,增加代码长度,所以不建议很容易读懂的地方增加注释信息。

 

三·变量需要初始化

php中程序默认是允许变量不进行声明初始化而直接使用的,但是这样会造成一定的问题。例如:

$page=$_GET[‘page’];

if(1==$page){

       $user_page = $page;

}

echo $user_page;

 

这段代码在$page不等于1的情况下会找不到$user_page的值而出现运行的异常,如进行声明则:

 

page=$_GET[‘page’];

$user_page = 0 ;

if(1==$page){

     $user_page = $page;

}

echo $user_page;

 

无论是否等于1都会有一个很确定的输出。类似的例子还有很多。另外例如下面这种情况:

$input_arr = array(array('a'=>1,'b'=>2,'c'=>3),array('a'=>2,'b'=>3,'d'=>5),array('b'=>9,'c'=>3));

foreach($input_arr as $key=>$val){

    foreach($val as $k=>$v){

        $output[$k] = $v;

    }

    var_dump($output);

}


 

在这个例子中我们本来是相输出每一个子集的结果,即理想结果应该是:

array (size=3)

  'a' => int 1

  'b' => int 2

  'c' => int 3

 

array (size=3)

  'a' => int 2

  'b' => int 3

  'd' => int 5

 

array (size=2)

  'b' => int 9

  'c' => int 3

 

但是这个运行的结果是:

array (size=3)

  'a' => int 1

  'b' => int 2

  'c' => int 3

 

array (size=4)

  'a' => int 2

  'b' => int 3

  'c' => int 3

  'd' => int 5

 

array (size=4)

  'a' => int 2

  'b' => int 9

  'c' => int 3

  'd' => int 5

原因是每次进行循环之前没有进行初始化,使得数据产生了累加,结果数值错误,得到理想结果的代码如下:

$input_arr = array(array('a'=>1,'b'=>2,'c'=>3),array('a'=>2,'b'=>3,'d'=>5),array('b'=>9,'c'=>3));

foreach($input_arr as $key=>$val){

    $output=array();

    foreach($val as $k=>$v){

        $output[$k] = $v;

    }

    var_dump($output);

}


 

所以每次使用变量之前对变量进行初始化声明是很重要的。很多时候代码很长在前面直接使用的变量在后面没有初始化声明就不注意再次使用,造成数据混乱的情况,在开发中复现和调试修改都是非常麻烦的事情。

 

四·1==$a

常量写在变量前面,这一点和很多人平时的编码习惯有比较大的区别,正常的思维方式是某一个变量值等于某一个常量值时候进行什么操作,所以很容易就会出现如下写法:

$page = mt_rand(0,1);

if($page ==1){

      echo ‘Hello’;

}else{

       echo ‘page error’;

}

 

但是如上代码不注意就回写成如下代码:

$page = mt_rand(0,1);

if($page =1){

      echo ‘Hello’;

}else{

       echo ‘page error’;

}

 

这个时候有些编译器会警告你if那行有问题,但是有很多编译器是不会警告的,在这种情况下永远输出的都是’Hello’,这种错误在编译的时候是不会报错的,所以查起来难度也是很大的,毕竟只是一个===的区别。但是如下这种写法的话在编译的时候编译器直接就会报错,变异不通过直接定位进行修改,也就不会有后面的编码麻烦了。

$page = mt_rand(0,1);

if(1=$page ){

      echo ‘Hello’;

}else{

      echo ‘page error’;

}

所以在编写程序的时候将常量放在变量的前面可以避免很多不必要的错误,减少时间开支。

 

五·防御式编程

在编程中,很多数据是通过外界获取的数据,如果不加以验证就直接使用的话可能会造成错误,不要说客户端是你们自己的,客户端上写的数据直接传过来的就没有问题,或者是说前端js已经验证过的数据就不用验证了,可以相信的拿着使用,这样的话一旦数据被人截取篡改或者是数据不完整就会导致整个程序的错误,甚至有可能直接就会被别人改掉数据库信息。所以不要相信任何一个外界获取的数据,包括在数据库中取得的数据。所有数据在使用前都要进行必要的数据验证,比如isset(),is_numeric(),is_array()等这类的验证,对程序的运行效率消耗较小,但是可以很好的保护程序的健壮性。对于正则表达式而言,可以使用简单验证的情况下个人不太建议使用正则匹配,虽然正则非常厉害,但是会对程序的运行资源有一个较大的开销,关于正则的深入研究,将会有另外一篇文章来描述。对于防御性编程而言,合理验证,保证程序的健壮性但是不要过度验证使得程序臃肿,运行效率低下。

 

六·可控的环境参数

在很多时候我们所编写的程序会跑在什么样的环境下我们不得而知,有时我们写的一些方法所需要的一些环境参数是我们不可提前预知的,在这种情况下可以自己使用显示的声明方式来对环境参数进行声明控制。对于路径最好是在程序的访问入口文件处通过define('ROOT',dirname(__FILE__));这种方式来获得项目的绝对路径来进行文件操作,所有的给予文件的操作使用绝对路径方式可以避免多个文件对一个文件或者一个文件对多个文件的时候的路径问题。对于一些对于环境参数有要求的模块自己给定一个系统默认值,另外自定义错误警报的级别也可以减少因为服务器未定义某些级别的错误造成的日志缺失查找程序错误的时候的困难。

对于自己所运行的服务器是在自己完全可控的情况,个人建议只使用入口文件定义绝对路径,另外两项直接自己修改服务器的默认属性,这样可以一定量的减少程序的开销。

 

七·PHP结束标记

对于php的结束标记是否需要写出的这个问题,如果是纯php代码,最后的结束标记最好不要写,因为当其余的文件对其进行引入的时候有可能会因为结束标记之后的部分有某些字符而造成不可预知的错误。

 

八·if的使用技巧之“给定初始值”

代码在进行if判定之前给定一个有意义的初始值,这个值可以使else时候的值,这样的话可以减少一定的代码量,使代码简洁,另外也可以在一些情况下减少一次赋值操作,提高一定的效率。例如:

$long = 0;

$rand = mt_rand(0,5);

if($rand>3){

      $long=5;

}else{

      $long=1;

}

则可写成:
$long=1;

$rand = mt_rand(0,5);

if($rand>3){

      $long=5;

}

 

九·if的使用技巧之“用"&&" 替换 if

上面的代码可以使用&&来进一步减少代码量,例如:

$long=1;

$rand = mt_rand(0,5);

$rand>3 && $long=5;


 

这样代码中直接省略了if的操作,节约了操作步骤,同时减少了代码量。但是这种写法在以下的情况下要注意:

$num_1 = 1;

$num_2 = 1;

$rand = mt_rand(0,5);

$rand>3 && $num_1=5 && $num_2=7;

var_dump($num_1);

var_dump($num_2);


 

这段代码当rand>3的时候运行会出现问题,其运行结果会如下:

boolean true

int 7

会出现这个原因的问题主要是因为运算符的优先级问题,在程序中=的优先级低于&&且是从右往左的,所以当rand>3的时候真正的运行顺序会是如下这样:

$num_2=7  //$num_2=7,所以$num_2的值是正确的

5&&$num_2  // 即5&&2 ,结果为true

$num_1 = (5&&$num_2=7); //即 $num_1 =true,所以$num_1的值错误为了true

 

如果想用上面这种形式实现连续赋值操作的话,就要使用()来进行分割,即如下代码:

$rand>3 && ($num_1=5) && ($num_2=7);

 

另外如果使用&&||配合的话,可以实现伪原子性操作,例如(((a=1)&&(b=2)) || (a=0)&&(b=0));不过这种操作还是推荐使用if语句去完成,因为如果后半截在恢复时某一个出了问题会比较麻烦,虽然理论上前面可以修改成功的变量后面也可以成功,不过还是有一定的危险性导致部分无法恢复。

 

十·if的使用技巧之“用三元运算符替换if

使用三元运算符和使用&&的目的都是一样的,减少代码量,这里就不再过多陈述。

 

十一·if的使用技巧之“去掉多此一举的if

很多时候我们会写出如下的代码:

if(1==$a){

      return true;

}else{

      return false;

}


其实这种写法完全没有任何的意义,可以直接简化为:

return (1==$a);

 

对于这种本身返回值就是bool值的数据再次进行判断返回bool值完全是没有意义的,如果你想取反操作,例如:

if(1==$a){

     return false;

}else{

      return true;

}


 

也完全可以直接写成:

return !(1==$a);

来完成。

 

十二·表驱动法

对于很多时候我们需要用N多个ifelseifelseif...来达到连续判定完后取出某个值的效果,例如:

$data = array();

if(‘login’==$type){

     $data = array(‘uid’=>1,’pwd’=>123);

}elseif(‘register’==$type){

     $data = array(‘username’=>’max’,’new_pwd’=>432);

}elseif(‘put_info’==$type){

     $data = array(‘something’=>’’Hello);

}


 

向上面这样的连续判断效率较低,有些人会说改成switch case 的写法,效率会高过if,但是依然是十分的繁琐,如下:

$data = array();

switch($type){

    case ‘login’ :

          $data = array(‘uid’=>1,’pwd’=>123);

          break;

    case ‘register’:

          $data = array(‘username’=>’max’,’new_pwd’=>432);

          break;

    case ‘put_info’:

          $data = array(‘something’=>’’Hello);

          break;
    
}

 

但是这样写依然会比较麻烦,且运行效率也不会太高,当数据量较大的时候速度会比较慢,如上程序改成如下样式:

$data_arr = array(‘login’=>aarray(‘uid’=>1,’pwd’=>123),‘register’=>array(‘username’=>’max’,’new_pwd’=>432),‘put_info’=>array(‘something’=>’’Hello));

 

使用的时候只要是 isset($data_arr[$type]) && $data = $data_arr[$type] 就可以取到数据,在php中数组使用的是hashtable,时间复杂度是O(1),运行速度远远高于以上两种,另外书写起来也更简便的多。如果传入的参数是开始未定义的也不会运行查找浪费大量的系统资源。

 

十三·使用更精悍短小的代码

函数的最佳最大长度是150行代码,这样的代码比较便于维护,也方便修改,对于某些过于集中的算法函数,可能长度会大于这个长度。不过尽量还是不要超过,短小的才是美好的,短小的便于理解也便于修改,而功能相对单一的代码也就意味着可以复用它的地方会更多,有更好的复用性,另外当程序出问题的时候,测试起来也会相对简单好定位,便于维护修改。

 

十四·避免使用幻数

幻数,简单来说既是我们所说的硬编码,当程序中多处用到了一个值的时候,最好将这个值做成一个变量,使全局中就这一份,当需要修改的时候,可以只修改这个一文件,而不用挨个文件修改,想想如果一个值在100个或者更多的文件中用到,而你没有做成全局的变量,你会怎么样呢?不要说不可能,最简单的一个例子:<meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 这段代码大家肯定很熟悉,现在让你修改一下编码,改成utf-8的,你怎么办呢。两种处理方式,一种是做模板,需要修改的时候就一份,另外一种是直接编码就是一个全局的变量,我只修改一个值,如果你用了幻数,你的工作量有了。这个是个很典型的例子,其实还有很多的值都是需要做成变量而我们直接使用的幻数。

 

十五·中间结果赋值给变量

当一个表达式中嵌套层数过多,逻辑过于复杂的时候,将其拆分成一块块的,将其每一块的结果赋值给中间变量,这样可以降低程序的阅读难度和提高可维护性。

 

十六·复杂的逻辑表达式做成布尔函数

当某一个判断比较复杂的时候,可以考虑将其做成一个布尔函数,不要怕这个函数里面的代码少,很多时候这样写可以使你的逻辑更容易维护,另外碰到相同逻辑判定的地点还可以直接复用,不需要一处修改处处修改。

十七·永远不要复制粘贴雷同的代码

大段相同的代码实现类似的但是略有不同的程序功能的时候,我们很容易就回进行复制完后修改,其实这种做法会有很大的问题,例如,一个功能段,几十个地方使用了它,完后发现有了一点点的问题需要修改里面的一部分代码,这个时候就会出现问题,挨个文件改麻烦不说,如果一旦有漏改的情况,那么将会造成比较麻烦的错误。其较好的做法是利用参数来区别不同的调用方法,例如加一个$type=’login’这样的参数值,默认给一个默认参数,这样即使原来掉用过这个方法的地方不做修改也可以得到正确的结果,当出问题的时候只需要修改一个地方整个项目都进行了修改。

类似于复制雷同代码一样,永远不要直接修改线上服务器代码,因为你不知道有多少台服务器要改,你也不知道你会不会漏改,另外,你会不会被累趴下也不得而知,做一份代码,其余的事情交给运维去处理就好了,毕竟服务器那么多你去改这个有点太不靠谱了。

十八·备份源代码文件

看了这么久了,真心不容易呀,终于到了最后一条了,咱们写代码也是如此,点灯熬油无数个夜晚终于大功告成了,结果发现代码丢失了,别和我说不可能,我遇到过,一个朋友自己写的游戏,和运营都说好了,结果发现硬盘损坏数据都丢失了,悲催哀哉,所以最后一个建议,代码处处留档,最好有一个网上的空间存代码,如果你的代码不想让人看的话那些项目维护网站就算了,你要是自己有线上服务器可以存一份,个人比较推荐存在云盘里,我的很多代码存在百度云空间里,这样的好处是自己的电脑挂掉了也不会有事,另外用的时候比较方便可以拿到,保密性也还不错,当然,你也可以多存几个网络存储上。

 

啰啰嗦嗦说了这么多,希望对大家有所帮助。

2014-05-07 曹树芋

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值