บรรทัดว่าง (Blank Line)
ใช้บรรทัดว่างเพื่อแยกโคดภายใน method
ให้เป็นสัดส่วน
ใช้บรรทัดว่าหนึ่งหรือสองบรรทัดระหว่างแต่ละ
methods
ลำดับของโคดภายใน class
class Order
{
// final attributes
// attributes
// constructors
// methods
}
ให้ private methods ขึ้นก่อน method ที่เรียกใช้มัน
แต่ต้องอยู่หลัง constructors เว้นแต่ว่า constructors จะใช้มัน
โครงสร้างการเขียน File
"package" (ถ้าใช้) จะต้องมาเป็นอันดับแรก
"import" เป็นอันดับที่สอง
ตามมาด้วยคำบรรยาย (comment) ที่ไม่ได้ใช้สำหรับสร้าง
javadoc
ทุกๆ เอกสารของที่จะเป็น javadoc ให้อยู่ต่อจากนี้
ให้ class เป็นอันดับสุดท้าย
เงื่อนไขนี้ใช้เฉพาะเมื่อหนึ่ง file มีแค่หนึ่ง
class (ยกเว้น inner classes)
Example:
package misc ;
import java.io.* ;
import java.net.* ;
/** this class does cool stuff
@author Joe Programmer
*/
class SpaceMonkey
{
...
}
จำนวนตัวอักษรในแต่ละบรรทัด
พยายามไม่เขียนให้แต่ละบรรทัดมีจะนวนอักษรมากกว่า
120 ตัวอักษร แต่โดยมากแล้วเราควรจะเขียนโคดให้น้อยกว่า 80 ตัวอักษรในหนึ่งบรรทัด
และถ้าโคดของเรา เริ่มต้นย่อหน้าก็อยู่ขวามากแล้ว ก็ควรจะยกโคดส่วนนั้นขึ้นไปเป็นอีก
methods
เหตุผล : การแก้ไข และการพิมพ์(printing)
ที่มีอยู่ทั่วไป จะใช้งานโคดง่ายกว่าถ้าแต่ละบรรทัดมีไม่เกิน 120 ตัวอักษร อีกทั้งบรรทัดยาวๆ
ยังสร้างปัญหาในการทำงานกับมัน
วงเล็บ
นอกจากเราจะใช้วงเล็กเพื่อกำหนดลำดับการทำงานของสมการแล้ว
เรายังควรใช้วงเล็บทำให้สมการดูง่าย เมื่อมันมีขนาดใหญ่ หรือซับซ้อน
การประกาศต่างๆ (Identifiers)
ทุกๆ การประกาศ ควรใช้ตัวอักษร ('A' ถึง
'Z' และ 'a' ถึง 'z') และตัวเลข ('0' ถึง '9') เท่านั้น พยายามอย่าใช้ขีดเส้นใต้('_'
: underscores) หรือ เครื่องหมายบาท ('฿') หรือ ตัวอักษรที่ไมใช่ ascii (non-ascii
characters)
"Hungarian Notation violates OO abstraction"
ก็พยายามไม่ใช้
Classes และ interfaces
ในการประกาศ class และ interface เราจะใช้ภาษาอังกฤษทั้งตัวใหญ่และตัวเล็ก
โดยให้ตัวอักษรตัวแรกของแต่ละคำให้เป็นตัวใหญ่ (Uppercase) รวมทั้วตัวอักษรตัวแรกของชื่อด้วย
นอกนั้นให้ใช้อักษรตัวเล็กทั้งหมด ยกเว้นว่าจะเป็นตัวย่อ ซึ่งต้องเป็นตั้วใหญ่
ก็ให้ใช้อักษรตัวใหญ่ทั้งหมดครับ
Examples:
Customer
SalesOrder
TargetURL
URLTarget
Packages
ชื่อของ Package ให้เป็นอักษรตัวเล็กเท่านั้น
(lower case) และพยายามใช้ตัวอักษรให้น้อยกว่าแปด (8) ตัวอักษร ให้พยายามหลีกเลี่ยงการใช้คำหลายคำในชื่อ
package
Examples:
common
core
lang
สำหรับการประกาศอื่นๆ
ทุกๆ การประกาศไม่ว่าจะเป็น including(ให้ใช้ตามความจำเป็น)
attributes, variables, methods และ parameters ให้พยายามตั้งชื่อที่เป็นสากล
รวมทั้งการประกาศ final (ให้ใช้อักษรตัวใหญ่ทั่งหมด ตามที่นิยมกันในภาษา C แม้ว่าจะขัดกับหลักของ
OO ก็ตาม) สำหรับตัวอักษรตัวแรกของแต่ละคำให้ใช้อักษรตัวใหญ่ ยกเว้นอักษรตัวแรกของชื่อ
อักษรที่เหลือทั้งหมดให้ใช้ตัวเล็ก แต่ถ้าคำใดเป็นอักษรย่อ ก็ให้ใช้ตัวอักษรตัวใหญ่ทั้งหมด
ยกเว้นอักษรย่อนั้นเป็นคำแรกของชื่อ
Examples:
customer
salesOrder
targetURL
urlTarget
ชื่อพิเศษ Getters และ Setters
Methods ที่ทำหน้าที่กำหนดสถานะ มักจะใช้คำนำหน้าว่า
set ในชื่อของ method
Methods ที่ส่งค่าตัวแปลกลับ (return)
เป็น boolean object มักใช้คำนำหน้าว่า is ในชื่อของ method นอกนั้น
methods ที่มีการส่งค่าสถานนะของ object กลับให้ใช้คำนำหน้าว่า get
ในชื่อ method
Examples:
setEnabled()
getName()
isEnabled()
การเขียนคำชี้แจง (Comment)
ให้ใช้คำชี้แจงรูปแบบ // สำหรับจุดหลักๆ
ของคำชี้แจง (comment).
สำหรับคำชี้แจงรูปแบบ /** */ ให้ใช้เพื่อสร้าง
javadoc
พยายามใช้คำชี้แจงรูปแบบ /* */ สำหรับคำชี้แจงทั่วไปที่ไม่ค่อยเกียวกับโคด
การเขียนคำชี้แจงเพื่อสร้าง Javadoc
Javadoc ถูกใช้เพื่อสร้างเอกสารที่บอกถึงความเชื่อมโยง
class, attributes and methods ที่ถูกใช้โดย classes อื่นๆ คำชี้แจงจะต้องเขียนติดอยู่กับสิ่งๆที่เราต้องการ
เพื่อให้อยู่ในเอกสาร (javadoc)
คำชี้แจงของ Javadoc ไม่จำเป็นสำหรับ methods
ที่ไม่ค่อยสำคัญ อย่างเช่น
public static void main( String[] args )
หรือ
public int getX()
คำชี้แจง Javadoc ไม่จำเป็นสำหรับ parameters
ที่ไม่ค่อยสำคัญ อย่างเช่น
public void setX( int newX )
และคำชี้แจง Javadoc ก็ไม่จำเป็นสำหรับ
class ที่ไม่ต้องการให้ Class อื่นๆ เข้ามาใช้ อย่างเช่น servlets และ EJB's
ก่อนที่คุณจะส่งโคดของคุณไปให้กลุ่ม คุณจะต้องใส่
JavaDoc และต้องคิดถึงการให้ตัวอย่างการใช้งานพร้อมผลลัพท์ เพื่อให้แน่ใจว่า
เอกสารของคุณสร้างมาให้คนอ่าน และไม่วุ่นวาย
ถ้าคำชี้แจง JavaDoc สามารถเขียนได้ภายในหนึ่งบรรทันให้คุณเขียนในลักษณะนี้:
/** Used to mark spots */
int x ;
แต่ถ้าคำชี้แจง JavaDoc ไม่สามารถเขียนได้ภายในหนึ่งบรรทัด
ก็ให้เขียนในลักษณะนี้:
/** Set how much to grow when growth is needed. <p>
Smaller values will usually save memory, but frequent
reallocation may take a lot of time. <p>
@param howMuch The number of extra ints to allocate when
memory reallocation is required. Values must be greater than
zero. <p>
*/
public void setExtra( int howMuch )
{
เราสามารถใช้ HTML tags <p>
และ <pre> ได้ โดย <p> หมายถึงการสิ้นสุดย่อหน้า ส่วน
<pre> .. </pre> เพื่อกำกับส่วนที่ต้องการแสดงอักษรแบบ
fixed font และให้แสดงช่องว่างด้วย (ปกติ html จะแสดงช่องว่างหลายช่องด้วยช่องเดียว)
JavaDoc ยังให้คุณใช้ HTML ต่างๆ ที่คุณต้องการ
แต่ขอให้คุณไม่ใช้ header tags (<h1>, <h2>, etc.)
แต่จะเป็นการดีถ้าให้ใช้ <b>.. </b> เพื่อทำตัวหนา
หรือ <i>.. </i> แทนตัวเอียงแทนที่จะใช้ header tags
JavaDoc จะตัดบรรทัดแรกของคำชี้แจงออก
เพื่อนำไปใช้เป็นคำอธิบายสั้นๆ ใน table of contents เราคงต้องคำถึงถึงด้วยว่า
เราคงต้องคิดด้วยว่าจะตัดที่ท่อนไหน JavaDoc กำหนดการตัดโดยใช้บรรทัดว่าง แต่ไม่นับเครื่องหมายคำถามที่ตามด้วยช่องว่าง
หรือไม่ก็ ตามด้วย <p> tag (ให้ใช้บรรทัดว่างระหว่างประโยคและ <p>
tag)
สุดจะแปลครับ :ใครแปลได้ช่วยส่งมาบอกผมด้วย
Note that JavaDoc splits out the first line of any JavaDoc comment to use
for a sort of "table of contents". You might want to think about where you
want this line division to happen. JavaDoc defines this as a period followed
by a space. So question marks followed by a space don't count! Nor does a
period followed by a <p>tag! Use a space between the period and
the <p> tag.
Classes
JavaDoc สำหรับเอกสารอธิบาย class ต้องประกอบด้วย:
- บทสรุป และสาระสำคัญ
- คำอธิบายในรายละเอียด
- ตัวอย่างโคดและตัวอย่างการใช้ class
- รายชื่อของผู้เขียนโดยใช้ JavaDoc @author
tag
เพราะ "feature" ใน JavaDoc ทำให้เราต้องใส่เครื่องหมายดอกจันไว้หน้าบรรทัดเพื่อรักษาย่อหน้าของเราไว้.
Example:
/** A vector class optimized for working with ints. <p>
Like the Vector object, except rather than tracking a dynamic
array of pointers to different objects, this is simply a
dynamic array of ints. The advantage is speed and memory
savings.<p>
Example:
<pre>
*
* // report longest lines
* TextFileIn f = new TextFileIn("blather.txt");
* IntVector v = new IntVector();
* int longestLine = 0 ;
* boolean done = false ;
* while ( ! done )
* {
* String s = f.readLine();
* if ( s == null )
* {
* done = true ;
* }
* else
* {
* int sLength = s.length() ;
* if ( sLength > longestLine )
* {
* longestLine = sLength ;
* }
* v.append( sLength );
* }
* }
* f.close();
* System.out.println("The longest lines are on line numbers:");
* for ( int i = 0 ; i < v.length() ; i++ )
* {
* if ( v.get( i ) == longestLine )
* {
* System.out.println( i );
* }
* }
</pre>
@author Adam Baum
@author Justin Case
*/
public class IntVector
{
Methods
สำหรับ method ของเอกสาร JavaDoc จะต้องมี:
- บทสรุปสาระสำคัญของ method
- ใส่ทุกคำอธิบายในรายละเอียด (มากเท่าที่จะใส่ลงไปได้)
- รายการของ prameter ให้เขียนในรูปแบบ
@param tag (ถ้ามี parameters)
- ค่าที่ส่งกลับมา (return) ให้เขียนในรูปแบบ
@return tag (ถ้ามี returned)
- รายการของค่าผิดพลาดไม่ยอมรับ (exception)
ให้เขียนในรูปแบบ @exception tag (ถ้ามี exceptions ออกมา)
Example:
/** Get a copy of one int. <p>
Retrieve an int relative to the index provided.<p>
@param Index Which int (0 is the first int).<p>
@return The retrieved int or zero if Index is outside of 0..length.<p>
*/
public int get( int Index )
{
แนวทางการที่ดีของ document code
"ไม่ว่าจะโง่แค่ไหนก็สามารถเขียนโคดให้คอมพิวเตอร์เข้าใจได้.
แต่ programmer ที่ดีจะต้องเขียนโคดให้คนเข้าใจ"
ถ้าคุณพยายามเขียนเอกสารเพื่ออธิบาย algorithm
ที่ซับซ้อนของคุณ ให้เปลี่ยนเป็นพยายามเขียน algorithm ของคุณให้ง่าย โดยการดึงคำสั่งที่ซับซ้อนออกมาประกาศก่อนซะก่อน
สิ่งนี้จะช่วยลดความซับซ้อนของ algorithm เพื่อให้ง่ายแก่การปรับแต่ง และการอ่านโดย
ไม่จำเป็นต้องเขียนเอกสารอธิบายในส่วนนี้
ตัวอย่าง:
/** determine if the given year is a leap year. <p>
The Gregorian calendar principal states that a leap year occurs
every fourth year, except every 100 years, except every 400
years. <p>
If the year is evenly divisible by 400 or is evenly divisible by
4 and not by 100, then it is a leap year. <p>
@param year The year to be tested. Make sure this is a
four digit year!<p>
@return true if "year" is a leap year. <p>
*/
boolean isLeapYear( int year )
{
return ( ( ( y % 400 ) == 0 ) || ( ( ( y % 4 ) == 0 ) &&
( ( y % 100 ) != 0 ) ) );
}
แก้ไขเป็น:
/** determine if the given year is a leap year. <p>
The Gregorian calendar principal states that a leap year occurs
every fourth year, except every 100 years, except every 400
years. <p>
@param year The year to be tested. Make sure this is a
four digit year!<p>
@return true if "year" is a leap year. <p>
*/
boolean isLeapYear( int year )
{
boolean y4 = ( ( year % 4 ) == 0 ) ;
boolean y100 = ( ( year % 100 ) == 0 ) ;
boolean y400 = ( ( year % 400 ) == 0 ) ;
return ( y400 || ( y4 && ! y100 ) );
}
หรือ:
/** determine if the given year is a leap year. <p>
The Gregorian calendar principal states that a leap year occurs
every fourth year, except every 100 years, except every 400
years. <p>
@param year The year to be tested. Make sure this is a
four digit year! <p>
@return true if "year" is a leap year. <p>
*/
boolean isLeapYear( int year )
{
boolean returnVal = false ;
if ( ( year % 400 ) == 0 )
{
// this is definitely a leap year
returnVal = true ;
}
else if ( ( year % 4 ) == 0 )
{
// this is probably a leap year
if ( ( year % 100 ) == 0 )
{
// this is definitely not a leap year
// do nothing
}
else
{
// this is definitely a leap year
returnVal = true ;
}
}
return returnVal ;
}
การเขียนโคด
สิ่งที่ไม่ควรใช้อีกต่อไป
ไม่ควรใช้ do..while
ไม่ควรใช้ลูป do..while
เหตุผล: ลำรึกไว้ว่าเวลาที่โปรแกรมเมอร์อ่านโปรแกรมเค้าจะเริ่มอ่านตามลำดับการทำงานซึ่งไล่จากหัวลงมาท้าย
ตอนที่ programmer พยายามจะทำความเข้าใจกับ loop เค้าจะเริ่มจากเงื่อนไขของมันก่อน
ถ้าเราเอาเงื่อนไขไปไว้ที่ส่วนท้ายจะทำอ่านได้ลำบากมาก อีกทั้งจากประสบการณ์แล้วโปรแกรมส่วนใหญ่ไม่จำเป็นต้องใช้
do..while เราสามารถแก้ไขโคดไปในทางอื่นได้
ถ้าต้องการให้ดีกว่า:
boolean done = false ;
do
{
...
} while( ! done )
ก็ให้แก้เป็น:
boolean done = false ;
while ( ! done )
{
...
}
อย่าใช้ "return" ในช่องกลางของ method
"return" ถูกสร้างมาเพื่อใช้ในส่วนท้ายของ
method เท่านั้น
เหตุผล: การใช้ "return" ในช่วงกลางของ
method ทำให้ยากในการแยก method เป็นส่วนเล็กๆหรือเป็น method เล็กๆ และมันยังเป็นการบังคับให้
programmer ต้องกังวลกับทางออกของ method ที่มีมากกว่าหนึ่งที่อีกด้วย
อย่าใช้ "continue"
อย่าใช้ "continue" อีกต่อไป
เหตุผล: การใช้งาน "continue" ทำให้ยากในการแยก
method เป็นส่วนเล็กๆหรือเป็น method เล็กๆ และมันยังเป็นการบังคับให้ programmer
ต้องกังวลกับทางออกของ method ที่มีมากกว่าหนึ่งที่อีกด้วย
อย่าใช้ "break" นอกจากใน Switch Statement
"break" ควรถูกใช้สำหรับควบคุม switch
statement เท่านั้น
เหตุผล: การใช้ "break" ยกเว้นในกรณีของ
switch statement จะทำให้ยากในการแยก method เป็นส่วนเล็กๆหรือเป็น method เล็กๆ
และมันยังเป็นการบังคับให้ programmer ต้องกังวลกับทางออกของ method ที่มีมากกว่าหนึ่งที่อีกด้วย
พยายามอย่าใช้ Compound Increment หรือ
Decrement
ให้ใช้คำสั่งหลายบรรทัดแทน increment หรือ
decrement.
ตัวอย่าง:
foo( x++ ); // no!
foo( x ) ; // yes!
x++ ;
y += 100 * x++ ; // no!
y += 100 * x ; // yes!
x++ ;
การกำหนดค่าเริ่มต้น
พยายามกำหนดค่าเริ่มต้นให้กับตัวแปรตั้งแต่ตอนที่สร้างมันขึ้นมา
พยายามอย่าประกาศตัวแปรจนกว่าจะได้ใช้มัน
เพราะมันจะมีผลกระทบต่อ ความสามารถของโคด
ตัวอย่าง:
int totalWide ;
int firstWide = 20 ;
int secondWide = 12 ;
firstWide = doFoo( firstWide , secondWide );
doBar( firstWide , secondWide );
totalWide = firstWide + secondWide ; // wrong!
int firstWide = 20 ;
int secondWide = 12 ;
firstWide = doFoo( firstWide , secondWide );
doBar( firstWide , secondWide );
int totalWide = firstWide + secondWide ; // right!
int secondWide = 12 ;
int firstWide = doFoo( 20 , secondWide );
doBar( firstWide , secondWide );
int totalWide = firstWide + secondWide ; // even better!
เงือนไขการใช้
class หรือ attributes ทั้งหมดควรเป็น private เสมอ
ยกเว้น inner classes