วันอังคารที่ 7 ธันวาคม พ.ศ. 2553

php coding standard

ผมอาจจะแปลผิดมั่งถูกมั่ง ถ้าอ่านแล้วไม่รู้เรื่องให้ไปอ่านต้นฉบับที่นี่ครับ :D
http://www.dagbladet.no/development/phpcodingstandard/

ชื่อ Class


- ตั้งชื่อให้ตามสิ่งที่มันเป็น
- ชื่อผสมที่มากกว่า 3 คำอาจจะทำให้สับสน, ตรวจสอบการออกแบบว่า object ของคุณมีหน้าที่รับผิดชอบมากเกินไปหรือเปล่า
- อย่าพยายามที่จะนำชื่อ class แม่ มาผสมในคลาสที่ได้รับการสืบทอด ชื่อคลาสควรจะเป็นชื่อที่อธิบายถึงตัวมันเอง
- อาจจะใช้ suffix เพื่อระบุหน้าที่ของ class

ชื่อ method และชื่อ function


- ปกติ method และ function จะทำงานบางอย่าง, ชื่อของมันจึงควรบอกได้ชัดเจนว่ามันทำอะไร
- ใช้ suffix เพื่อระบุข้อมูลที่คืนมาจาก function
--- Max - ค่าสูงสุด
--- Cnt - จำนวนข้อมูล
--- Key - ค่า key
--- ตัวอย่างเช่น pageMax, pageCnt,
- ใช้ prefix เพื่อระบุถึงหน้าที่ของ function
--- is - เพื่อบอกคำตอบของคำถาม
--- get - นำค่าออกมาใช้
--- set - นำค่าไปบันทึก
--- ตัวอย่างเช่น isEmail, setBackgroundColor

ถ้าพบคำย่อซึ่งเป็น uppercase ทั้งหมด
ให้เขียน uppercase เฉพาะตัวแรกเท่านั้น
อย่างเช่น UserID ให้เปลี่ยนเป็น UserId แทน

รูปแบบชื่อคลาส


- ใช้ uppercase เป็นตัวแบ่งคำในชื่อคลาส
- ตัวอักษรตัวแรกเป็น uppercase
- ไม่ใช่ _


รูปแบบชื่อของคลาสไลบรารี่


- ใช้แทน namepsace
- เป็นตัวอักษรสองตัวเพื่อแบ่งแยกกลุ่ม class ที่มาจากที่ต่างๆ กันเช่น คนที่ชื่อ Somchai Jaidee
SjInputValidation


รูปแบบชื่อ method


- ใช้กฎแบบเดียวกับชื่อคลาส
- ** ในบาง standard จะยกเว้นตัวอักษรตัวแรกเป็นตัวเล็ก และอาจจะ _ นำหน้าชื่อ method สำหรับ private หรือ protected method


ชื่อ member attribute


- ควรจะ (ไม่บังคับ) ขึ้นต้นด้วยตัวอักษร m เพื่อให้สามารถแยกชื่อ method กับชื่อ attribute ในกรณีที่มีชื่อซ้ำกัน
- หลังจากตัวอักษร m ให้ใช้กฎเดียวกับการตั้งชื่อ class
- ใช้ r ตามหลัง m เพื่อแทนตัวแปร reference


ชื่อ parameter ของ method


- ตัวอักษรตัวแรกควรจะเป็นตัวเล็ก
- คำต่อไปจะมีวิธีตั้งชื่อเหมือนชื่อ class


ชื่อตัวแปร


- ใช้ตัวอักษรตัวเล็กเสมอ
- ใช้ _ เป็นตัวแบ่งคำ

ชื่อ element ของ array


- ใช้ _ เป็นตัวแบ่งคำ
- ไม่ใช่ - เป็นตัวแบ่งคำ
- จะต้องมี ' ใน key ของ array element
$_POST[name] ผิด
$_POST['name'] ถูก


ตัวแปร reference และ function return reference


- ควรจะนำหน้าด้วยตัวอักษร r


ตัวแปร global


- ควรจะขึ้นต้นด้วยตัวอักษร g

constant


- เป็น uppercase หมด และแบ่งคำด้วย _


ตัวแปร static


- อาจจะขึ้นต้นด้วย s


ชื่อ function


- เป็น lower case หมด และแบ่งคำด้วย _


นโยบายการตรวจสอบค่า error ที่ return จาก function


