4. 幫助與共享
4.1. 重用您和其他人的艱苦工作
跨工程的重用在沒有一個通用結構的情況下幾乎是不可能的。對象符合他們現有的服務需求,不同的過程有著不同的服務需求環境,這使對象重用變得很困難。
開發一個通用結構需要預先花費許多的努力來設計。當努力不成功的時候,無論出於什麼原因,有幾種辦法推薦使用:
4.2. 請教!給群組發Email求助
這個簡單的方法很少被使用。因為有些程序員們覺得如果他向其他人求助,會顯得自己水平低,這多傻啊!做新的有趣的工作,不要一遍又一遍的做別人已經做過的東西。
如果你需要某些事項的源代碼,如果已經有某人做過的話,就向群組發email求助。結果會很驚喜哦!
在許多大的群組中,個人往往不知道其他人在干什麼。你甚至可以發現某人在找一些東西做,並且自願為你寫代碼,如果人們在一起工作,外面就總有一個金礦。
4.3. 告訴!當你在做事的時候,把它告訴所有人
如果你做了什麼可重用的東西的話,讓其他人知道。別害羞,也不要為了保護自豪感而把你的工作成果藏起來。一旦養成共享工作成果的習慣,每個人都會獲得更多。
4.4. 小型代碼庫
對於代碼重用,一個常見的問題就是人們不從他們做過的代碼中做庫。一個可重用的類可能正隱蔽在一個程序目錄並且決不會有被分享的激動,因為程序員不會把類分拆出來加入庫中。
這樣的其中一個原因就是人們不喜歡做一個小庫,對小庫有一些不正確感覺。把這樣的感覺克服掉吧,電腦才不關心你有多少個庫呢。
如果你有一些代碼可以重用,而且不能放入一個已經存在的庫中,那麼就做一個新的庫吧。如果人們真的考慮重用的話,庫不會在很長的一段時間裡保持那麼小的。
4.5. 知識庫
很多公司不清楚現有什麼代碼可用,而且大多數程序員仍然沒有通過溝通他們已經做過了什麼,或者一直在詢問現存什麼代碼可用。解決這個的方法是有一個可用的知識庫。
理想的情況是,程序員可以到一個WEB頁,浏覽或者查詢打包的知識庫列表,找到他們所要的。建立一個程序員可以自動維護的知識庫系統,是一個很不錯的做法。如果有一個專門的管理員來負責維護這個知識庫,那當然更好。
另一種方法是自動的從代碼中產生知識庫的做法。把通用的類、方法和標頭(subsystem headers)作為手冊或者是知識庫的一個條目。
5. 書寫注釋
5.1. 講一個故事
把你的注釋當作描述系統的一個故事。並且使得你的注釋能被機器解析後,以固定的格式放到手冊中去。類的注釋是故事的一部分,方法的名稱、方法的注釋、方法的實現也是故事一部分。所有的這些部分編織在一起,使得人們在以後的時間裡能夠准確的知道你干了什麼,為什麼這麼做。
5.2. 歸檔注釋
注釋的要歸檔才有意義,否則,假如在一個地方放一條注釋描述你做了什麼選擇和你為什麼這麼做,只有考古學家才能發現這是最有用的信息。(如何歸檔另行規范)
5.3. 注釋結構
工程的每部分都有特定的注釋結構。 程序中的注釋,這裡給出示例作為規范,注釋中以 * @ 為關鍵字的開始,以:為注釋關鍵字結尾。
5.3.1. 預定義關鍵字
關鍵字 含義
Purpose 表示類、屬**、方法要做些什麼或者什麼含義。
Package Name 類名
Author 作者
Modifications 修改記錄(編號規則為“No”+日期+“-”+序號)
See 參考
Method Name 方法名
Parameter 參數名(包括類型)
Return 返回值(包括類型)
Attribute/Variable Name 屬**/變量名
Type 屬**/變量類型
5.3.2. 類的注釋
/**
* @ Purpose:
* 訪問數據庫的類,以ODBC作為通用訪問接口
* @Package Name: Database
* @Author: Forrest Gump
[email protected] * @Modifications:
* No20020523-100:
* odbc_fetch_into()參數位置第二和第三個位置調換
* John Johnson
[email protected] * @See: (參照)
*/
class Database
{
……
}
5.3.3. 方法注釋
/**
* @Purpose:
* 執行一次查詢
* @Method Name: Query()
* @Parameter: string $queryStr SQL查詢字符串
* @Return: mixed 查詢返回值(結果集對象)
*/
function($queryStr){……}
5.3.4. 屬**或變量注釋
/**
* @Purpose:
* 數據庫連接用戶名
* @Attribute/Variable Name: mDbUserName
* @Type: string
*/
var mDbUserName;
5.3.5. if (0)來注釋外部代碼塊
有時需要注釋大段的測試代碼,最簡單的方法就是使用if (0)塊:
function example()
{
great looking code
if (0) {
lots of code
}
more code
}
你不能使用/**/,因為注釋內部不能包含注釋,而大段的程序中可以包含注釋。
5.3.6. 目錄文檔
所有的目錄下都需要具有README文檔,其中包括:
・ 該目錄的功能及其包含內容
・ 一個對每一文件的在線說明(帶有link),每一個說明通常還應該提取文件標頭的一些屬**名字。
・ 包括設置、使用說明
・ 指導人們如何連接相關資源:
o 源文件索引
o 在線文檔
o 紙文檔
o 設計文檔
・ 其他對讀者有幫助的東西
考慮一下,當每個原有的工程人員走了,在6個月之內來的一個新人,那個孤獨受驚嚇的探險者通過整個工程的源代碼目錄樹,閱讀說明文件,源文件的標頭說明等等做為地圖,他應該有能力穿越整個工程。
6. 其他
・ 采用面向對象的設計方法;
理由
毫無疑問這是最接近人們自然思維的方法,可能前期會覺得沒有直接書寫來得快,能否試著保留自己的看法?好戲在後頭!
・ 類的定義采用一個文件一個類,並且類名和文件名相同;
理由
o 越來越多的人接受了這種做法
o 事實證明這種方法使得項目的邏輯結構更清晰
・ 類定義文件中,定義體之外不得出現諸如echo、print等輸出語句;
理由
出現這樣的語句,應該當做出現bug來看。
・ 輸出網頁的頁面不出現SQL語句
理由
這是n層結構的編程思想所致,每層的任務不同,雖然可以越權行使,可能這樣很快捷,但我們不贊成這麼干。
・ 進行SQL執行的數據必須進行有效**檢測
特殊符號:
對於MS SQL Server,’%_[ ] 這些符號都是在書寫SQL語句中的特殊含義字符,在SQL執行前需要對這些字符進行處理。
腳本符號:
對於
PHP腳本標記,如<??><%%><?php?><script lang<script language="PHP"></script>,在進入數據庫前需要檢測處理。
理由
這是數據庫編程的一個約定,很多參考書上也是這麼說,這裡需要強調一下。
・ 在Html網頁中盡量不要穿插PHP代碼
循環代碼和純粹變量輸出(類似於<?=$UserName?>)除外。
理由
o 需要說明的是我們工作的上游,頁面設計者的工作,假如在頁面中穿插代碼,將破壞結構,這應當是我們需要避免的。
o 在這裡的PHP代碼只負責顯示,多余的代碼顯然是不應該的。
・ 沒有含義的數字
一個在源代碼中使用了的赤裸裸的數字是不可思議的數字,因為包括作者,在三個月內,沒人它的含義。例如:
if (22 == $foo) { start_thermo_nuclear_war(); }
else if (19 == $foo) { refund_lotso_money(); }
else if (16 == $foo) { infinite_loop(); }
else { cry_cause_im_lost(); }
在上例中22和19的含義是什麼呢?如果一個數字改變了,或者這些數字只是簡單的錯誤,你會怎麼想?
使用不可思議的數字是該程序員是業余運動員的重要標志.
你應該用define()來給你想表示某樣東西的數值一個真正的名字,而不是采用赤裸裸的數字,例如:
define("PRESIDENT_WENT_CRAZY", "22");
define("WE_GOOFED", "19");
define("THEY_DIDNT_PAY", "16");
if (PRESIDENT_WENT_CRAZY == $foo) { start_thermo_nuclear_war(); }
else if (WE_GOOFED == $foo) { refund_lotso_money(); }
else if (THEY_DIDNT_PAY == $foo) { infinite_loop(); }
else { happy_days_i_know_why_im_here(); }
現在不是變得更好了麼?
7. PHP文件擴展名
常見的PHP文件的擴展名有:html, .php, .php3, .PHP4, .pHtml, .inc, .class...
這裡我們約定:
・ 所有浏覽者可見頁面使用.Html
・ 所有類、函數庫文件使用.PHP
理由
・ 擴展名描述的是那種數據是用戶將會收到的。PHP是解釋為Html的。
8. PHP代碼標記
統一使用<?php ?>,只輸出變量時<?=$username?>PHP 編程風格規范
第1章 命名規范
1.1變量
1.1.1全局變量
全局變量使用$g_開頭,如$g_data_list。
1.1.2 一般變量
一般的變量使用小寫字母命名,單詞之間使用下劃線分隔。
變量名字應該使用名詞或者形容詞+名詞的方式。如$value,$new_value。
1.1.3 臨時變量
不要將在循環中頻繁使用的臨時變量如$i,$j等用於其它用途。
1.2 函數
函數采用小寫字母命名,單詞之間使用下劃線分隔。
函數的命名建議使用動詞+名詞的方式,如get_user_img。
完成一組功能的函數放到一個文件中,存放函數的文件采用function_name.func.PHP命名。
1.3 類
類使用英文的大小寫來分隔單詞,包括首個單詞,所有單詞的首字母大寫,如PageManager;
在類中,方法放到屬性定義前邊、公用方法放到專用方法前邊;
一般情況下,一個類對應到一個文件;
當一些類關系緊密時,可以存放在一個文件中;
存放類的文件采用ClassName.class.PHP方式命名。
1.4 方法
方法使用英文的大小寫來分隔單詞,除首個單詞外,其他單詞的首字母大寫,如getCurrentPage();
不要采用不常用的縮寫,如where2go();
使用常用的縮寫時,只大寫首字母,如getHtml()。
第2章 版式規則
2.1 語義分隔
各個函數、方法之間應該采用空行間隔;
同一個函數中聯系緊密的語句之間可以不換行,其他情況需要換行。
2.2 空格規則
2.2.1 邏輯運算符前後必須加空格
正確 $a == $b;
錯誤 $a==$b;
$a ==$b;
備注 -
正確 $a++; $a--;
錯誤 $a ++; $a --;
備注 加一減一運算符不能加空格。
2.2.2 多個參數分隔時必須加空格
正確 $g_pro , $g_user , g_show;
get_db_info($host, $user, $passwd);
錯誤 $g_pro,$g_user,$g_show;
get_db_info($host,$user,$passwd);
備注 -
2.2.3 語法關鍵字後必須加空格
例如:If, for , while, switch …..
正確 for ($i = 0; $i < 10; $i++)
錯誤 for($i = 0; $i < 10; $i++ )
備注 -
2.3 字符串和變量連接規則
字符串與變量連接使用'.'號時,必須在'.'前後加空格,使用"號時,必須在變量前後加"{}"。
正確 $my_name = 'file_' . $var1;
$my_name = "file_{$var1}";
錯誤 $my_name = "file_'.$var1;
$my_name = "file_$var1";
備注 -
2.4 圓括號規則
函數名後括號不需要加空格、語法關鍵字後的括號必須加空格。
正確 for ($i = 0; $i < 10; $i++)
strlen($my_name);
錯誤 for($i = 0; $i < 10; $i++ )
strlen ($my_name);
備注 -
2.5 花括號規則
花括號必須為上下對應。
正確
if ($a)
{
$b = $a;
}
錯誤 if ($a){
$b = $a;
}
備注 -
2.6 數組定義規則
數組定義和使用時中key值前後必須加單引號。
PHP 代碼:
正確
$user_info = array(
'name' => '',
'gender' => ''
);
echo $user_info['name'];
錯誤
$user_info = array(
name => '',
gender => ''
); echo $user_info[name];
備注 -
2.7 SQL規則
在PHP中嵌入的SQL語句關鍵字全部采用大寫;
表名和字段名要用反引號(`)引起來以防止因為字段名中包含空格而出現錯誤;
數據值兩邊用單引號''包括,並且應確保數據值中的單引號已經轉義以防止SQL注入。
正確 $sql = "SELECT `user`.`name` FROM `user` WHERE `id` = '$id' LIMIT 1";
錯誤 $sql = "select name.user from name where id = $id ";
備注 -
第3章 注釋規則
3.1 一般規則
不寫不必要的注釋;只有當代碼不能很好地說明邏輯時,才用注釋補充;
把注釋看成程序的一部分,在編寫/維護代碼時同時編寫/維護注釋;
注釋完全采用PHPDocumentor的規范,以方便用其生成API級文檔。
3.2 詳細規則
請參見PHPDocumentor手冊。下邊給出各個部分的注釋示范。
3.2.1 版權信息
注釋名稱 版權信息
注釋示范 //
// +----------------------------------------------------+
// | PHPDocumentor |
// +----------------------------------------------------+
// | Copyright (c) 2000-2003 Joshua Eichorn |
// | Email
[email protected] |
// | Web http://www.PHPdoc.org |
// +----------------------------------------------------+
// | This source file is subject to PHP License |
// +----------------------------------------------------+
//
備注 使用//來標示版權信息,以免和PHPDocumentor的page-level DocBlock發生沖突
3.2.2文件頭注釋示例
注釋名稱 文件頭注釋
注釋示范
PHP 代碼:
/**
* All abstract representations of inline tags are in this file
* @package PHPDocumentor
* @subpackage InlineTags
* @since separate file since version 1.2
* @version $Id $
*/
備注
1 文件頭注釋需要指明所屬的包和子包
2 在@version中加上$ID,以方便使用CVS管理文件
3.2.3 類注釋示例
注釋名稱 類注釋
注釋示范
PHP 代碼:
/**
* Use this element to represent an {@}inline tag} like {@}link}
* @see parserStringWithInlineTags
* @package PHPDocumentor
* @subpackage InlineTags
* @author Greg Beaver <
[email protected]>
* @since 1.0rc1
* @version $Revision: 1.21.2.6 $
* @tutorial inlinetags.pkg
*/
備注 -
3.2.4 類屬性注釋示例
注釋名稱 類屬性注釋
注釋示范
PHP 代碼:
/**
* Element type
*
* Type is used by many functions to skip the hassle of
*
* <code>
* if get_class($blah) == 'parserBlah'
* </code>
* always "inlinetag"
* @var string
*/
var $type = 'inlinetag';
備注 -
3.2.5 函數/類方法注釋示例
注釋名稱 函數/類方法注釋
注釋示范
PHP 代碼:
/**
* @return string always ''
* calculate the short description of a DocBlock
* @see parserStringWithInlineTags::getString()
* @see parserStringWithInlineTags::trimmedStrlen()
*/
function getString()
{
return '';
}
-