配色: 字号:
PHP实例说明编写PHP代码的5个好习惯
2016-08-29 | 阅:  转:  |  分享 
  
PHP实例说明编写PHP代码的5个好习惯

5个PHP编程的好习惯

有些人问,优秀程序员和大牛有什么区别,大概有10到20种吧。因为大牛有很好的编程习惯和丰富的经验,所以他们非常的高效。如果不好的编程习惯出现在你的代码里,你的代码效率就会降低。本文阐述一些好的编程习惯,他们可以让你成为更好的程序员。

这些习惯能让你的代码在高效运行的同时提高可维护性。你写代码的时候,可能大部分时间都浪费在维护上了,程序的维护代价很高。培养良好的编程习惯,如模块化设计,可以让你的代码可读性更好,从而容易维护。

代码中的问题往往伴随着不良的编程习惯,而且后者会导致代码不好修改并可能出现新的缺陷。下面有五个好的编程习惯,将帮你避免这些陷阱:

使用友好的命名方式。

使用更精悍短小的代码。

注释你的代码。

编写异常处理。

永远,永远不要复制粘贴.(玉米:我深深的同意这一点)

下面的章节将解释这些习惯。

良好的命名方式是最重要的编程习惯,因为好的命名会让代码易懂,好懂。代码的可读性决定它的可维护性。即使你在代码没有写注释,如果它可读性好的话,它也修改起来也会简单。你应该在练习开时就使用良好的命名方式,让你的代码像一本书一样。

例1包含一个过短的变量名,写出这样的代码非常不好弄懂,而且函数名也没有清晰的描述出这个方法是做什么的。函数名表示了函数的功能,如果它却是做别的用途的,那就会误导别人。




functiongetNBDay($d)

{

switch($d){

case5:

case6:

case7:

return1;

default:

return($d+1);

}

}



$day=5;



$nextDay=getNBDay($day);



echo("Nextdayis:".$nextDay."\n");



?>

例2则给出了使用良好命名方式的代码。重新命名函数是为了更好的反映它们的功能。变量也重新命名为描述性的。只有一个在循环中的$i还使用短的变量名。尽管有些人不同意,短变量名在循环中是请允许的——甚至更好些,因为它们清晰的起到了指针的功能。




define(''MONDAY'',1);

define(''TUESDAY'',2);

define(''WEDNESDAY'',3);

define(''THURSDAY'',4);

define(''FRIDAY'',5);

define(''SATURDAY'',6);

define(''SUNDAY'',7);



/



@param$dayOfWeek

@returnintDayofweek,with1beingMondayandsoon.

/

functionfindNextBusinessDay($dayOfWeek)

{

$nextBusinessDay=$dayOfWeek;



switch($dayOfWeek){

caseFRIDAY:

caseSATURDAY:

caseSUNDAY:

$nextBusinessDay=MONDAY;

break;

default:

$nextBusinessDay+=1;

break;

}



return$nextBusinessDay;

}



$day=FRIDAY;



$nextBusDay=findNextBusinessDay($day);



echo("Nextdayis:".$nextBusDay."\n");



?>

我鼓励你在函数中分隔长的条件给函数命名,以便于描述这个条件。(玉米:这句话啥意思?5555)这个技巧会让你的代码容易阅读和扩展,因此它可以被抽象复用。如果条件发生了改变,这样也会很容易更新函数.由于方法有一个见名知义的名字,化码就不会失去它本来的意思或者变得难以理解。

使用更少的代码

编写代码、解决问题是一种容易的事情。当你解决一个正在发生的问题,编呀编,写呀写,你的方法越来越长。只要你回头使用更少的代码来重构,就是过了很久也没什么问题。

重构是个好主意,但你应该养成第一次就写出更短小精悍代码的习惯。在一个窗口上(玉米:不用翻页)就能看全的短小函数更容易理解。要是一个函数长出了窗口,就很难理解了,因为你不能快速的从头到脚的浏览整个代码。