- ตรวจสอบ error จากค่าที่ return ทุกครั้ง ยกเว้นต้องการเพิกเฉยกับ error
- แทรกการแสดงคำอธิบาย error  ทุกๆ error ที่อาจเกิดขึ้น

นโยบายการใช้ {}


if ($condtion)
{
}
และ
if ($condtion){
}
ตามความเห็นของผมถ้าความซับซ้อนสูงควรจะใช้แบบแรก
เพราะเวลาใช้ editro จะหา { } ที่คู่กันได้ง่าย
แต่แบบหลังจะดีกว่าถ้าเป็นคำสั่งง่ายๆ ทำให้จำนวนบรรทัด sourcecode ไม่ยาวมาก

นโยบายการใช้ identation/tabs และ space


-ในแต่ละ indent จะเท่ากับ space 4 ช่องในแต่ละระดับ
-อย่าใช้ tabs, ใช้ space แทน. editor ส่วนใหญ่สามารถปรับ tab ให้เป็น space
-ใช้ indent เท่าที่จำเป็นอย่ามากเกินไป


นโยบาย การใช้ parens () กับ Keywords และ Functions


- อย่าใช้ parens ถัดจาก keywords. ให้เว้นช่องว่างไว้
- ใช้ parens ติดกับชื่อฟังชั่น
- อย่าใช้ parens ใน return statements ถ้าไม่จำเป็น
    if (condition)
    {
    }
    strcmp($s, $s1);
    return 1;


อย่าเขียนคำสั่งปฎิบัติการจริงใน object constructor


ภายใน constructor จะมีเฉพาะการกำหนดค่าเริ่มต้นให้กับตัวแปรและ/หรือประมวลผลคำสั่งที่ไม่มีทางที่จะเกิดข้อผิดพลาด

   class Device
   {
      function Device()    { /* initialize and other stuff */ }
      function Open()  { return FAIL; }
   };

   $dev = new Device;
   if (FAIL == $dev->Open()) exit(1);


ทำให้ฟังค์ชั่นเรียกใช้เหมือนเดิมได้หลายครั้ง


function ไม่ควรมีตัวแปร static ที่จะทำให้ไม่สามารถใช้งานเหมือเดิม


ใช้ block ในโครงสร้าง switch


switch (){
  case 1:
  case 2:
  {

  }
  break;
}


การใช้ ?:


เพื่อให้อ่านได้ง่ายให้ นำ condition ไว้ใน parens
ถ้าเป็นไปได้ตัวทดสอบควรจะเป็น function ง่ายๆ
วาง action ของ then และ else ไว้แยกบรรทัด ยกเว้นมันสามารถเขียนให้อ่านได้ง่ายในบรรทัดเดียว


การจัดเรียงส่วนประกาศตัวแปร


- ทำให้อ่านได้ง่าย
- กลุ่มของการกำหนดค่าเริ่มต้นควรจัดให้เป็นกล่องซี่เหลี่ยม
- & ควรจะอยุ่ติดกับ type ไม่ใช่ name


ควรจะมี เพียงแค่ statement เดียวในแต่ละบรรทัด


ยกเว้น statement มีความสัมพันธ์กันมาก


method สั้นๆ


- จำนวนบรรทัดควรจะจำกัดอยู่ภายใน 1 หน้า


ให้คำอธิบาย Null Statement


- เพื่อให้แสดงถึงว่าโค้ดทำงานถูกต้อง และ statement แยกออกจาก statment ที่ตามมาชัดเจน


อย่าใช้ค่าที่ไม่ใช่ 0 มาแทนค่าที่เป็นเท็จ


เช่น
if (false != f())
ถ้า function คืนค่า -1 แทน 0 จะทำให้คำสั่งเดิมทำงานเพี้ยนไป
ดังนั้นควรใช้ return ค่าเฉพาะ 0 เท่านั้น
if (f()) แทนเพื่อกันปัญหาที่อาจจะเกิดขึ้น
และไม่ควรใช้กับเงื่อนไข boolean ที่คืนค่าตัวเลข
if (!f()) ควรเขียนเป็น if (0 == f()) แทนจะเหมาะสมกว่า
ในการตั้งชื่อ function boolean ควรจะใช้ IsValid แทน checkValid

หลีกเลี่ยงการแนบ assignment ใน statement อื่นๆ


ถ้ามันทำให้อ่านยากขึ้น ยกเว้นแต่มันช่วยให้เขียนได้ง่ายขึ้นและเป็นส่วนที่ใช้เป็นประจำ
   while ($a != ($c = getchar()))
   {
      process the character
   }


