程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP入門知識 >> PHP實例說明編寫PHP代碼的5個好習慣

PHP實例說明編寫PHP代碼的5個好習慣

編輯:PHP入門知識

5個PHP編程的好習慣

有些人問,優秀程序員和大牛有什麼區別,大概有10到20種吧。因為大牛有很好的編程習慣和豐富的經驗,所以他們非常的高效。如果不好的編程習慣出現在你的代碼裡,你的代碼效率就會降低。本文闡述一些好的編程習慣,他們可以讓你成為更好的程序員。

這些習慣能讓你的代碼在高效運行的同時提高可維護性。你寫代碼的時候,可能大部分時間都浪費在維護上了,程序的維護代價很高。培養良好的編程習慣,如模塊化設計,可以讓你的代碼可讀性更好,從而容易維護。

代碼中的問題往往伴隨著不良的編程習慣,而且後者會導致代碼不好修改並可能出現新的缺陷。下面有五個好的編程習慣,將幫你避免這些陷阱:

  1. 使用友好的命名方式。
  2. 使用更精悍短小的代碼。
  3. 注釋你的代碼。
  4. 編寫異常處理。
  5. 永遠,永遠不要復制粘貼.(玉米:我深深的同意這一點)

下面的章節將解釋這些習慣。

良好的命名方式是最重要的編程習慣,因為好的命名會讓代碼易懂,好懂。代碼的可讀性決定它的可維護性。即使你在代碼沒有寫注釋,如果它可讀性好的話,它也修改起來也會簡單。你應該在練習開時就使用良好的命名方式,讓你的代碼像一本書一樣。

例1包含一個過短的變量名,寫出這樣的代碼非常不好弄懂,而且函數名也沒有清晰的描述出這個方法是做什麼的。函數名表示了函數的功能,如果它卻是做別的用途的,那就會誤導別人。

<?php

function getNBDay($d)
{
switch($d) {
case 5:
case 6:
case 7:
return 1;
default:
return ($d + 1);
}
}

$day = 5;

$nextDay = getNBDay($day);

echo ("Next day is: " . $nextDay . "\n");

?>

 例2則給出了使用良好命名方式的代碼。重新命名函數是為了更好的反映它們的功能。變量也重新命名為描述性的。只有一個在循環中的$i還使用短的變量名。盡管有些人不同意,短變量名在循環中是請允許的——甚至更好些,因為它們清晰的起到了指針的功能。

<?php

define ('MONDAY', 1);
define ('TUESDAY', 2);
define ('WEDNESDAY', 3);
define ('THURSDAY', 4);
define ('FRIDAY', 5);
define ('SATURDAY', 6);
define ('SUNDAY', 7);

/*
*
* @param $dayOfWeek
* @return int Day of week, with 1 being Monday and so on.
*/
function findNextBusinessDay($dayOfWeek)
{
$nextBusinessDay = $dayOfWeek;

switch($dayOfWeek) {
case FRIDAY:
case SATURDAY:
case SUNDAY:
$nextBusinessDay = MONDAY;
break;
default:
$nextBusinessDay += 1;
break;
}

return $nextBusinessDay;
}

$day = FRIDAY;

$nextBusDay = findNextBusinessDay($day);

echo ("Next day is:" . $nextBusDay . "\n");

?>

我鼓勵你在函數中分隔長的條件給函數命名,以便於描述這個條件。(玉米:這句話啥意思?5555)這個技巧會讓你的代碼容易閱讀和擴展,因此它可以被抽象復用。如果條件發生了改變,這樣也會很容易更新函數 .由於方法有一個見名知義的名字,化碼就不會失去它本來的意思或者變得難以理解。

使用更少的代碼

編寫代碼、解決問題是一種容易的事情。當你解決一個正在發生的問題,編呀編,寫呀寫,你的方法越來越長。只要你回頭使用更少的代碼來重構,就是過了很久也沒什麼問題。

