PHP 程式设计的风格与技巧

Tips and Style of My PHP Codeing.

作者:罗文辰

这篇文章著重在‘方法论’而不是实作上的技术,所以这篇文章并不会教导您任何实作上的
技巧和实例。如果您是个只问结果不看过程的人,请您不要浪费时间来看这篇文章。

*** 关于 PHP 与网页程式设计 ***

PHP 是一种很强大又方便的工具,她能够让一般对程式设计不是很瞭解的人写出一般网路
的应用程式,并允许您在撰写 PHP 的程式时不需要做太多的规划与文件准备。特别是如果
您本身已经对 C/C++、Perl、Java 有一定的程度时,您几乎不必任何的学习就能写出很像
样的程式。

很不幸的,这就像一把剑的两面,有利有弊,您很容易写出松散、没有结构、不易维护的程
式,我非常的清楚这一点,因为我写过太多类似的 PHP 程式。这类的程式有一个称呼:
Quick and Dirty (快与杂乱)。

也许您已经开始了一个或数个不错的计划,并尝试著为该计划撰写一些像样的程式,也许您
正在思考著找一个架构更好的语言来取代 PHP (如 JSP),但其实您应该知道,一个程式的
好坏是决定在程式员而不是所使用的语言,这就像是武侠小说中讲的心中有剑意,花草皆为
剑的道理是不谋而合的,其实用什么语言不是重点,这篇文章也和 PHP 没什么关系,我只
是以 PHP 来当范例说明一些观念罢了。

我并不是很清楚高手们认为一个好的程式原始码要有什么条件,但我认为一个好的程式大致
上一定要有:

1.变数命名清楚
2.结构控制良好
3.容易阅读
4.注解与文件说明详细
5.错误与例外处理完善

以下我要说的技巧其实是通用于任何高阶的程式语言,只是拿 PHP 来当范例而已。



*** 缩排的技巧 ***

有写过程式的人都会知道,缩排 (Indenting) 是写程式的基本风格与技巧之一,缩排能让
您的程式容易阅读与维护,而缩排的间隔究竟要多少才恰当,我知道有许多人都是使用 TAB
来做他们的缩排的,而有看过我程式的人都很清楚我一直都是用四个空白字元来做缩排,主
要是因为不喜欢 TAB 一次跳八个空白让我的程式被拖得很长才这样用的,但后来看到有许
多高手也都建议您使用四个空白来当定格,(您可以在 C 语言的风格与艺术这本书看到相同
的说法,但我是在看过这本书之前就一直用四个空白来当 TAB 了)当然您也可以使用 TAB
来做缩排,我知道有些人是设定他的 editor 使 TAB 一次显示四个空白间隔而不是八个,
至于我自己是用‘真正的四个空白字元’来取代 TAB 字元的,这是为了让一些Viewer 看到
的缩排方式会完全相同。缺点大概就是占用了比较多的磁碟空间,产生出来的
Source Code File 会比较大,以大多数的 editors 来说,都可以让您自由设定 TAB,
像 UltraEditor, PE2/HE 等等。

结论:四个空白的缩排往往比八个空白(TAB预设值)的缩排好



*** 变数命名规则 ***

关于变数的命名一向是国内程式员很少去探讨的主题,其实命名是一种学问,最出名的就像
是MicroSoft 的匈牙利式命名法,所谓的匈牙利式命名法就是在变数名称前加上型别分辨的
方式,像:

  $cMyChar = "c";
  $sMyString = "this is a string";
  $iMyInt = 2002;

除此之外,还有一些约定成俗的习惯,最常见的像 Class 的命名方式,如 Class 的第一个
字母为大写,其他小写,字与字之间是以大小写来区分,而 Methods 的第一个字母为小写
,其他的同 Class,另外也有人会在 Class 之前加上大写 C 表示为 C Language 或
Class,像:

  Class CMyClass { // 这个 C 有人说是 Class 有人说是 C Language
    function myMethod() {
      ...
    }
    ...
  }

所以你会看到有些 Java Swing 的 Class 为了和 AWT 同名 Class 做区分会加 J:

  Class JButton { // 这个 J 就是 Java 啦
    ...
  }