当构思一个方法的时候,你还应该养成一个让它们只做一件事情的习惯。以下因素写代码时应常注意。第一,只做一件事情的函数更易于复用。第二,这样的函数测试更方便。第三,这样的函数好读易懂方便改——如果必要的话——让它们尽可能的简单吧。

坏习惯:过长的函数(很多时候)

例三是过长函数的表现。它不知道自己要做什么。它做太多的事情,所以没有集成化。它更难以理解,不好Debug和测试。它遍历文件建立列表,它给对象赋值,它做一些计算,……它耕田,它浇水,甚至做更多事情。(^_^)

例三.坏习惯:过长函数






functionwriteRssFeed($user)

{

//GettheDBconnectioninformation





//lookuptheuser''spreferences...

$link=mysql_connect(''mysql_host'',''mysql_user'',''mysql_password'')

ORdie(mysql_error());



//Query

$perfsQuery=sprintf("SELECTmax_storiesFROMuser_perfsWHEREuser=''%s''",

mysql_real_escape_string($user));



$result=mysql_query($query,$link);



$max_stories=25;//defaultitto25;



if($row=mysql_fetch_assoc($result)){

$max_stories=$row[''max_stories''];

}



//gogetmydata

$perfsQuery=sprintf("SELECTFROMstoriesWHEREpost_date=''%s''",

mysql_real_escape_string());



$result=mysql_query($query,$link);





$feed="".

"".

"MyGreatFeed".

"".

"Thebestfeedintheworld".

"en-us".

"Tue,20Oct200810:00:00GMT".

"Tue,20Oct200810:00:00GMT".

"http://www.example.com/rss".

"MyFeedGenerator".

"editor@example.com".

"webmaster@example.com".

"5";



//buildthefeed...

while($row=mysql_fetch_assoc($result)){

$title=$row[''title''];

$link=$row[''link''];

$description=$row[''description''];

$date=$row[''date''];

$guid=$row[''guid''];



$feed.="";

$feed.="".$title."";

$feed.="";

$feed.="".$description."";

$feed.="".$date."";

$feed.="".$guid."";

$feed.="
";

}



$feed.="


//writethefeedouttotheserver...

echo($feed);



}



?>

要是你再加更多东西到这个函数里,它会很快变得难以维护。

好习惯:可管理,集成化的函数




functioncreateRssHeader()

{

return"".

"".

"MyGreatFeed".

"".

"Thebestfeedintheworld".

"en-us".

"Tue,20Oct200810:00:00GMT".

"Tue,20Oct200810:00:00GMT".

"http://www.example.com/rss".

"MyFeedGenerator".

"editor@example.com".

"webmaster@example.com".

"5";

}



functioncreateRssFooter()

{

return"
";

}



functioncreateRssItem($title,$link,$desc,$date,$guid)

{

$item.="";

$item.="".$title."";

$item.="";

$item.="".$description."";

$item.="".$date."";

$item.="".$guid."";

$item.="
";

return$item;

}



functiongetUserMaxStories($db_link,$default)

{

$perfsQuery=sprintf("SELECTmax_storiesFROMuser_perfsWHEREuser=''%s''",

mysql_real_escape_string($user));



$result=mysql_query($perfsQuery,$db_link);



$max_stories=$default;



if($row=mysql_fetch_assoc($result)){

$max_stories=$row[''max_stories''];

}



return$max_stories;

}



functionwriteRssFeed($user)

{

//GettheDBconnectioninformation

$settings=parse_ini_file("rss_server.ini");



//lookuptheuser''spreferences...

$link=mysql_connect($settings[''db_host''],$settings[''user''],

$settings[''password''])ORdie(mysql_error());



$max_stories=getUserMaxStories($link,25);



//gogetmydata

$newsQuery=sprintf("SELECTFROMstoriesWHEREpost_date=''%s''",

mysql_real_escape_string(time()));



$result=mysql_query($newsQuery,$link);



$feed=createRssHeader();



$i=0;

//buildthefeed...

while($row=mysql_fetch_assoc($result)){

if($i<$max_stories){

$title=$row[''title''];

$link=$row[''link''];

$description=$row[''description''];

$date=$row[''date''];

$guid=$row[''guid''];



$feed.=createRssItem($title,$link,$description,$date,$guid);



$i++;

}else{

break;

}

}



mysql_close($link);



$feed.=createRssFooter();



//writethefeedouttotheserver...

echo($feed);

}

?>

把长函数分割会导致效率降低,所以要注意,这个好习惯不要使用过度。这样做可能也会引起阅读性差,跟原来人家是一个整体时没什么区别。

注释代码

注释你的代码有时就像你刚着手写代码一样困难。明确注释内容很棘手,因为他要写出代码要做什么。注释变量是一个好主意。在函数头部注释可能不太明显时,就可以告诉阅读者函数要什么参数,有什么返回以及主要的意图。

通常大家会注释代码是做什么的,但这并不必要。如果代码让人困惑以至于你不得不写注释说它是做什么的,这就提示你应该重写它,使它更好懂。命名良好、更加短小、组织合理的代码习惯会让你的代码用不着注释就拥有很高的可读性。

坏习惯:压根没有或者叽叽歪歪的函数注释(^_^)

例5的注释只给出了代码在做什么——它的通过循环的遍历、加了个数。但是丢了为什么这么做和要做什么。这会让别人难以不影响原代码的情形下安全修改的做出修改。

例5:压根没胡或者叽叽歪歪的函数注释






classResultMessage

{

private$severity;

private$message;



publicfunction__construct($sev,$msg)

{

$this->severity=$sev;

$this->message=$msg;

}



publicfunctiongetSeverity()

{

return$this->severity;

}



publicfunctionsetSeverity($severity)

{

$this->severity=$severity;

}



publicfunctiongetMessage()

{

return$this->message;

}



publicfunctionsetMessage($msg)

{

$this->message=$msg;

}

}



functioncntMsgs($messages)

{

$n=0;

/iteratethroughthemessages.../

foreach($messagesas$m){

if($m->getSeverity()==''Error''){

$n++;//addonetotheresult;

}

}

return$n;

}



$messages=array(newResultMessage("Error","Thisisanerror!"),

newResultMessage("Warning","Thisisawarning!"),

newResultMessage("Error","Thisisanothererror!"));



$errs=cntMsgs($messages);



echo("Thereare".$errs."errorsintheresult.\n");



?>

好习惯:注释函数和类

例6里的注释标明了类和函数的意图。注释表明方法做了什么和为什么做,这会对将来了解代码的意图很有帮助。环境的变化会需要你进行代码修改,这就会让很容易的知道开始时你代码是做什么的。

例6.好习惯:注释函数和类




/

TheResultMessageclassholdsamessagethatcanbereturned

asaresultofaprocess.Themessagehasaseverityand

message.



@authornagood



/

classResultMessage

{

private$severity;

private$message;



/

ConstructorfortheResultMessagethatallowsyoutoassign

severityandmeswww.shanxiwang.netsage.

@param$sevSee{@linkgetSeverity()}

@param$msg

@returnunknown_type

/

publicfunction__construct($sev,$msg)

{

$this->severity=$sev;

$this->message=$msg;

}



/

Returnstheseverityofthemessage.Shouldbeone

"Information","Warning",or"Error".

@returnstringMessageseverity

/

publicfunctiongetSeverity()

{

return$this->severity;

}



/

Setstheseverityofthemessage

@param$severity

@returnvoid

/

publicfunctionsetSeverity($severity)

{

$this->severity=$severity;

}



publicfunctiongetMessage()

{

return$this->message;

}



publicfunctionsetMessage($msg)

{

$this->message=$msg;

}

}





/

Countsthemessageswiththegivenseverityinthearray

ofmessages.



@param$messagesAnarrayofResultMessage

@returnintCountofmessageswithaseverityof"Error"

/

functioncountErrors($messages)

{

$matchingCount=0;

foreach($messagesas$m){

if($m->getSeverity()=="Error"){

$matchingCount++;

}

}

return$matchingCount;

}



$messages=array(newResultMessage("Error","Thisisanerror!"),

newResultMessage("Warning","Thisisawarning!"),

newResultMessage("Error","Thisisanothererror!"));