重構是個好主意,但你應該養成第一次就寫出更短小精悍代碼的習慣。在一個窗口上(玉米:不用翻頁)就能看全的短小函數更容易理解。 要是一個函數長出了窗口,就很難理解了,因為你不能快速的從頭到腳的浏覽整個代碼。

當構思一個方法的時候,你還應該養成一個讓它們只做一件事情的習慣。以下因素寫代碼時應常注意。第一,只做一件事情的函數更易於復用。第二,這樣的函數測試更方便。第三,這樣的函數好讀易懂方便改——如果必要的話——讓它們盡可能的簡單吧。

壞習慣:過長的函數(很多時候)

例三是過長函數的表現。它不知道自己要做什麼。它做太多的事情,所以沒有集成化。它更難以理解,不好Debug和測試。它遍歷文件建立列表,它給對象賦值,它做一些計算,……它耕田,它澆水,甚至做更多事情。(^_^)

例三. 壞習慣:過長函數

 

<?php

function writeRssFeed($user)
{
// Get the DB connection information


// look up the user's preferences...
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
OR die(mysql_error());

// Query
$perfsQuery = sprintf("SELECT max_stories FROM user_perfs WHERE user= '%s'",
mysql_real_escape_string($user));

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

$max_stories = 25; // default it to 25;

if ($row = mysql_fetch_assoc($result)) {
$max_stories = $row['max_stories'];
}

// go get my data
$perfsQuery = sprintf("SELECT * FROM stories WHERE post_date = '%s'",
mysql_real_escape_string());

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


$feed = "<rss version=\"2.0\">" .
"<channel>" .
"<title>My Great Feed</title>" .
"<link>http://www.example.com/feed.xml</link>" .
"<description>The best feed in the world</description>" .
"<language>en-us</language>" .
"<pubDate>Tue, 20 Oct 2008 10:00:00 GMT</pubDate>" .
"<lastBuildDate>Tue, 20 Oct 2008 10:00:00 GMT</lastBuildDate>" .
"<docs>http://www.example.com/rss</docs>" .
"<generator>MyFeed Generator</generator>" .
"<managingEditor>[email protected]</managingEditor>" .
"<webMaster>[email protected]</webMaster>" .
"<ttl>5</ttl>";

// build the feed...
while ($row = mysql_fetch_assoc($result)) {
$title = $row['title'];
$link = $row['link'];
$description = $row['description'];
$date = $row['date'];
$guid = $row['guid'];

$feed .= "<item>";
$feed .= "<title>" . $title . "</title>";
$feed .= "<link>" . $link . "</link>";
$feed .= "<description> " . $description . "</description>";
$feed .= "<pubDate>" . $date . "</pubDate>";
$feed .= "<guid>" . $guid . "</guid>";
$feed .= "</item>";
}

$feed .= "</rss";

// write the feed out to the server...
echo($feed);

}

?>

要是你再加更多東西到這個函數裡,它會很快變得難以維護。

好習慣:可管理,集成化的函數

<?php

function createRssHeader()
{
return "<rss version=\"2.0\">" .
"<channel>" .
"<title>My Great Feed</title>" .
"<link>http://www.example.com/feed.xml</link>" .
"<description>The best feed in the world</description>" .
"<language>en-us</language>" .
"<pubDate>Tue, 20 Oct 2008 10:00:00 GMT</pubDate>" .
"<lastBuildDate>Tue, 20 Oct 2008 10:00:00 GMT</lastBuildDate>" .
"<docs>http://www.example.com/rss</docs>" .
"<generator>MyFeed Generator</generator>" .
"<managingEditor>[email protected]</managingEditor>" .
"<webMaster>[email protected]</webMaster>" .
"<ttl>5</ttl>";
}

function createRssFooter()
{
return "</channel></rss>";
}

function createRssItem($title, $link, $desc, $date, $guid)
{
$item .= "<item>";
$item .= "<title>" . $title . "</title>";
$item .= "<link>" . $link . "</link>";
$item .= "<description> " . $description . "</description>";
$item .= "<pubDate>" . $date . "</pubDate>";
$item .= "<guid>" . $guid . "</guid>";
$item .= "</item>";
return $item;
}