comment


คำอธิบายของบอกเรื่องราว
- อธิบายถึงระบบ, โดยคาดว่ามันจะถูก robot ดึงแปลงไปอยู่ในรูป manual.
คำอธิบายคลาสเป็นส่วนหนึ่งของเนื้อเรื่อง, คำอธิบาย ลายเซ็นของ method (ชื่อ method และจำนวน parameter)
ก็เป็นส่วนหนึ่งของเนื้อเรื่อง, argument ก็เป็นอีกส่วนหนึง และส่วน implement ก็เป็นอีกส่วนหนึ่ง
ทุกๆ ส่วนควรจะถูกนำมาแสดงเพื่อบอกข้อมูลให้กับผู้อื่น เพื่อให้ทราบว่าคุณกำลังทำอะไร และเพราะอะไรจึงทำเช่นนั้น

อธิบายถึงการตัดสินใจ
ทุกๆ จุดซึ่งคุณตัดสินใจที่จะทำอะไรให้เขียนคำอธิบายว่าคุณเลือกวิธีไหนและเพราะอะไร

ใช้ headers
ใช้ระบบดึงเอกสาร อย่างเช่น ccdoc.
ส่วนถัดไปจะอธิบายถึงการใช้ cdoc เพื่ออธิบาย class และ method
headers ถูก structure ในทางที่พวกเขาสามารถ

ทุกๆ ส่วนของโปรเจคจะมี คำอธิบายภาพรวม

Gotcha Keyword แสดงคำอธิบายที่มีลักษณะเฉพาะตัว เพื่อช่วยในการดูแลรักษาและพัฒนาระบบ
:TODO: topic
หมายความว่ามีสิ่งที่ต้องทำที่นี่อีกอย่าลืม

:BUG: [bugid] topic
หมายถึงมี bug ที่รู้ที่นี่อีก, อธิบายมันและอาจจะกำหนดค่า bug ID.

:KLUDGE:
ถ้าคุณได้บางสิ่งที่แย่ไป อธิบายว่าควรจะทำอย่างไรในครั้งถัดไป ถ้าคุณมีเวลามากกว่านี้

:TRICKY:
บอกว่าโค้ดส่วนนี้เป็นเทคนิคพิเศษ ดังนั้นอย่าพยายามเปลี่ยนหากยังไม่ได้พิจารณาขั้นตอนทำงานโดยละเอียด

:WARNING:
แจ้งให้ระวังบางสิ่ง

:PARSER:
บางครั้งกำลังมีปัญหากับการ parse อธิบายว่าตอนนี้ได้ตรวจสอบอะไรไปแล้วบ้าง เพื่อจะใช้วิธีอื่นๆ ในการหาพยายามหาจุดที่เป็นปัญหาแทน

:ATTRIBUTE: value
คุณสามารถกำหนด attribue ที่คุณสร้างขึ้นเองได้

การจัดระเบียบ
ให้ Gotcha keyword เป็นสัญลักษณ์แรกใน comment
คำอธิบายอาจจะมีหลายบรรทัดแต่บรรทัดแรกควรจะเป็นข้อสรุปที่มีความหมายสมบูรณ์ในตัวเอง
ชื่อของผู้เขียน และวันที่ควรจะเป็นส่วนหนึ่งของคำอธิบาย.
แม้ว่าระบบ repository สามารถไล่ตามได้ว่าใครเป็นคนเขียนคำอธิบายนี้แต่ก็ต้องใช้เวลาในการหาว่าใครเป็นคน
เพิ่มข้อมูลนี้เข้าไป. บ่อยครั้งที่ gotcha อยู่นานเกินไปกว่าที่มันควรจะเป้น. การแทรกวันที่ช่วยให้โปรแกรมเมอร์คนอื่น
สามารถตัดสินใจได้ว่าจะทำอย่างไรกับ comment นี้ .การแทรก comment นี้ช่วยให้เรารู้ว่าจะสามารถสอบถามข้อมูลเพิ่มได้จากใคร
   // :TODO: tmh 960810: possible performance problem
   // We should really use a hash table here but for now we'll
   // use a linear search.

   // :KLUDGE: tmh 960810: possible unsafe type cast
   // We need a cast here to recover the derived type. It should
   // probably use a virtual method or template.


ผู้อ่าน document สองกลุ่ม