至于变数的命名除了匈牙利式命名,我们在最常看到的是 Unix 里典型命名法 => 加底线,
像:

  $my_baby = "baby";
  $whos_your_daddy = "not me";

不过也有人喜欢用大小写区分的方式像:

  $myBaby = "baby";
  $whosYourDaddy = "not me";

至于我见过另一种是完全连在一起写不分大小的,你可以在 VBD Forum 的 Source 中看到
这种命名法。

变数的命名其实是很自由的,所有的规则只是为了让整个开发团队中有个准则而已。
如果您的计划是由很多人一起写的,请试著建立共识,采用一定的撰码与命名标准想必可以
提升不少的效率。

试著先看一下这个程式:

  $s = round($this->ey / $this->ln);
  $ly = $this->ey - $ps/2 - $s;
  $sv = round(max($this->d)/($this->ln-2));
  $i = 0;
  while ($ly > $this->sy) {
    $i++;
    ImageString ($this->im, $this->ef, 8, $ly-7, $i*$sv, $this->sc);
    ImageLine ($this->im, $this->sx+$ps, $ly, $this->ex-1+$ps, $ly, $this->dc);
    $ly = $ly - $s;
  }

看半天搞不清楚是在干嘛对吧?
我很不欣赏这样的写法,道理很简单,谁知道您的 $s、$ps、$ey、$sy 代表了什么,
更糟糕的是经过三个月之后,您想要替您自己的程式修改功能时,您才发现完了,因为您
根本已经忘记那些变数是干嘛用的,所以我宁愿用一些看起来很累赘的命名方式像
$step_value、$start_y 之类的变数名,这样我可以一看就很容易回想起来 $step_value
是用来代表间隔与间隔间的数值、$start_y 是用来代表起始的 Y 座标。这一点能确保我不
易忘记这个程式段是用来做什么用途的。

再看另一只其实是做同一件事的程式码:

  $step = round($this->end_y / $this->line_num); // 计算每条线的间距
  $line_y = $this->end_y - $poly_size/2 - $step; // 计算启始的 Y 座标
  $step_value = round(max($this->data)/($this->line_num-2));
  // 计算该刻度对应的数值

  $i = 0;
  while ($line_y > $this->start_y) {
    $i++;
    ImageString($this->im, $this->eng_font, 8,
      $line_y-7, $i*$step_value, $this->str_color);
      // 依照间隔依序写出该条刻线对应的数值

    ImageLine($this->im, $this->start_x+$poly_size, $line_y,
      $this->end_x-1+$poly_size, $line_y, $this->dash_color);
      // 依照间隔画出刻度线

    $line_y = $line_y - $step;
  }

是不是容易阅读多了?
其实每个人心目中都有个标准,函式与变数命名其实是很自由化的,要如何做是您自己的选
择,我不能保证我的方式是最好的,只是提供自己的心得,我的变(常)数命名原则就是:
最笨的方法往往都是最有用的方法。

*** 注解与说明文件 ***

适当的为您程式加上注解,可以让您或您的同事将来维护程式时事半功倍,当然如果这个程
式不小心外流了,那也很容易让别人搞清楚一些功能是怎么写的。注解用自己熟悉与瞭解的
语言就可以了,不一定要用英文,除非您的专案是要和一些老外合作的,
PHP 支援了 C Language 型态和 Shell Script 型态的注解方式,讲到 C 型态的注解我想
大家应该都很熟,不过说明文件在 PHP 中没有一个像 JavaDOC 那样有力的机制,所以我建
议是先把注解做好就好。

在 PHP 中的注解方式与 C 很类似:

您可以用 /* 和 */ 将您的注解包起来:

  /*
  这是 PHP 的注解
  */

也可以用 // 代表注解到行尾:

  echo "Hello World!/n";  // 从这开始是 PHP 的注解。
  echo "This is PHP Sample";

另一种方式是像 Shell Scripts 的 # ,作用和 // 一样是注解到行尾:

  ## 我也是注解

还有一些人或语言喜欢做一些变化像:

/*
* 我是猪头
* 我是一个大猪头
*/

/******************************************
* 这个程式是由猪头撰写,版权所有翻考必究 *
******************************************/

虽然看起来很猪头但不可否认的有招牌的效果



*** 结构控制 ***