function getUserMaxStories($db_link, $default)
{
$perfsQuery = sprintf("SELECT max_stories FROM user_perfs WHERE user= '%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;
}

function writeRssFeed($user)
{
// Get the DB connection information
$settings = parse_ini_file("rss_server.ini");

// look up the user's preferences...
$link = mysql_connect($settings['db_host'], $settings['user'],
$settings['password']) OR die(mysql_error());

$max_stories = getUserMaxStories($link, 25);

// go get my data
$newsQuery = sprintf("SELECT * FROM stories WHERE post_date = '%s'",
mysql_real_escape_string(time()));

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

$feed = createRssHeader();

$i = 0;
// build the feed...
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();

// write the feed out to the server...
echo($feed);
}
?>

把長函數分割會導致效率降低,所以要注意,這個好習慣不要使用過度。這樣做可能也會引起閱讀性差,跟原來人家是一個整體時沒什麼區別。

注釋代碼

注釋你的代碼有時就像你剛著手寫代碼一樣困難。明確注釋內容很棘手,因為他要寫出代碼要做什麼。注釋變量是一個好主意。在函數頭部注釋可能不太明顯時,就可以告訴閱讀者函數要什麼參數,有什麼返回以及主要的意圖。

通常大家會注釋代碼是做什麼的,但這並不必要。如果代碼讓人困惑以至於你不得不寫注釋說它是做什麼的,這就提示你應該重寫它,使它更好懂。命名良好、更加短小、組織合理的代碼習慣會讓你的代碼用不著注釋就擁有很高的可讀性。

壞習慣:壓根沒有或者叽叽歪歪的函數注釋 (^_^)

例5的注釋只給出了代碼在做什麼——它的通過循環的遍歷、加了個數。但是丟了為什麼這麼做和要做什麼。 這會讓別人難以不影響原代碼的情形下安全修改的做出修改。

例5 :壓根沒胡或者叽叽歪歪的函數注釋

 

<?php

class ResultMessage
{
private $severity;
private $message;

public function __construct($sev, $msg)
{
$this->severity = $sev;
$this->message = $msg;
}

public function getSeverity()
{
return $this->severity;
}

public function setSeverity($severity)
{
$this->severity = $severity;
}

public function getMessage()
{
return $this->message;
}

public function setMessage($msg)
{
$this->message = $msg;
}
}

function cntMsgs($messages)
{
$n = 0;
/* iterate through the messages... */
foreach($messages as $m) {
if ($m->getSeverity() == 'Error') {
$n++; // add one to the result;
}
}
return $n;
}

$messages = array(new ResultMessage("Error", "This is an error!"),
new ResultMessage("Warning", "This is a warning!"),
new ResultMessage("Error", "This is another error!"));

$errs = cntMsgs($messages);

echo("There are " . $errs . " errors in the result.\n");

?>

好習慣: 注釋函數和類

例6裡的注釋標明了類和函數的意圖。注釋表明方法做了什麼和為什麼做,這會對將來了解代碼的意圖很有幫助。環境的變化會需要你進行代碼修改,這就會讓很容易的知道開始時你代碼是做什麼的。

例6.好習慣:注釋函數和類

 

<?php
/**
* The ResultMessage class holds a message that can be returned
* as a result of a process. The message has a severity and
* message.
*
* @author nagood
*
*/
class ResultMessage
{
private $severity;
private $message;

/**
* Constructor for the ResultMessage that allows you to assign
* severity and message.
* @param $sev See {@link getSeverity()}
* @param $msg
* @return unknown_type
*/
public function __construct($sev, $msg)
{
$this->severity = $sev;
$this->message = $msg;
}

/**
* Returns the severity of the message. Should be one
* "Information", "Warning", or "Error".
* @return string Message severity
*/
public function getSeverity()
{
return $this->severity;
}

/**
* Sets the severity of the message
* @param $severity
* @return void
*/
public function setSeverity($severity)
{
$this->severity = $severity;
}

public function getMessage()
{
return $this->message;
}

public function setMessage($msg)
{
$this->message = $msg;
}
}


/*
* Counts the messages with the given severity in the array
* of messages.
*
* @param $messages An array of ResultMessage
* @return int Count of messages with a severity of "Error"
*/
function countErrors($messages)
{
$matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == "Error") {
$matchingCount++;
}
}
return $matchingCount;
}