- Class Users
  ต้องการข้อมูลเกี่ยวกับ class interface วิธีการใช้ method และประกาศ object ฯลฯ ซึ่งจะสามารถอ่านได้จากส่วน header ของไฟล์
  โดยไม่ต้องการข้อมูลรายละเอียดเกี่ยวกับ algorithm ที่ใช้ใน function
- Class Implementors
  ผู้ผลิต class จำเป็นต้องรู้ว่า class ถูกสร้างขึ้นอย่างไร. comment ชนิดนี้จะอยู่ใน souce file ที่สร้าง class
  จะอธิบาย algorithm และการตัดสินใจออกแบบ. และบล้อก comment ใน method ควรจะมีคำอธิบายเพิ่มขึ้นอีก

เอกสารของ directory


ทุกๆ directory ควรจะมีไฟล์ README ซึ่งอธิบาย
- จุดประสงค์ของ directory และอะไรที่มันบรรจุอยู่ข้างในมัน
- คำอธิบาย 1 บรรทัดสำหรับแต่ละไฟล์
- ผู้ที่เกี่ยวข้องกับแหล่งที่มาต่างๆ
--- directory, เอกสารออนไล์, เอกสารกระดาษ, เอกสารการออกแบบ
- อื่นๆ
เอกสารสร้างนี้จช่วยผู้ที่จะแก้ไขโค้ดไม่ต้องไล่อ่านโค้ดในทุกๆ ไฟล์เพื่อหาข้อสรุป


สถานะ open/closed


การระบุสถานะ class ว่า open หรือ close
- open หมายถึงว่า class นั้นสามารถที่จะขยายเพิ่มเติมได้
- closed หมายถึงปิดการแก้ไข แต่ไม่ได้หมายถึงปิดการ extension.
เมื่อคลาสถูกทดสอบ และตรวจสอบว่ามีประสิทธิภาพดีแล้ว, คุณไม่จำเป็นต้องแก้ไข class นั้นมากให้ extend แทน
การตั้งสถานะให้ open/closed ระบบที่ขยายขึ้นมาจะไม่แก้ไขโค้ดที่ทำงานอยู่ก่อนหน้านี้.


อย่าใช้ floating point ในที่ๆ จำเป็นต้องใช้ค่า discrete


อย่างเช่นใน loop for
อย่าใช้ == และ != กับค่า float ให้ใช้ >= และ <= แทน

ใช้ if (0) แทน comment


จะเขียนง่ายกว่า

Accessor Styles


Get/Set
   class X
   {
      function GetAge()        { return $this->mAge; }
      function SetAge($age)    { $this->mAge = $age; }
      var $mAge;
   };

Attributes as Objects
   class X
   {
      function         Age()          { return $this->mAge; }
      function         Name()         { return $this->mName; }

      var              $mAge;
      var              $mName;
   }

   $x = new X;

   // Example 1
   $age = $x->Age();
   $r_age = &$x->Age(); // Reference

   // Example 2
   $name = $x->Name();
   $r_name = &$x->Name(); // Reference


ใช้ tag  <?php ?>


tag รูปแบบอื่นอาจถูกระงับการใช้งานในบาง server


No Magic Numbers


ไม่ใช่ตัวเลข แต่กำหนดค่าตัวเลขเป็น CONSTANT แทน

ช่องว่างระหว่าง token


ในแต่ละคู่อันแรกจะแทนแบบที่ผิดอันที่สองจะแทนแบบที่ถูกต้อง

<?php

$i=0;
$i = 0;

if(( $i<2 )||( $i>5 ))
if ( ($i < 2) || ($i > 5) )

foo ( $a,$b,$c )
foo($a, $b, $c)

$i=($j<5)?$j:5
$i = ($j < 5) ? $j : 5

?>


โครงสร้างควบคุม




if ($a != 2) {
$a = 2;
} else {
$a = 7;
}

if ($a != 2) {
$a = 2;
} elseif ($a == 3) {
$a = 4;
} else {
$a = 7;
}

if (($a == $b)
&& ($b == $c)
|| (Foo::CONST == $d)
) {
$a = $d;
} elseif (($a != $b)
|| ($b != $c)
) {
$a = $c;
} else {
$a = $b;
}



Ref:
http://www.dagbladet.no/development/phpcodingstandard/
http://www.evolt.org/node/60247
http://framework.zend.com/manual/en/coding-standard.coding-style.html

ไม่มีความคิดเห็น:

แสดงความคิดเห็น