所谓的结构控制就是 if, for, while 等条件判断与回圈的规则,有些人会说连这种东
西都要探讨规则那是不是太无聊了,其实这一点也不无聊,如果您有使用过 Unix 下的
一套叫 indent 的程式,光看那些复杂的参数您就会知道这一点都不简单,大体上来说
以 C 的结构来讲分为两大派,一派是 C 创始者 (K&R) 所使用的写法,另一派则是 GNU
的写法,而我个人是比较偏好 K&R 的写法,所以也在此仅以 K&R 的方式当范本:

您可能知道像一些 if 的控制式是这样写:

  if ($hit_point <= $damage) echo "you are dead";
  else echo "you alive";

可是我个人极度的反对这样的写法,因为当 if 一多起来,您全部都这样写会造成程式的
阅读性变差,甚至会搞不清楚这个 else 该和哪个 if 配对,像:

  if ($a > $b ) $c = true;
    if ($c == true) echo "c = true";
    else echo "c = false";
  else $c = false;



C 的老手应该会很清楚 else 是和最靠近的那个 if 配对,可是如果程式码不是短短四行而
是数千行时,这样的写法就会像是一颗颗的地雷不知何时会引爆。
因此不管要判断的东西是多么的简单,都应该要加上 {},像:

  if ($hit_point <= $damage) {
    echo "you are dead";
  }



照这样来看,另一个范例我的建议写法会成为:

  if ($a > $b) {
    $c = true;
    if ($c == true) {
      echo "c = true";
    } else {
      echo "c = false";
    }
  } else {
    $c = false;
  }



可是这个程式看起来很糟糕对不对?
其实程式设计上有一个很重要的技巧和观念就是:不要把 if 写太多层的巢状,
所以上式应该改成更单层的写法:

  if ($a > $b) {
    $c = true;
  } else {
    $c - false;
  }
  if ($c == true) {
    echo $c = true";
  } else {
    echo $c = false";
  }



是不是好多了?

至于有另一种所谓的单行条件式像是:

  // 这是错误的示范,请看接下来的说明
 

 ($hit_point <= $damage) ? echo "you are dead" : echo "you are alive";

以程式简洁的立场来说我不反对使用单行条件式,但是单行条件式在使用上需要小心,
一般来说我建议是在需要有赋值(assign value)动作时才用单行条件式,像:

 

 $alive = ($hit_point <= $damage) ? false : true;

因为在需要赋值时,使用 if 并不会占到多少便宜,像上式改用 if 来写就成为:

  if ($hit_point <= $damage) {
    $alive = false;
  } else {
    $alive = true; // 做了两次赋值的动作,感觉起来似乎就笨多了。
  }

还有一个蛮好用的地方就是在于 function 中的返回值,像:

  function myFunction($guess_num) {
    if ($guess_num == $random_num) {
      return true;
    } else {
      return false;
    }
  }



使用单行的判断式会有意想不到的方便:

  function myFunction($guess_num) {
    return ($guess_num == $random_num)? true : false;
  }

单行条件式纯脆是个人喜好,并没有好坏的问题,有些人极度反对单行条件式,我是觉得有
点追求架构到走火入魔的地步,个人是觉得该用的时候就用。

*** 后记 ***

在下才疏学浅,以上的心得只是在下的小小的经验累绩与自我遵行的规则,您不一定要按照
我的方式来写程式,因为在下很笨只能用这种方式来自我约束,我相信有许多天综英才的人
是不需要这样做的。

笔者最近公私上都发生很多事,所以都没稿件,觉得蛮对不起小企鹅的,因为原本 PHP 周
报是我提出来的想法,但发生了这些事也不是在下愿意的,而且自己其实懂得真的不多,实
在不敢野人献曝徒增笑柄,因此才一直强调所有的文章只是个人的小心得,不是什么了不起
的发现或研究成果。

此外好像有些人觉得笔者不是很喜欢发表一些应用上的技术,主要是因为那些东西在
php.net、RFC 或 PHP Builder里大都找得到,反而是方法与观念才是影响一个人学习成效
的最大关键。不过如果大家只喜欢吃牛肉面而不是想知道煮牛肉面的方法,我想我将来会提
供一些现成的牛肉面让大家吃吧,这可能是最后一篇讲观念的东西。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值