บทความนี้เป็นการสรุปเนื้อหาเท่าที่ผู้อ่านเข้าใจจากหนังสือ
CleanCode ของ Robert C martin หรือลุง Bob
Table Of Contents
Introduction
บทความนี้เป็นการสรุปหนังสือ Clean Code Robert C. Martin
ตามความเข้าใจหากผิดพลาดช่วย Comment กัได้นะเออ
Clean code คืออะไร
Clean code คือ code สะอาดครับ คำว่าสะสาดอาจจะหมายถึง อ่านง่าย แก้ไขง่าย ต่อยอดง่าย แต่เราจะทำยังไงให้มันได้อย่างที่เราบอกกันละ ก่อนอื่นเราต้องรู้จัก Bad code กันก่อน
Bad code
เราอาจจะเคยต้องอ่านโค๊ทต่อจากคนอื่น หรือ เราไม่ได้ทำ Project นั้นนานๆ แล้วกลับมาอ่านสิ่งที่เราจะเจอ
- ตัวแปลตัวนี้คืออะไรวะ dowData อ่านชื่อแล้วงง
- function นี้มันทำอะไรวะ genAcTcUserSta
- อ่าน code แล้วต้องลงไปดูใน function เพราะชื่อไม่สื้อ
- เรา check if เพื่ออะไรวะ for ตรงนี้ไม่เห็นจำเป็นต้องมีนิ
- บางตัวแปลไม่ได้ใช้ประกาศทำไม
- ฯลฯ
สิ่งเหล่านี้ที่เราเจอมาล้วนเป็นหนี้สินทาง software ทั้งสิ้น
หนี้สินทาง software คืออะไร
มันคือสิ่งที่ทำให้เราช้าลง เพราะหนี้สินล้วนมีดอกเบี้ย สิ่งที่จะเกิดผลกระทบ
- เวลาในการศึกษา code นั้นๆ จะมากขึ้น เช่น มีคนใหม่เข้าทีมอ่านทีหัวแตก (learning curve สูง)
- การแก้ไขโปรแกรมทำได้ยาก ไม่ว่าจะเพิ่ม feature หรือ fix bug
- เขียน test ยาก (ถึงกับไม่รู้จะเขียนยังไง)
- อ่านยากมากๆ อ่าน code แล้วอยากลาออก
- ฯลฯ
วันหนึ่งจะมีคนพูดว่า "ถ้าอ่านยากขนาดนี้ เขียนใหม่ยังง่ายกว่า"
แนวคิดเรื่อง Clean code
ถ้าเราถามว่า code ทำงานได้ กับ code สวย อะไรสำคัญกว่ากัน
หลายคนคงตอบไม่ยากว่า งานเสร็จ code ทำงานได้สำคัญกว่าอยู่แล้ว
ความเร็วในการออกของสำคัญมากยิ่งเราอยู่ในโลกของ agile และ scrum
ผมก็จะบอกว่าถูกครับ
เรามองว่า Clean code เป็นสิ่งเล็กๆ แต่คุณลองคิดถึงเวลาคุณมีบ้าน ที่ประตูปิดไม่สนิท เวลาปิดมีเสียง เอี๊ยดดดๆ เหมือนในหนังผี กระเบื้องห้องน้ำเรียงมั่ว ก๊อกน้ำน้ำรั่ว
บางปลั๊กไม่มีไฟ ถามว่าเป็นบ้านไหม เป็น อยู่ได้ไหม ก็อยู่ได้ แต่ทุกสิ่งที่กล่าวมาล้วนปัดเป่าเสน่ของบ้านทั้งสิ้น
จงให้ความสำคัญกับสิ่งเล็กๆ ในสิ่งเล็กๆ ล้วนสำคัญ
คนธรรมดากับมืออาชีพ ต่างกันที่ความใส่ใจในรายระเอียด
แต่เรามักถูกบีบด้วยเวลา และคนเดินมาเร่งมากมาย เวลาเกิดปัญหาเราก็จะบอกว่า
- ผมมีเวลาแค่นี้ครับ
- ได้แค่นี้ก็หรูแล้ว
- มันทำงานได้ก็โอเคร
จริงๆ แล้วไม่ใช่แค่ Programmer ที่จะต้องเข้าใจในคำว่า หนี้สินทาง software ขอเรียก software debt คำนี้มันเกิดตอนที่ ลุง Robert C. Martin อธิบายให้หัวหน้าฟังเพราะบริษัทที่ทำงานนั้นเกี่ยวกับด้านการเงินเลยเกิดคำนี้มาเพื่อให้หัวหน้าเข้าใจ มันแปลว่าหัวหน้า , PM ใครก็แล้วแต่ที่สั่งเรา ต้องเข้าใจ
ในเรื่อง software debt ด้วยเพื่อใช้ในการประเมิณเวลาในการทำด้วย
หลักการในการ Clean Code
Meaningful Names
การตั้งชื่อ
Use Intention-Revealing Names
ชื่อทุกสิ่งที่เราตั้งล้วนต้องมีความหมาย บ่งบอกถึงเจตนาของสิ่งนั้นๆ อย่างชัดเจน เช่น class function val หากชื่อพวกนั้นต้องการ comment แสดงว่าชื่อนั้นยังไม่บอกเจตนาอย่างชัดเจน
// Day of week
var dow
or
var dayOfWeek
Use Pronounceable Names
ชื่อต้องอ่านออกเสียงได้ หลีกเลี่ยงการใช้
number series : a1 a2 a3
Noise words are another meaningless distinction
ลองนึกภาพว่าคุณมี product class. หากคุณมีชื่ออื่นที่เรียกว่า ProductInfo หรือ ProductData คุณได้สร้างชื่อให้แตกต่างกันโดยไม่ทำให้มีความหมายแตกต่างกัน ข้อมูลและข้อมูลเป็นสัญญาณรบกวนที่ไม่ชัดเจน
คำเช่น a, an และ this
อย่ากลัวที่จะตั้งชื่อยาวหากชื่อนั้นสร้างความแตกต่างอย่างมีความหมายได้
Noise words are redundant
ไม่ควรใส่ type ของตัวแปลไปหลังชื่อ เช่น nameString, dateLong เพื่อเลี่ยงการปิดเบือนข้อมูลเหมือน accountList ด้านบน และ
เพราะว่า IDE สมัยนี้หากเราเอาเมาส์ไปชี้ก็จะแสดง type ให้อยู่แล้วถ้าไม่ใช้ตัวแปร dynamic type
Avoid Disinformation
หลีกเลี่ยงการทำเกิดความเข้าใจผิด หรือทำให้ความหมายเปลี่ยนแปลง ต่างจากความหมายที่เราตั้งใจไว้ เช่น hp,aix, sco ทั้งหมดนี้ล้วนเป็นชื่อของ platfrom linux
การตั้งชื่อโดยใส่คำว่า list accountList การตั้งชื่อแบบนี้เสี่ยงต่อการเข้าใจผิดได้ง่ายว่ามันคือ รายการบัญชีหรือกลุ่มของบัญชีหรือเปล่า เราอาจจะใช้ accounts สำหรับ array account หรือ accountGroup สำหรับกลุ่มของ account
Make Meaningful Distinctions
ทำให้มีความหมายอย่างแตกต่างบางครั้งการตั้งชื่อให้แตกต่างกันมันก็ยาก ตัวแปรบางตัวที่ชื่อเหมือนกันจะโดนฟ้องโดยคอมไพเรอให้เปลี่ยนชื่อ
Use Searchable Names
ใช้ชื่อที่ search ได้ หลีกเลี่ยงการใช้ ตัวอักษรตัวเดียว และ ควรใช้ Constants แทน ตัวเลข มันไม่ง่ายเลยที่เราจะหาตัว i ที่เราตั้งการใน โปรเจค
หรือเราจะหาตัวเลข 1 ในโปรเจค ควรตั้ง constant แทน เช่น MAX_DRIVER_IN_CAR
Avoid Encodings
เลี่ยงการใช้ตัวย่อ เพราะว่ายากต่อการเข้าใจและออกเสียงไม่ได้ คิดถึงหนังสือพิมพ์ นย พตรอ นพ อะไรวะงงเยอะไปหมด
Member perfixes
เลี่ยงการใช้คำนำหน้าเช่น m_student ถ้า function เราเล็กพอสิ่งนี้จะไม่เกิดแน่นอน
Class Names
ควรเป็นคำนามเท่านั้น ห้ามใช้กริยา
Method Names
ควรเป็นกริยาเท่านั้น ห้ามเป็นคำนาม
Don't Be Cute
อย่าอวดฉลาดตั้งชื่อตัวแปลเท่ๆ เช่น Eureka ,phoenix, Aileen (แปลว่าแสงสว่าง)
Pick one word per concept
เป็นการนิยามชื่อ protocalManager และ ProtocolController ดูเหมือนกันเลยแต่จะเอาอันไหนละ
Use Solution Domain Name
ใช้การต่อชื่อไปอย่างสอดคล้องกัน createPluralDependentMessageParts
หากทำไม่ได้การเพิ่ม name space ไว้ข้างหน้าจะเป็นทางออกสุดท้าย
Function
Small ต้องเล็ก
1 บรรทัดไม่เกิน 150 อักษร
1 function ไม่ควรเกิน 100 บรรทัด
แต่จะให้ดี ไม่เกิน 20 บรรทัด
Blocks and Indenting
if else if else while statement ไม่ควรเกิน 1 บรรทัด หากเกินควรแยก function
Do One Thing
1 function ควรทำแยกสิ่งเดียว
Function Arguments
ควรน้อยที่สุดเท่าที่เปิดไปได้ และไม่ควรเกิน 3 ถ้าเกินเราอาจจะสร้าง class มารองรับ
Verbs and Keywords
เลือกชื่อที่ดีเป็นกริยาสำหรับ function
Have No Side Effects
function เราต้องไม่มี side effects เพราะหากมีเราจะรู้เลยว่า function เราไม่ได้ทำสิ่งเดียว Do One Thing
public class UserValidator {
private Cryptographer cryptographer;
public boolean checkPassword(String userName, String password) {
User user = UserGateway.findByName(userName);
if (user != User.NULL) {
String codedPhrase = user.getPhraseEncodedByPassword();
String phrase = cryptographer.decrypt(codedPhrase, password);
if ("Valid Password".equals(phrase)) {
Session.initialize();
return true;
}
}
return false;
}
code จาก clean code :Rovert C matin หน้าที่ 44
Extract Try/Catch Blocks
การ try catch ลงใน function เลยอาจจะทำให้ดูน่าเกลียด
หากเราไม่แยกการทำงานของ function ให้ทำงานเพียงอย่างเดียว
(ในการ try catch ควรมีแค่ function เดียวการทำงานเดียวที่เราดัก)
don't
ในตัวอย่างนี้เราจะเห็นได้ว่าเรา try catch ในหลาย function อาจจะทำให้เราสับสนได้ว่า error นี้มาจากกระบวนการไหนของ flow กันแน่
function delete(page){
try{
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}catch(error){
throw Exception("can't delete page "+page.id+" error :"+error)
}
}
do
function delete(page){
try{
deletePageAndAllReferences(page);
}catch(error){
throw Exception("can't delete page "+page.id+" error :"+error)
}
}
function deletePageAndAllReferences(){
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}
เราควร
Don’t Repeat Yourself
อย่าทำซ้ำ เช่นซ้ำซ้อนการทำงานต่างๆ duplication
Comments
code ที่ดีต้องไม่มี comment เราชอบคิดว่ามันซับซ้อนเลยต้องมี comment จริงๆ มันไม่ถูกซะทีเดียวเราควรทำให้ code ดีมากกว่าคิดว่ามันซับซ้อนอ่านยากเลยต้อง comment
comment ที่ควรเขียนมีแค่ Copyright กับ authorship statement
หรือข้อยกเว้นหากเราเขียน libary ที่ซับซ้อนมากๆ การ comment ก็ไม่แปลกอะไรแต่ทางที่ดีที่สุดคือ ทางที่เราไม่ใส่ comment
Formatting
The coding style and readability เราควรจะจัด code style ให้ตรงกัน ซึ่งสามารถกำหนดใน IDE ได้
เช่น 150 ตัวอักษรสำหรับ 1 บรรทัด ฯลฯ
ทั้งหมดทั้งมวลนี้อาจจะไม่สอดคล้องกับสิ่งที่คุณรู้เชื่อ หรือเข้าใจ คุณอาจจะไม่เห็นด้วยกับบทความนี้ทั้งหมดก็ได้เพราะหลายคนประสบห์การต่างกันอาจจะมี trick ที่เทคนิคพิเศษที่ต่างกันไป
Top comments (2)
1 function ควรทำแย่สิ่งเดียว
พิมพ์ผิด ไปตัวนึงครับผม
Thank ครับ