Clean code第一章

clean code

程式品質:每分鐘罵髒話的次數

劣質的程式碼

有時候常常想快點、很趕的狀況下完成工作項目,而我們盯著我們自行造成的 雜亂程式碼,若看到可以執行,就會留著他,待會有空再來整理程式。待會等於永不。

雜亂程式的代價

如果你是一位2~3年工程師,也許有被別人設計拖累牽絆的經驗, 程式品質好壞拖累的非常顯著。該團隊可能於初期開發迅速,但後期開發速度如蝸牛一般的速度前進,每次修改都非常困難、都需花費大量時間去了解混亂、曲折與打結的程式碼,時間越來越長,該專案已無法整理簡化。

最根本的難題

程式開發師面臨一個基本價值的難題,有著數年以上經驗開發者,都知道爛程式會降低他們效率,然而,開發者都感受到截止期限的壓力,所以只好產生爛程式以達到目標,但他們並沒有花費時間讓開發速度變更快。

真正的專家知道撰寫爛程式並不會趕上截止,事實上爛程式只能馬上讓開發速度變得更慢,讓你錯誤截止時間,唯一讓開發速度變快的方法,就是隨時隨地,讓程式碼盡可能保持整齊潔淨。

甚麼事clean code

  • 減少重複

  • 具有高度表達力

  • 及早建立簡單抽象改念

有意義的命名

命名無所不在,我們替變數、函數、參數、類別與套件命名以下介紹簡單規則

讓名稱代表意圖--名符其實

名稱d沒有傳達任何意義,無法關聯跟消逝天數或天數有任何聯想

// bad
int d;//消逝的天數

選擇有意圖的名稱

int elapsedTimeInDays;
public List<int[]>getThem(){
    List<int[]>list1=new ArrayList<>();
    for(int[]x:theList){
        if(x[0]==4){
            list1.add(x);
        }
    }
    return list1;
}

以上程式目的為何?

public List<int[]>getFlaggedCells(){
    List<int[]>flaggedCells=new ArrayList<>();
    for(int[]cell:gameBoard){
        if(cell[STATUS_VALUE]==FLAGGED){
            flaggedCells.add(cell);
        }
        
    }
    return flaggedCells;
}

進一步

public List<Cell>getFlaggedCells(){
    List<Cell>flaggedCells=new ArrayList<>();
    for(cell cell:gameBoard){
        if(cell.isFlagged()){
            flaggedCells.add(cell);
        }
        
    }
    return flaggedCells;
}

避免誤導

不要使用accountList,若型態非List,會有認知錯誤,否則改用 accountGroup、bunchOfAcounts。

拼字太過接近,容易無法辨識。

產生有意義的區別

public static void copyChar(char a1[],char[]a2){
 //略
}


public static void copyChar(char source[],char[]destinaction){
 //略
}

能夠唸出來的名稱

建立能溝通之語言,方便於專案內討論

使用可搜尋的名字

  • 定義可以容易找到文字 MAX_CLASSES_PER_STUDENT (每學生最大修課次數) VS 7

  • 若要定義短名稱如 i、j僅能出現於區域變數內

  • 若常數與變數不少地方使用到,最好取容易搜尋名稱

成員的字首

不用對於成員變數,名稱增加m_xxxx

class Student{
    private String id;
    public Student(String id){
        this.id=id;
    }
}

介面和實作

介面與實作,常常根據專案架構而規定

MVC:介面 BillService、實作:BillServiceImpl clean architecture :介面 IBillService、實作:BillServiceByDB

類別的命名

應該使用名詞或名詞片語來命名

Customer顧客、Account(帳號)

方法的命名

應該使用動詞或動詞片語來命名

save、delete..等

Acccount.save(..);

每一種概念使用一種詞句

需統一專案概念名稱,常見元件結尾文字

MVC:Controller、Service、DAO、DTO、VO MVC:Controller、UseCase、Service、Repository、DTO、Command、Event

統一行為用詞:fetch、retrieve、get,需統一專案名詞

使用解決方案領域的命名

類似JobQueue,Factory

別說雙關語

add、insert、append差異要區別。

 AcoountGroup acccounts=new AcoountGroup();
 acccounts=acccounts.add(acccount);//? 加入原本帳號、產生新的帳號

使用問題領域命名

使用專案內定義之英文名稱,方便溝通

添加有意義的上下文

一般若看到id變數名稱,可能有無限猜測,可透過增加上下文提升可讀性 或是建立新該類別,將提供更帶概念SkillMessage。 ex:id > skillId

//含糊不清變數名稱
public void printName(String id) {
	String name = "";
	if (StringUtils.equals(id, "A")) {
		name = "baseball";
	} else if (StringUtils.equals(id, "B")) {
		name = "badminton";
	} else {
		name = "unKnow";
	}
	System.out.print(MessageFormat.format("{0}:{1}", id, name));
}

public void printName(String skillId) {
	String name = "";
	if (StringUtils.equals(skillId, "A")) {
		name = "baseball";
	} else if (StringUtils.equals(skillId, "B")) {
		name = "badminton";
	} else {
		name = "unKnow";
	}
	System.out.print(MessageFormat.format("{0}:{1}", skillId, name));
}



class SkillMessage {

	String getName(String id) {
		String name;
		if (StringUtils.equals(id, "A")) {
			name = "baseball";
		} else if (StringUtils.equals(id, "B")) {
			name = "badminton";
		} else {
			name = "unKnow";
		}
		return name;
	}
}
public void printNameWithContext(String id) {
	String skillName = new SkillMessage().getName(id);
	System.out.print(MessageFormat.format("{0}:{1}", id, skillName));
}

Last updated

Was this helpful?