$messages = array(new ResultMessage("Error", "This is an error!"),
new ResultMessage("Warning", "This is a warning!"),
new ResultMessage("Error", "This is another error!"));

$errs = countErrors($messages);

echo("There are " . $errs . " errors in the result.\n");

?>

異常處理

寫健壯應用時經常會提到的異常處理,一般遵循著80/20原則: 80%的代碼用於處理異常或者驗證,20%的代碼沒什麼實際的用途。原始的代碼通常都是在樂觀的環境下編寫的。這意味著代碼可以在數據正常、一切理解的基礎環境中工作的很好。但是這種代碼在其生命周期內是脆弱的。在極端的情形中,你得花更多的時間來未很可能永遠不會發生的狀況編寫相應代碼。

這個習慣就是要你處理全部的出錯情況,而且如果要是不這麼做,你的代碼永遠也完不成。

壞習慣:不處理任何異常

<?php

// Get the actual name of the
function convertDayOfWeekToName($day)
{
$dayNames = array(
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday");
return $dayNames[$day];
}

echo("The name of the 0 day is: " . convertDayOfWeekToName(0) . "\n");
echo("The name of the 10 day is: " . convertDayOfWeekToName(10) . "\n");
echo("The name of the 'orange' day is: " . convertDayOfWeekToName('orange') . "\n");

?>

好習慣: 防守型編程

例8表明處理並拋出異常是一件很有意義的事情。不只是額外的異常處理可以讓代碼健壯,但是這有助於提高代碼的可讀性。這種異常處理為原作者查看何時編寫提供了一個很好的說明。

例8.好習慣:防守型編程

<?php

/**
* This is the exception thrown if the day of the week is invalid.
* @author nagood
*
*/
class InvalidDayOfWeekException extends Exception { }

class InvalidDayFormatException extends Exception { }

/**
* Gets the name of the day given the day in the week. Will
* return an error if the value supplied is out of range.
*
* @param $day
* @return unknown_type
*/
function convertDayOfWeekToName($day)
{
if (! is_numeric($day)) {
throw new InvalidDayFormatException('The value \'' . $day . '\' is an ' .
'invalid format for a day of week.');
}

if (($day > 6) || ($day < 0)) {
throw new InvalidDayOfWeekException('The day number \'' . $day . '\' is an ' .
'invalid day of the week. Expecting 0-6.');
}

$dayNames = array(
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday");
return $dayNames[$day];
}

echo("The name of the 0 day is: " . convertDayOfWeekToName(0) . "\n");

try {
echo("The name of the 10 day is: " . convertDayOfWeekToName(10) . "\n");
} catch (InvalidDayOfWeekException $e) {
echo ("Encountered error while trying to convert value: " . $e->getMessage() . "\n");
}

try {
echo("The name of the 'orange' day is: " . convertDayOfWeekToName('orange') . "\n");
} catch (InvalidDayFormatException $e) {
echo ("Encountered error while trying to convert value: " . $e->getMessage() . "\n");
}

?>

通過檢驗參數的全法性——這有助於他人使用你需要正確參數的函數——你應該檢驗它們並拋出異常的大意:

  • 盡量拋出接近錯誤的異常.
  • 處理每個特殊的異常.

永遠,永遠不要復制粘貼

把代碼復制到你的編輯裡的能力是一把雙刃劍。一方面,它避免了你參照一些示例後重新再打一遍時出現的錯誤;另一方面,它讓書寫相似代碼太簡單了。

你要避免在你的程序應用中復制粘貼代碼。當你發現自己在這樣做時,停下來並問自己可不可以把復制的部分重復使用。把相同的代碼放在同一個地方可以讓你以後修改時更加的輕松,因為要改變都在一起。

壞習慣:相似的代碼塊

例9表現了除了一些值所在位置之外很相近的幾個方法。有些工具可以檢驗你的代碼中復制粘貼的部分(去看看Resources)。

例9.相似的代碼塊

 

<?php
/**
* Counts the number of messages found in the array of
* ResultMessage with the getSeverity() value of "Error"
*
* @param $messages An array of ResultMessage
* @return unknown_type
*/
function countErrors($messages)
{
$matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == "Error") {
$matchingCount++;
}
}
return $matchingCount;
}

