Clean code (TH.)
Tags: cleancode
Published: 2020-11-12 11:04:15

บทความนี้เป็นการสรุปเนื้อหาเท่าที่ผู้อ่านเข้าใจจากหนังสือ 
CleanCode ของ Robert C martin หรือลุง Bob

# Table Of Contents
 1. [Introduction] (#Introduction)
   1. [Clean code คืออะไร](#11WhatCleanCode)
   2. [Bad code] (#badcode)
   3. [หนี้สินทาง software คืออะไร] (#13SoftwareDebt)
   4. [แนวคิดเรื่อง Clean code (สำคัญ)](#14CleanCode)
 2. [หลักการการทำ Clean code ](#CleanCodeContent)
   1. [Meaningful Name ](#meaningFulName)
   2. [Function] (#function)
   3. [Comments] (#comments)
   4. [Formatting] (#formatting)

# Introduction <a name="Introduction"></a>
บทความนี้เป็นการสรุปหนังสือ **Clean Code** Robert C. Martin 
ตามความเข้าใจหากผิดพลาดช่วย Comment กัได้นะเออ

## Clean code คืออะไร <a name="11WhatCleanCode"></a>
Clean code คือ code สะอาดครับ คำว่าสะสาดอาจจะหมายถึง อ่านง่าย แก้ไขง่าย ต่อยอดง่าย แต่เราจะทำยังไงให้มันได้อย่างที่เราบอกกันละ ก่อนอื่นเราต้องรู้จัก Bad code กันก่อน

## Bad code <a name="badcode"></a>
เราอาจจะเคยต้องอ่านโค๊ทต่อจากคนอื่น หรือ เราไม่ได้ทำ Project นั้นนานๆ แล้วกลับมาอ่านสิ่งที่เราจะเจอ
 * ตัวแปลตัวนี้คืออะไรวะ dowData อ่านชื่อแล้วงง
 * function นี้มันทำอะไรวะ genAcTcUserSta
 * อ่าน code แล้วต้องลงไปดูใน function เพราะชื่อไม่สื้อ
 * เรา check if เพื่ออะไรวะ for ตรงนี้ไม่เห็นจำเป็นต้องมีนิ
 * บางตัวแปลไม่ได้ใช้ประกาศทำไม
 * ฯลฯ

*สิ่งเหล่านี้ที่เราเจอมาล้วนเป็นหนี้สินทาง software ทั้งสิ้น*

## หนี้สินทาง software คืออะไร <a name="13SoftwareDebt"></a>
มันคือสิ่งที่ทำให้เราช้าลง เพราะหนี้สินล้วนมีดอกเบี้ย สิ่งที่จะเกิดผลกระทบ
 * เวลาในการศึกษา code นั้นๆ จะมากขึ้น เช่น มีคนใหม่เข้าทีมอ่านทีหัวแตก (learning curve สูง)
 * การแก้ไขโปรแกรมทำได้ยาก ไม่ว่าจะเพิ่ม feature หรือ fix bug
 * เขียน test ยาก (ถึงกับไม่รู้จะเขียนยังไง)
 * อ่านยากมากๆ อ่าน code แล้วอยากลาออก
 * ฯลฯ

*วันหนึ่งจะมีคนพูดว่า "ถ้าอ่านยากขนาดนี้ เขียนใหม่ยังง่ายกว่า"*

### แนวคิดเรื่อง Clean code <a name="14CleanCode"></a>
ถ้าเราถามว่า code ทำงานได้ กับ code สวย อะไรสำคัญกว่ากัน
หลายคนคงตอบไม่ยากว่า งานเสร็จ code ทำงานได้สำคัญกว่าอยู่แล้ว
ความเร็วในการออกของสำคัญมากยิ่งเราอยู่ในโลกของ agile และ scrum

*ผมก็จะบอกว่าถูกครับ*

เรามองว่า Clean code เป็นสิ่งเล็กๆ แต่คุณลองคิดถึงเวลาคุณมีบ้าน ที่ประตูปิดไม่สนิท เวลาปิดมีเสียง เอี๊ยดดดๆ เหมือนในหนังผี กระเบื้องห้องน้ำเรียงมั่ว ก๊อกน้ำน้ำรั่ว
บางปลั๊กไม่มีไฟ ถามว่าเป็นบ้านไหม เป็น อยู่ได้ไหม ก็อยู่ได้ แต่ทุกสิ่งที่กล่าวมาล้วนปัดเป่าเสน่ของบ้านทั้งสิ้น

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

แต่เรามักถูกบีบด้วยเวลา และคนเดินมาเร่งมากมาย **เวลาเกิดปัญหาเราก็จะบอกว่า**
* ผมมีเวลาแค่นี้ครับ
* ได้แค่นี้ก็หรูแล้ว
* มันทำงานได้ก็โอเคร

จริงๆ แล้วไม่ใช่แค่ Programmer ที่จะต้องเข้าใจในคำว่า หนี้สินทาง software ขอเรียก software debt คำนี้มันเกิดตอนที่ ลุง Robert C. Martin อธิบายให้หัวหน้าฟังเพราะบริษัทที่ทำงานนั้นเกี่ยวกับด้านการเงินเลยเกิดคำนี้มาเพื่อให้หัวหน้าเข้าใจ มันแปลว่าหัวหน้า , PM ใครก็แล้วแต่ที่สั่งเรา ต้องเข้าใจ
ในเรื่อง software debt ด้วยเพื่อใช้ในการประเมิณเวลาในการทำด้วย



___



#หลักการในการ Clean Code <a name="CleanCodeContent"></a>

##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 <a name=“function”></a>
### 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 <a name=“comments”></a>
code ที่ดีต้องไม่มี comment เราชอบคิดว่ามันซับซ้อนเลยต้องมี comment จริงๆ มันไม่ถูกซะทีเดียวเราควรทำให้ code ดีมากกว่าคิดว่ามันซับซ้อนอ่านยากเลยต้อง comment 
comment ที่ควรเขียนมีแค่ Copyright กับ authorship statement

หรือข้อยกเว้นหากเราเขียน libary ที่ซับซ้อนมากๆ การ comment ก็ไม่แปลกอะไรแต่ทางที่ดีที่สุดคือ ทางที่เราไม่ใส่ comment

___

## Formatting <a name=“formatting“></a>
The coding style and readability เราควรจะจัด code style ให้ตรงกัน ซึ่งสามารถกำหนดใน IDE ได้
เช่น 150 ตัวอักษรสำหรับ 1 บรรทัด ฯลฯ

ทั้งหมดทั้งมวลนี้อาจจะไม่สอดคล้องกับสิ่งที่คุณรู้เชื่อ หรือเข้าใจ คุณอาจจะไม่เห็นด้วยกับบทความนี้ทั้งหมดก็ได้เพราะหลายคนประสบห์การต่างกันอาจจะมี trick ที่เทคนิคพิเศษที่ต่างกันไป

![Alt text of image](https://res.cloudinary.com/practicaldev/image/fetch/s--846b1Bv3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ko7x2fa9ztpp9m150vgb.jpg)