$errs=countErrors($messages);



echo("Thereare".$errs."errorsintheresult.\n");



?>

异常处理

写健壮应用时经常会提到的异常处理,一般遵循着80/20原则:80%的代码用于处理异常或者验证,20%的代码没什么实际的用途。原始的代码通常都是在乐观的环境下编写的。这意味着代码可以在数据正常、一切理解的基础环境中工作的很好。但是这种代码在其生命周期内是脆弱的。在极端的情形中,你得花更多的时间来未很可能永远不会发生的状况编写相应代码。

这个习惯就是要你处理全部的出错情况,而且如果要是不这么做,你的代码永远也完不成。

坏习惯:不处理任何异常




//Gettheactualnameofthe

functionconvertDayOfWeekToName($day)

{

$dayNames=array(

"Sunday",

"Monday",

"Tuesday",

"Wednesday",

"Thursday",

"Friday",

"Saturday");

return$dayNames[$day];

}



echo("Thenameofthe0dayis:".convertDayOfWeekToName(0)."\n");

echo("Thenameofthe10dayis:".convertDayOfWeekToName(10)."\n");

echo("Thenameofthe''orange''dayis:".convertDayOfWeekToName(''orange'')."\n");



?>

好习惯:防守型编程

例8表明处理并抛出异常是一件很有意义的事情。不只是额外的异常处理可以让代码健壮,但是这有助于提高代码的可读性。这种异常处理为原作者查看何时编写提供了一个很好的说明。

例8.好习惯:防守型编程




/

Thisistheexceptionthrownifthedayoftheweekisinvalid.

@authornagood



/

classInvalidDayOfWeekExceptionextendsException{}



classInvalidDayFormatExceptionextendsException{}



/

Getsthenameofthedaygiventhedayintheweek.Will

returnanerrorifthevaluesuppliedisoutofrange.



@param$day

@returnunknown_type

/

functionconvertDayOfWeekToName($day)

{

if(!is_numeric($day)){

thrownewInvalidDayFormatException(''Thevalue\''''.$day.''\''isan''.

''invalidformatforadayofweek.'');

}



if(($day>6)||($day<0)){

thrownewInvalidDayOfWeekException(''Thedaynumber\''''.$day.''\''isan''.

''invaliddayoftheweek.Expecting0-6.'');

}



$dayNames=array(

"Sunday",

"Monday",

"Tuesday",

"Wednesday",

"Thursday",

"Friday",

"Saturday");

return$dayNames[$day];

}



echo("Thenameofthe0dayis:".convertDayOfWeekToName(0)."\n");



try{

echo("Thenameofthe10dayis:".convertDayOfWeekToName(10)."\n");

}catch(InvalidDayOfWeekException$e){

echo("Encounterederrorwhiletryingtoconvertvalue:".$e->getMessage()."\n");

}



try{

echo("Thenameofthe''orange''dayis:".convertDayOfWeekToName(''orange'')."\n");

}catch(InvalidDayFormatException$e){

echo("Encounterederrorwhiletryingtoconvertvalue:".$e->getMessage()."\n");

}



?>

通过检验参数的全法性——这有助于他人使用你需要正确参数的函数——你应该检验它们并抛出异常的大意:

尽量抛出接近错误的异常.

处理每个特殊的异常.

永远,永远不要复制粘贴

把代码复制到你的编辑里的能力是一把双刃剑。一方面,它避免了你参照一些示例后重新再打一遍时出现的错误;另一方面,它让书写相似代码太简单了。

你要避免在你的程序应用中复制粘贴代码。当你发现自己在这样做时,停下来并问自己可不可以把复制的部分重复使用。把相同的代码放在同一个地方可以让你以后修改时更加的轻松,因为要改变都在一起。

坏习惯:相似的代码块

例9表现了除了一些值所在位置之外很相近的几个方法。有些工具可以检验你的代码中复制粘贴的部分(去看看Resources)。

例9.相似的代码块




/

Countsthenumberofmessagesfoundinthearrayof

ResultMessagewiththegetSeverity()valueof"Error"