/**
* Counts the number of messages found in the array of
* ResultMessage with the getSeverity() value of "Warning"
*
* @param $messages An array of ResultMessage
* @return unknown_type
*/
function countWarnings($messages)
{
$matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == "Warning") {
$matchingCount++;
}
}
return $matchingCount;
}

/**
* Counts the number of messages found in the array of
* ResultMessage with the getSeverity() value of "Information"
*
* @param $messages An array of ResultMessage
* @return unknown_type
*/
function countInformation($messages)
{
$matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == "Information") {
$matchingCount++;
}
}
return $matchingCount;
}

$messages = array(new ResultMessage("Error", "This is an error!"),
new ResultMessage("Warning", "This is a warning!"),
new ResultMessage("Error", "This is another error!"));

$errs = countErrors($messages);

echo("There are " . $errs . " errors in the result.\n");
?>

好習慣:可復用的帶參函數

例10展示了把要復制的代碼入到一個方法中的代碼修改。另一個修改的方法則把工作代理給了一個新的方法 。編寫一個通用的方法要花一些時間來設計,當然這會讓你停下來思考,而不是用復制粘貼的組合快捷鍵。但是這樣做會在以後修改時省回第一次多花的時間。

例10.好習慣 :可利用的帶參函數

 

<?php
/*
* Counts the messages with the given severity in the array
* of messages.
*
* @param $messages An array of ResultMessage
* @return int Count of messages matching $withSeverity
*/
function countMessages($messages, $withSeverity)
{
$matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == $withSeverity) {
$matchingCount++;
}
}
return $matchingCount;
}

/**
* Counts the number of messages found in the array of
* ResultMessage with the getSeverity() value of "Error"
*
* @param $messages An array of ResultMessage
* @return unknown_type
*/
function countErrors($messages)
{
return countMessages($messages, "Errors");
}

/**
* Counts the number of messages found in the array of
* ResultMessage with the getSeverity() value of "Warning"
*
* @param $messages An array of ResultMessage
* @return unknown_type
*/
function countWarnings($messages)
{
return countMessages($messages, "Warning");
}

/**
* Counts the number of messages found in the array of
* ResultMessage with the getSeverity() value of "Warning"
*
* @param $messages An array of ResultMessage
* @return unknown_type
*/
function countInformation($messages)
{
return countMessages($messages, "Information");
}

$messages = array(new ResultMessage("Error", "This is an error!"),
new ResultMessage("Warning", "This is a warning!"),
new ResultMessage("Error", "This is another error!"));

$errs = countErrors($messages);

echo("There are " . $errs . " errors in the result.\n");

?>

 

結論

如果當你開發PHP的時候養成了本文中提到的好習慣,你寫的代碼將會好讀、好懂、好維護。編寫可維護代碼的方式將讓你的代碼可以高度排錯,並告別低級錯誤。

使用良好命名並用短代碼塊來組強你的代碼會讓你的代碼簡單明了。注明你代碼的目的會讓它的主旨明確易於理解。異常處理讓你的代碼健壯。最後,摒棄復制粘貼的惡習讓你的代碼整潔。

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

玉米寄語:最後的這個復制粘貼的建議讓我一身冷汗,想想其實有很多代碼都是重復的工作,有時只是為了“快”,而把相似的代碼又“復制”了一遍,雖然我沒有使用ctrl+c\v 但是也是寫了很多類似的代碼,看來,review的事兒可以在世界和平的事兒之前考慮了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved