35
SEMINAR: CLEAN CODE PRESENTERS: NGUYEN VAN THIEU TRAN THE ANH

Seminar clean code

Embed Size (px)

Citation preview

Page 1: Seminar clean code

SEMINAR: CLEAN CODE

PRESENTERS:

NGUYEN VAN THIEU

TRAN THE ANH

Page 2: Seminar clean code

1. THẾ NÀO LÀ CLEAN CODE

• Là làm tốt 1 việc

• Là đơn giản và trực tiếp, giống như đọc văn xuôi được viết tốt, không làm lu mờ ý định của thiết kế nhưng

vẫn đầy đủ các khái niệm trừu tượng sắc nét và đường kiểm soát đơn giản.

• Là mã sạch có thể đọc, nhận biết và có ý nghĩa.

• Là code sẽ có thể được đọc, và được cài thiện hoặc viết tiếp được bởi developer khác. Nó có đơn vị chấp

nhận và kiểm tra. Nó có tên đầy ý nghĩa. Nó cung cấp một cách khá hơn nhiều cách để làm một điều. Nó có

phụ thuộc tối thiểu, được định nghĩa một cách rõ ràng, và cung cấp một API rõ ràng và tối thiểu.

• Luôn luôn giống những gì mà được viết bởi 1 người quan tâm nó thật sự

• Giảm sự lặp lại, biểu cảm cao, và xây dựng ban đầu của sự trừu tượng đơn giản.

• Là mã chạy tất cả các bài test để kiểm tra, mã không chứa trùng lặp mà vẫn bày tỏ đầy đủ những ý tưởng

thiết kế trong hệ thống.

• Là mã giảm thiếu số lượng các classes, functions, methods.

Page 3: Seminar clean code

2. LÀM THẾ NÀO ĐỂ CODE "TRONG SÁNG"

• Khi làm dự án hay lập trình bất kỳ thứ gì ta phải có các quy tắc

code (code convention)

• Để code trong sáng thì ta phải có quy tắc code chuẩn, rõ ràng,

và làm theo được các chuẩn đó đó.

Page 4: Seminar clean code

3. NHỮNG NGUYÊN TẮC CƠ BẢN (CODE CONVERSION)

• Quy tắc đặt tên

• Quy tắc với Hàm (Functions)

• Quy tắc với Comments

• Định dạng code (Formatting)

• Quy tắc với Objects và Data Structures

• Quy tắc xử lý lỗi

Page 5: Seminar clean code

3.1. Quy tắc đặt tên

1. Sử dụng tên có ý nghĩa

2. Tránh dùng các chữ cái gây hiểu lầm, hoặc đặt tên quá ngắn gây hiểu lầm

3. Làm cho sự phân biệt có ý nghĩa.

4. Sử dụng tên phát âm được để có thể dễ nhớ, dễ hình dung.

5. Đặt tên dễ tìm kiếm trong phần mềm.

6. Tên classes và object thì nên để là danh từ và phải rõ nghĩa, không nên là động từ.

7. Tên hàm dùng prefixed để rõ nghĩa với set, get, is..

Page 6: Seminar clean code

3.1. Quy tắc đặt tên

1. Sử dụng tên có ý nghĩa (Tên thể hiện rõ được mục đích của biến, hàm...)

Vd:

int d // Không có ý nghĩa gì

int dayOfThisMonth // Hiểu được là số ngày trong tháng

2. Tránh dùng các chữ cái gây hiểu lầm, hoặc đặt tên quá ngắn gây hiểu lầm

Vd:

int o // Đây là biến o

if (o == 1)

a = o

else

b = o // Nhìn nó giống số 0 nên dễ gây hiểu lầm

Page 7: Seminar clean code

3.1. Quy tắc đặt tên

3. Làm cho sự phân biệt có ý nghĩa.

Vd:

public static void copyChars(char a1[], char a2[]) {

for (int i = 0; i < a1.length; i++) {

a2[i] = a1[i];

}

}

public static void copyChars(char source[], char destination[]) {

for (int i = 0; i < source.length; i++) {

destination[i] = source[i];

}

}

Page 8: Seminar clean code

3.1. Quy tắc đặt tên

4. Sử dụng tên phát âm được để có thể dễ nhớ, dễ hình dung.

Vd: class DtaRcrd102 {

private Date genymdhms;

private Date modymdhms;

private final String pszqint = "102";

};

class Customer {

private Date generationTimestamp;

private Date modificationTimestamp;;

private final String recordId = "102";

};

Page 9: Seminar clean code

3.1. Quy tắc đặt tên

5. Đặt tên dễ tìm kiếm trong phần mềm.

Vd:

Page 10: Seminar clean code

3.1. Quy tắc đặt tên

6. Tên classes và object thì nên để là danh từ và phải rõ nghĩa, không nên là động từ.

Vd:

Manager, Processor, Data. (Không nên dùng)

Customer, WikiPage,Account, and AddressParser. (Nên dùng)

8. Tên hàm

Vd:

postPayment, deletePage, save. Tên hàm thường viết dạng cammelCase hoăc cammel_case

- Dùng prefixed để rõ nghĩa với set, get, is..

Vd:

string name = employee.getName();

customer.setName("thieunv");

if(paycheck.isPosted()) {

...

}

Page 11: Seminar clean code

3.2. QUY TẮC VỚI HÀM

1. Nhỏ gọn

2. Blocks và Indenting

3. Làm 1 việc .

4. Một cấp độ trừu tượng trên 1 hàm.

5. Reading code from Top to Bottom : The Stepdown Rule

6. Switch Statements

7. Sử dụng tham số của hàm

8. Command Query Separation

9. Prefer Exceptions to Returning Error Codes

10. Trích xuất try/catch block.

11. Error Handling Is One Thing

12. How Do You Write Functions Like This?

Page 12: Seminar clean code

3.2. QUY TẮC VỚI HÀM

1. Nhỏ gọn

• 1 dòng không nên quá 150 ký tự

• 1 hàm không nên quá 30 dòng (1 trang giấy)

2. Blocks và Indenting

• Với các block if,else không nên nối tiếp lặp quá sâu (quá 3 mức)

• Lùi đầu dòng chuẩn, nên dùng tab.

3. Làm 1 việc

• FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL. THEY SHOULD DO

IT ONLY.

4. Một cấp độ trừu tượng trên 1 hàm.

5. Reading code from Top to Bottom : The Stepdown Rule

Page 13: Seminar clean code

3.2. QUY TẮC VỚI HÀM

6. Switch Statements

==> 1. Quá lớn, khi thêm loại của employee nó sẽ lớn hơn nữa.

2. Nó làm nhiều hơn 1 việc.

3. Xâm phạm nguyên tắc Single Responsibility Principle (SRP)

4. Xâm phạm nguyên tắc Open Closed Principle (OCP)

Page 14: Seminar clean code

3.2. QUY TẮC VỚI HÀM

Page 15: Seminar clean code

3.2. QUY TẮC VỚI HÀM

7. Sử dụng tham số của hàm

- Nhiều nhất nên là 2 tham số đầu vào

- Nếu có nhiều tham số hơn 2 thì nên bao chúng lại trong 1 class

Vd:

Circle makeCircle(double x, double y, double radius);

Circle makeCircle(Point center, double radius);

- Đối với tham số đầu ra cần rõ ràng, giải thích như tham số đầu vào.

Page 16: Seminar clean code

3.2. QUY TẮC VỚI HÀM

8. Command Query Separation

- Hàm nên làm việc gì đó hoặc trả lời gi đó nhưng không nên làm cả 2.

Vd phổ biến:

public boolean set(String attribute, String value);

==> Hàm này set giá trị của attribute là value. Nếu thành công thì trả về true.

==> Nó sẽ dẫn đến câu lệnh sau:

if (set("username", "unclebob"))...

==> Nếu ta là reader. Ta sẽ tự hỏi. cái hàm set này nó làm nhiệm vụ gì? Đã là set tại sao lại cho được trong if.

==> Để fix được ta có thể đổi tên là: setAndCheckIfExists ==> Cũng không mấy khả quan.

==> Để thật sự fix được ta nên chia rẽ nhiệm vụ của chúng ra như sau:

if (attributeExists("username")) {

setAttribute("username", "unclebob");

...

}

Page 17: Seminar clean code

3.2. QUY TẮC VỚI HÀM

9. Prefer Exceptions to Returning Error Codes

- Trả về lỗi code từ hàm là vi phạm sự tinh tế của gọi lệnh tách biệt.

if (deletePage(page) == E_OK)

- Điều này không gây nhầm lẫn hay dẫn đến xử lý cấu trúc lặp. Nhưng khi trả về lỗi code, ta phải giải quyết

ngay nó.

Page 18: Seminar clean code

3.2. QUY TẮC VỚI HÀM

- Thay vì phải dùng nhiều if như trên ta có thể dùng Exceptions để xử lý.

Page 19: Seminar clean code

3.2. QUY TẮC VỚI HÀM

- Một lợi thế khác của Exceptions nữa là:

public enum Error {

OK,

INVALID,

NO_SUCH,

LOCKED,

OUT_OF_RESOURCES,

WAITING_FOR_EVENT;

}

==> Khi ta có các lỗi code như trên. Sẽ rất nhiều nơi phải import enum vào. Nếu giờ Error có thêm lỗi. Ta

phải thay đổi enum.

==> Sẽ dẫn đến việc các nơi khác dùng Error sẽ phải thay đổi ==> Ta phải recompile and rebuild lại.

==> Giờ nếu ta dùng Exceptions

Page 20: Seminar clean code

3.2. QUY TẮC VỚI HÀM10. Trích xuất try/catch block.

- Bản thân try/catch đã là rất tồi. Nó bị trộn lẫn giữa lỗi và xử lý tự nhiên.

- Để giúp dễ đọc, dễ hiểu và khiến code trong sáng hơn thì ta nên tách biệt thân ra hàm.

Vd:

- Hàm delete bên trên chỉ về xử lý lỗi. Hàm deletePageAndAllReferences chỉ về xử lý việc xóa page. xử lý lỗi không trộn lẫn.

public void delete(Page page) {

try {

deletePageAndAllReferences(page);

}

catch (Exception e) {

logError(e);

}

}

private void deletePageAndAllReferences(Page page) throws

Exception {

deletePage(page);

registry.deleteReference(page.name);

configKeys.deleteKey(page.name.makeKey());

}

private void logError(Exception e) {

logger.log(e.getMessage());

}

Page 21: Seminar clean code

3.2. QUY TẮC VỚI HÀM

11. Error Handling Is One Thing

- Hàm làm 1 việc. Xử lý lỗi làm 1 việc. Vậy hàm xử lý lỗi không nên làm việc gì khác.

- Giống vd bên trên. Trong hàm delete chỉ có duy nhất khối try/catch.

Page 22: Seminar clean code

3.2. QUY TẮC VỚI HÀM

12. How Do You Write Functions Like This?

- Viết hàm giống như viết paper, article hay bất cứ thứ gì về viết.

- Đầu tiên ta nên có bản nháp, sau đó tổ chức lại, đặt tên lại, chia nhỏ nó ra, giảm sự trùng

lăp...

- Có thể lúc đầu ta cảm thấy làm vậy mất thời gian, nhưng khi về sau phải debug hoặc

maintain thì ta mới thấy được sự

lợi hại thật sự của việc viết nó clean.

- Không những vậy nó còn làm ta trở thành better programmer.

Page 23: Seminar clean code

3.3. QUY TẮC VỚI COMMENTS

1. Comment giải thích đúng rõ mục đích của nó.

2. Comment tốt và hợp lý

3. Bad Comments

4. Redundant Comments

5. Noise Comments, Comments sai lêch

6. Commented-Out Code

Page 24: Seminar clean code

3.3. QUY TẮC VỚI COMMENTS

1. Comment giải thích đúng rõ mục đích của nó.

- Comment không trang điểm cho bad code nhưng nó nói lên rằng code của bạn không

clean.

- Trước khi comment, ta hãy nghĩ tại sao ta lại phải cần comment.

- Nếu ta thấy đoạn code lằng nhằng, khó hiểu phải cần comment. Thì ta nên giành thời

gian để clean đoạn code đó thay vì ngồi comment nó.

- Vd:

// Check to see if the employee is eligible for full benefits

if ((employee.flags & HOURLY_FLAG) && (employee.age > 65))

if (employee.isEligibleForFullBenefits())

- Thay vì phải viết comment và 1 đống logic như trên. Ta chỉ cần tống chúng vào hàm và

đặt tên dễ hiểu thì code clean hơn.

Page 25: Seminar clean code

3.3. QUY TẮC VỚI COMMENTS

2. Comment tốt và hợp lý

Vd:

// Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.

// Released under the terms of the GNU General Public License version 2 or later.

- Khi publish dự án thì ta nên viết comment thế nào vào source để nói quyền sở hữu,

version...

Page 26: Seminar clean code

3.3. QUY TẮC VỚI COMMENTS

3. Bad Comments

- Đa phần chúng ta rơi vào đây.

- Có nhiều lúc ta không cần comment, nhưng ta lại cảm thấy cần comment. vậy là ta giành thời gian để viết comment.

Vd:

==> Ta có thể thấy đoạn comment trên có thể có ý nghĩa nào đó với người viết, nhưng chắc chắn sẽ vô nghĩa với reader.

- Ta có thể hiểu nếu rơi vào catch thì sẽ không có file nào được load.

- Nhưng nếu file được load thì sẽ load ở đâu, load lúc nào (tác giả chưa nói bên trên)

Page 27: Seminar clean code

3.3. QUY TẮC VỚI COMMENTS

4. Redundant Comments

Vd:

- Ta thấy comment trên kia là sự lặp lại thông tin của hàm, không những thế nó còn cho ta

biết

it thông tin hơn của hàm. Nếu đọc lần đầu vào comment bạn sẽ không hiểu gì.

Page 28: Seminar clean code

3.3. QUY TẮC VỚI COMMENTS

5. Noise Comments, Comments sai lêch

- Nhiều khi comments thật sự là noise. Nó không thật sự cung cấp cho ta thông tin mới gì cả.

Vd:

/*** @param title The title of the CD* @param author The author of the CD* @param tracks The number of tracks on the CD* @param durationInMinutes The duration of the CD in minutes*/ public void addCD(String title, String author, int tracks, int durationInMinutes) {

CD cd = new CD();cd.title = title;cd.author = author;cd.tracks = tracks;cd.duration = duration;cdList.add(cd);

}

/*** Default constructor.*/

protected AnnualDateRule() {}

/** The day of the month. */private int dayOfMonth;

/*** Returns the day of the month.** @return the day of the month.*/

public int getDayOfMonth() {return dayOfMonth;

}

Page 29: Seminar clean code

3.3. QUY TẮC VỚI COMMENTS

6. Commented-Out Code

- Không bao giờ nên làm điều này.

- Người sau đọc sẽ thấy khó hiểu, và không dám xóa vì ngỡ nó quan trọng.

- Nó còn gây ra hiểu lầm. Do đó tốt nhất nên xóa đi luôn.

InputStreamResponse response = new InputStreamResponse();

response.setBody(formatter.getResultStream(), formatter.getByteCount());

// InputStream resultsStream = formatter.getResultStream();

// StreamReader reader = new StreamReader(resultsStream);

// response.setContent(reader.read(formatter.getByteCount()));

Page 30: Seminar clean code

3.4. ĐỊNH DẠNG CODE (FORMATTING)

1. Vertical Formatting

2. Variable Declarations

• Instance variables

• Dependent Functions.

• Horizontal Formatting

• Indentation

• Breaking Indentation

• Team Rules

Page 31: Seminar clean code

3.4. ĐỊNH DẠNG CODE (FORMATTING)

1. Vertical Formatting

- Số dòng trong 1 file tùy theo các lập trình viên viết code của họ thế nào.

- Nhưng một file nên có ít nhất 10 dòng và tối đa là 500 dòng, thường trung bình là 150-300.

- Như vậy code sẽ không quá lớn để đọc hiểu 1 file.

2. Variable Declarations

- Ta nên khai báo biến gần nơi mà nó sử dụng nhất có thể. Bởi vì hàm rất ngắn, biến local nên xuất hiện ở đầu

của hàm.

- Biến điều khiển thì nên khai báo luôn trong vòng lặp.

Vd:

Page 32: Seminar clean code

3.4. ĐỊNH DẠNG CODE (FORMATTING)3. Instance variables

- Biến thể hiện thì nên khai báo ở ngay đầu của class. Điều quan trọng ở đây là các biến

instance thì nên khai báo cùng 1 nơi, để reader có thể thể biết mà đọc.

Page 33: Seminar clean code

3.4. ĐỊNH DẠNG CODE (FORMATTING)

4. Dependent Functions.

- Nếu có 1 hàm gọi hàm khác. Thì nên đặt hàm gọi trên đầu.

- Như vậy reader có thể đọc hiểu theo 1 cách tự nhiên theo top-down.

5. Horizontal Formatting

- Lời khuyên là nên để 120 ký tự là max trên 1 dòng.

- Nên để ý đến khoảng trắng giữa các ký tự.

Page 34: Seminar clean code

3.4. ĐỊNH DẠNG CODE (FORMATTING)

6. Breaking Indentation

- Đôi lúc ta gặp vài trường hợp mà ta có thể phá vỡ được việc lùi đầu dòng.

Vd:

--> Mặc dù việc làm này rút gọn được số dòng code, nhưng nó lại làm cho ta khó nhìn hơn, tốt

nhất nên để dạng chuẩn như bên dưới.

Page 35: Seminar clean code

3.4. ĐỊNH DẠNG CODE (FORMATTING)

7. Team Rules

- Mỗi programmer đều có formatting rule riêng. Nhưng nếu anh ta tham gia vào 1 team thì

team đó phải có rule rõ ràng và chi tiết.

- Cả nhóm cần thống nhất 1 rule. Không nên tồn tại ý kiến cá nhân rằng có người không

thích theo rule này.

- Hãy nhớ, hệ thống phần mềm tốt là tập hợp các tài liệu đọc tốt. Người đọc chấp được

style của team đó.