@param$messagesAnarrayofResultMessage

@returnunknown_type

/

functioncountErrors($messages)

{

$matchingCount=0;

foreach($messagesas$m){

if($m->getSeverity()=="Error"){

$matchingCount++;

}

}

return$matchingCount;

}



/

Countsthenumberofmessagesfoundinthearrayof

ResultMessagewiththegetSeverity()valueof"Warning"



@param$messagesAnarrayofResultMessage

@returnunknown_type

/

functioncountWarnings($messages)

{

$matchingCount=0;

foreach($messagesas$m){

if($m->getSeverity()=="Warning"){

$matchingCount++;

}

}

return$matchingCount;

}



/

Countsthenumberofmessagesfoundinthearrayof

ResultMessagewiththegetSeverity()valueof"Information"



@param$messagesAnarrayofResultMessage

@returnunknown_type

/

functioncountInformation($messages)

{

$matchingCount=0;

foreach($messagesas$m){

if($m->getSeverity()=="Information"){

$matchingCount++;

}

}

return$matchingCount;

}



$messages=array(newResultMessage("Error","Thisisanerror!"),

newResultMessage("Warning","Thisisawarning!"),

newResultMessage("Error","Thisisanothererror!"));



$errs=countErrors($messages);



echo("Thereare".$errs."errorsintheresult.\n");

?>

好习惯:可复用的带参函数

例10展示了把要复制的代码入到一个方法中的代码修改。另一个修改的方法则把工作代理给了一个新的方法。编写一个通用的方法要花一些时间来设计,当然这会让你停下来思考,而不是用复制粘贴的组合快捷键。但是这样做会在以后修改时省回第一次多花的时间。

例10.好习惯:可利用的带参函数




/

Countsthemessageswiththegivenseverityinthearray

ofmessages.



@param$messagesAnarrayofResultMessage

@returnintCountofmessagesmatching$withSeverity

/

functioncountMessages($messages,$withSeverity)

{

$matchingCount=0;

foreach($messagesas$m){

if($m->getSeverity()==$withSeverity){

$matchingCount++;

}

}

return$matchingCount;

}



/

Countsthenumberofmessagesfoundinthearrayof

ResultMessagewiththegetSeverity()valueof"Error"



@param$messagesAnarrayofResultMessage

@returnunknown_type

/

functioncountErrors($messages)

{

returncountMessages($messages,"Errors");

}



/

Countsthenumberofmessagesfoundinthearrayof

ResultMessagewiththegetSeverity()valueof"Warning"



@param$messagesAnarrayofResultMessage

@returnunknown_type

/

functioncountWarnings($messages)

{

returncountMessages($messages,"Warning");

}



/

Countsthenumberofmessagesfoundinthearrayof

ResultMessagewiththegetSeverity()valueof"Warning"



@param$messagesAnarrayofResultMessage

@returnunknown_type

/

functioncountInformation($messages)

{

returncountMessages($messages,"Information");

}



$messages=array(newResultMessage("Error","Thisisanerror!"),

newResultMessage("Warning","Thisisawarning!"),

newResultMessage("Error","Thisisanothererror!"));



$errs=countErrors($messages);



echo("Thereare".$errs."errorsintheresult.\n");



?>



结论

如果当你开发PHP的时候养成了本文中提到的好习惯,你写的代码将会好读、好懂、好维护。编写可维护代码的方式将让你的代码可以高度排错,并告别低级错误。

使用良好命名并用短代码块来组强你的代码会让你的代码简单明了。注明你代码的目的会让它的主旨明确易于理解。异常处理让你的代码健壮。最后,摒弃复制粘贴的恶习让你的代码整洁。

-----------------------------------------------------

玉米寄语:最后的这个复制粘贴的建议让我一身冷汗,想想其实有很多代码都是重复的工作,有时只是为了“快”,而把相似的代码又“复制”了一遍,虽然我没有使用ctrl+c\v但是也是写了很多类似的代码,看来,review的事儿可以在世界和平的事儿之前考虑了。

献花(0)
+1
(本文系网络学习天...首藏)