Trong thế giới phát triển phần mềm, việc viết code không chỉ là vấn đề chức năng, mà code viết ra còn phải đảm bảo việc dễ bảo trì và mở rộng sau này. Viết clean code là một kỹ năng quan trọng mà tất cả các lập trình viên nên có. Khi bạn viết clean code, bạn đang làm cho phần mềm của mình tốt hơn cho chính mình và cho những người khác sẽ bảo trì và phát triển nó trong tương lai.
1. Clean code là gì?
Hiện tại, chưa có định nghĩa chính thức nào về clean code được công nhận rộng rãi, với mỗi lập trình viên có thể có những định nghĩa khác nhau. Vì vậy, tôi sẽ đưa ra một định nghĩa về clean code của Grady Booch:
Clean code là code đơn giản và dễ hiểu. Đọc clean code giống như đọc bài văn được viết tốt. Clean code không bao giờ che đi ý định của người thiết kế, mà thay vào đó, nó chứa đầy sự trừu tượng rõ ràng và các dòng điều khiển dễ hiểu.
Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions and straightforward lines of control.
Grady Booch
Chúng ta còn có thể hiểu đơn giản clean code là code dễ đọc, dễ bảo trì, dễ hiểu và dễ thay đổi, mở rộng mã vẫn phải đáp ứng được các yêu cầu về tính năng, bảo mật, và hiệu năng.
2. Tìm hiểu về code smell
Trái ngược với clean code, chúng ta có code smell với những đặc điểm làm cho quá trình bảo trì và mở rộng về sau của phần mềm trở lên tốn kém và rủi ro hơn.
2.1. Code smell là gì?
Code smell được hiểu là những những dấu hiệu trong mã nguồn của một chương trình, những dấu hiệu này có khả năng tiết lộ những vấn đề phức tạp hơn nằm ẩn bên trong.
In computer programming, a code smell is any characteristic in the source code of a program that possibly indicates a deeper problem.
Wikipedia
Thuật ngữ code smell được giới thiệu bởi Kent Beck trên WardsWiki trong những năm cuối của thập niên 1990 và thuật ngữ này được sử dụng rộng rãu hơn sau khi nó xuất hiện trong cuốn sách Refactoring: Improving the Design of Existing Code của Martin Fowler. Code smell đối lập với clean code, tức là khi hạn chế được code smell thì cũng là đang tuân thủ clean code.
2.1. Các đặc điểm của code smell
Code smell không phải là lỗi của chương trình, và cũng không làm cho chương trình không chạy được, mà nó là chỉ báo cho sự hạn chế về thiết kế dẫn đến làm chậm quá trình phát triển trong tương lai hay làm tăng rủi ro gây ra lỗi cho phần mềm trong tương lai. Và ta có thể nhận biết code smell qua một số đặc điểm sau đây:
- Cứng nhắc: Các thành phần của phần mềm rất khó để thay đổi. Khi có một sự thay đổi nhỏ trong chương trình, rất có thể sẽ phải đi sửa ở rất nhiều chỗ khác có liên quan.
- Mong manh: Nhiều thành phần trong phần mềm có thể bị lỗi chỉ vì một sự thay đổi nhỏ trong chương trình.
- Bất động: Rất khó hoặc không thể tái sử dụng một thành phần nào đó trong chương trình do có thể có nguy cơ lỗi không kiểm soát được hoặc cần quá nhiều lỗ lực.
- Phức tạo hoá vấn đề: Sử dụng những thuật toán, cấu trúc dữ liệu hay những giải pháp quá phức tạp để giải quyết vấn đề khiến cho người đọc khó hiểu. Hiểu một cách dân gian là "Dùng giao mổ trâu giết gà".
- Lặp code không cần thiết: Các đoạn chương trình giống nhau bị lặp lại một cách không cần thiết dẫn đến khi bảo trì hoặc phát triển thêm thì những đoạn bị lặp lại ấy có thể không được sửa đổi cùng, dẫn đến lỗi trong tương lai.
- Khó hiểu: Người đọc code không hiểu được dụng ý của tác giả khi đọc tên biến hay cảm thấy bị dư thừa hoặc không nhất quán các bước thực thi trong hàm và tên của hàm.
Ngoài ra còn có một số đặc điểm cụ thể khác như: Nội dung hàm quá dài, class quá lớn, quá nhiều tham số đầu vào cho hàm, comment không giúp người đọc hiểu thêm về code, nhiều đoạn code không dùng đến nhưng không được loại bỏ ...
2.2. Vì sao lại có code smell?
Code smell có thể được tạo ra do một số nguyên nhân sau:
- Lập trình viên không biết hoặc hiểu không đúng về các nguyên tắc để viết clean code.
- Lập trình viên không biết được các dấu hiệu của code smell.
- Lập trình viên sử dụng code từ nơi khác và paste vào dự án của mình mà không kiểm tra kỹ càng.
- Lập trình viên nghĩ rằng giành thời gian để viết clean code là không cần thiết do đang phải làm gấp rút để kịp deadline. Và sau này có thể giành thời gian để quay lại refactor code, nhưng thường thì "sau này" có nghĩa là không bao giờ.
3. Tại sao phải viết clean code?
Với những lập trình viên có kinh nghiệm, chắc hẳn họ cũng đã từng tạo ra code smell hoặc phải đi dọn dẹp code smell của những người khác để lại. Cảm giác chung khi lập trình viên bảo trì những dòng code smell đó là khó chịu, và nhiều câu hỏi liên tiếp nảy ra trong đầu về sự xuất hiện của những dòng code đó.
Có lẽ điều khiến team không vui nhất khi làm việc với code smell là năng suất bị giảm đi và rất có thể lại tiếp tục tạo ra những đoạn code smell tiếp theo, và theo thời gian, vòng lặp lại tái diễn. Khi bắt đầu dự án, chúng ta có thể cảm thấy quá trình phát triển nhanh hơn khi không cần phải viết clean code, nhưng dần dần, những đoạn code ấy lại khiến cả team đi chậm lại do phải giành thêm thời gian để sửa lỗi của những phần khác đáng ra không liên quan hoặc phải refactor lại những đoạn code smell cũ.
Và sau đây là các lý do lập trình viên cần phải viết clean code:
- Dễ bảo trì: Bảo trì phần mềm bao gồm điều chỉnh các lỗi mà chưa được phát hiện trong các giai đoạn phát triển trước, nâng cấp tính năng sử dụng và đảm bảo an toàn vận hành cho phần mềm. Việc bảo trì có thể chiếm đến 65%-75% công sức trong vòng đời của một phần mềm. Khi viết clean code, những người bảo trì về sau sẽ dễ dàng và nhanh chóng trong việc sửa đổi phần mềm, từ đó làm tăng năng suất trong những giai đoạn về sau của dự án phần mềm.
- Dễ trao đổi: Thường trong một dự án sẽ có nhiều người tham gia, và rất dễ dẫn đến tình trạng mỗi người viết một kiểu, và những người còn lại rất khó để hiểu những đoạn code của người khác. Khi một người viết clean code, cũng là lúc họ quan tâm đến việc để cho những người khác dễ dàng tiếp cận và hiểu được các đoạn code của mình, thay vì chỉ có mỗi tác giả hiểu được.
- Thể hiện sự chuyên nghiệp của cá nhân: Trình độ một lập trình viên được thể hiện qua rất nhiều khía cạnh khác nhau, và những dòng code bạn viết ra cũng là một trong số đó. Khi đọc code của những lập trình viên khác, chúng ta có thể cảm nhận được trình độ, sự chuyên nghiệp của họ thông qua những chi tiết rất nhỏ như cách comment, cách đặt tên hàm, tên biến hay cách tổ chức cấu trúc của dự án ..
- Thể hiện sự chuyên nghiệp của team: Mã nguồn là thành quả của team sau quá trình làm việc, vì vậy khi đọc code của một phần mềm, chúng ta hoàn toàn có thể đánh giá được phần nào về sự chuyên nghiệp trong quá trình phát triển của phần mềm đó. Bên cạnh nhiều yếu tố khác để đánh giá như: trình độ quản lý, quy trình vận hành, chất lượng con người ... Nhưng có thể nói tất cả những yếu tố ấy đều phần nào phản ánh vào trong code mà các lập trình viên tạo ra.
4. Các nguyên tắc chung để viết clean code
Để có thể viết clean code không phải là điều dễ dàng, bởi nó đòi hỏi về thái độ, kiến thức, cảm nhận về code của từng người và cả kinh nghiệm làm việc thực tế. Tuy nhiên chúng ta vẫn có thể bắt đầu viết clean code với một số nguyên tắc chung:
- Tuân theo các quy ước chung: Thường trong các team sẽ có bộ quy ước về việc viết code để mọi người làm theo, và tốt nhất là chúng ta nên tuân theo các bộ quy ước đó để mọi người trong team có thể dễ dàng tiếp cận với code của bạn. Trong trường hợp bạn thấy một quy ước nào nào đó không hợp lý thì nên trao đổi lại với cả team thay vì một mình phá vỡ nó.
- KISS (Keep it simple, stupid!): Rất nhiều tình huống các lập trình viên sử các design pattern, hay các thuật toán phức tạp để giải quyết vấn đề mà chưa suy nghĩ xem là có thể dùng giải pháp đơn giản hơn hay không. Hãy cố gắng sử dụng các phương án đơn giản, dễ hiểu để giải quyết vấn đề thay vì áp dụng các kỹ thuật code một cách cứng nhắc.
- Quy tắc của hướng đạo sinh (Boy scout rule): Để lại bãi cắm trại sạch hơn so với lúc bạn tìm thấy nó. Khi bạn phát hiện các đoạn code smell trong quá trình làm việc, hãy thay vào đó clean code để những người làm việc về sau sẽ không còn thấy nó nữa. Đương nhiên quá trình này sẽ tốn thêm công sức của team, nhưng nếu xét trên toàn bộ vòng đời phát triển, nếu không sửa thì smell code vẫn còn đó và chi phí để sửa đổi trong giai đoạn về sau thường sẽ cao, vì vậy, sửa sớm vẫn hơn.
- Tìm nguyên nhân gốc rễ: Khi gặp một lỗi trong phần mềm, rất có thể do chịu áp lực về thời gian hoặc không kiểm tra kỹ mà lập trình viên chỉ sửa để chương trình không xuất hiện đúng lỗi đó nữa mà không chắc rằng đó có phải là nguyên nhân gốc rễ không. Dẫn đến có những đoạn code lạc lõng mà chỉ để xử lý đúng một vài trường hợp nào đó và phá vỡ tính logic chung của cả hàm hay class hay thậm chí là cả một package.
- DRY (Don't repeat your self): Ý tưởng chính của nguyên tắc này là chúng ta không nên lặp lại tri thức, logic nghiệp vụ trong chương trình. Code có thể vẫn bị lặp, miễn là tri thức, logic nghiệp vụ không bị lặp lại là được. Mục đích chính là khi chỉnh sửa thì chúng ta luôn biết có một nơi duy nhất để sửa, và chỉ cần sửa ở 1 chỗ là đủ. Nhưng nếu cố gắng áp dụng DRY một cách máy móc quá mức, rất có thể bạn sẽ vi phạm nguyên tắc KISS, vì vậy hãy sử dụng DRY một cách khôn ngoan.
5. Một số nguyên tắc clean code trong lập trình
5.1. Nguyên tắc đặt tên
Có một câu nói được lan truyền trong cộng đồng lập trình viên: Chỉ có hai việc khó trong khoa học máy tính là loại bỏ cache hết hạn và đặt tên cho một thứ gì đó.
There are only two hard things in Computer Science: cache invalidation and naming things.
Phil Karlton
Bạn có thể coi đây như là một câu nói đùa, hay một chân lý, hoặc cả hai. Lập trình viên ở bất kỳ trình độ nào thì chắc hẳn đôi lúc cũng sẽ gặp khó khăn trong việc đặt tên cho biến, hàm, class, file ... sao cho chúng có ý nghĩa nhất có thể. Và trong những phần tiếp theo của bài viết sẽ đưa ra một số nguyên tắc để chúng ta đặt tên giúp code "clean" hơn.
5.1.1. Sử dụng tên biến có chủ đích
Đôi khi, lập trình viên sử dụng các từ viết tắt hay những chữ cái nào đó để đặt tên cho biến. Việc này sẽ hữu ích khi phạm vi truy cập của biến đó là nhỏ và số lượng biến là ít (1 hoặc 2 biến) do người đọc sẽ không tốn công để ghi nhớ ý nghĩa của biến đó.
Tuy nhiên, nếu phạm vi sử dụng của biến đó rộng hơn thì nên đặt tên biến bằng những từ có nghĩa để người đọc dễ hiểu về ý nghĩa của biến đó.
5.1.2. Tạo sự phân biệt rõ ràng
Một thói quen xấu để đặt tên biến là sử dụng các số tịnh tiến để làm hậu tố cho các biến mà không đặt tên rõ ràng cho biến đó để thể hiện mục đích sử dụng. Trong trường hợp các biến có cùng kiểu dữ liệu thì người đọc sẽ khó để biết được ý nghĩa của các biến ấy nếu không đọc logic xử lý liên quan tới chúng là như thế nào.
5.1.3. Sử dụng tên theo nghiệp vụ
Tên biến nên được đặt theo ngữ cảnh của nghiệp vụ mà đoạn code đó đang giải quyết, không nên sử dụng các từ ngữ trong lập trình để đặt cho tên biến. Ví dụ, nên đặt tên biến là accounts
thay cho accountArray
hay accountCollection
.
5.1.4. Thống nhất cách dùng từ
Hãy sử dụng một từ nhất quán trên toàn bộ chương trình để diễn tả cho một hành động hay một khái niệm nào đó. Ví dụ: khi chúng ta muốn viết method lấy dữ liệu trong một class, có rất nhiều tên có thể sử dụng như getData
, retriveData
, fetchData
... Tuy nhiên, hãy sử dụng một từ duy nhất ở tất cả các class (fetchData
chẳng hạn) để người đọc không bị bối rối khi nhìn thấy nhiều cái tên với cùng một mục đích.
5.1.5. Tên method và tên class
Có hai quy tắc đơn giản giúp chúng ta đặt tên cho method và class:
- Tên class nên có danh từ hoặc cụm danh từ:
Student
,ClassRoom
,School
- Tên method nên có động từ hoặc cụm động từ:
countStudent
,showName
5.1.6. Sử dụng tên dễ phát âm và tìm kiếm được
Khi viết những tên biến hay tên hàm cần kết hợp nhiều từ với nhau, lập trình viên có xu hướng dùng từ viết tắt cho nối với nhau, và rồi tạo thành một từ mới rất khó hoặc không thể phát âm được như MsgCtrl
. Thay vào đó, hãy viết đầy đủ tên của class đó thành MessageController
.
Ngoài ra còn một số trường hợp khi không biết đặt tên biến là gì, một số lập trình viên còn dùng những chữ cái ngẫu nhiên như pszqint
hay modymdhms
để đặt tên biến và với hy vọng là sau này sẽ quay lại để sửa sau khi mà nghĩ ra cái tên phù hợp hơn. Và chắc chắn điều này là không nên chút nào.
Việc đặt tên khó phát âm cũng đồng nghĩa với việc khó nhớ và khó tìm kiếm. Một trường hợp nữa dẫn đến việc khó tìm kiếm là sử dụng chỉ 1 hoặc 2 chữ cái để đặt tên như i, j, k
bởi những chữ cái này xuất hiện quá nhiều trong code của bạn.
5.2. Nguyên tắc viết hàm
5.2.1. Hàm nên ngắn gọn và làm một việc duy nhất
Hãy cố gắng giữ số lượng dòng code trong một hàm không quá 20 dòng, trong trường hợp không thể làm được điều đó, hãy đảm bảo một hàm không có quá 100 dòng code, và mỗi dòng không có quá 150 ký tự. Điều này sẽ giúp cho người đọc dễ hiểu nội dung hàm mà bạn viết hơn.
Để có thể giữ được nội dung của hàm đủ nhỏ, chúng ta cần tách hàm lớn thành những hàm nhỏ hơn để gọi, và để dễ đọc, những hàm nhỏ hơn đó chỉ nên thực hiện một việc duy nhất để đảm bảo rằng người sử dụng sẽ không vô tình gây ra các tác động phụ nào tới những phần khác trong chương trình. Ví dụ trong hàm lấy dữ liệu không nên chứa các logic về việc đặt lại giá trị cho một biến nào đó.
Và khi tách hàm, phần còn lại trong hàm được tách cần theo nguyên tắc SLA (Single Level of Abstraction). Nghĩa là các lệnh trong một hàm nên có cùng mức độ trừu tượng. Lúc này, nội dung của hàm sau khi tách chỉ cần gọi tới những hàm nhỏ hơn mà không chứa logic phức tạp nữa.
5.2.2. Sử dụng tham số hợp lý
Ban đầu, khi mới tạo, các hàm thường sẽ có khá ít tham số, qua thời gian sửa đổi, do không muốn làm thay đổi logic đã có, nên các tham số mới có thể được thêm vào cuối hàm, và số lượng tham số tăng lên. Để giảm bớt số lượng tham số truyền vào hàm, chúng ta có thể nhóm các tham số thành một lớp, và truyền vào đối tượng của lớp đó thay vì truyền vào các tham số một cách rời rạc.
Không nên sử dụng tham số để điều khiển logic của hàm, thay vào đó, hãy tách thành hàm đó thành những hàm khác nhau để thực thi từng công việc cụ thể.
5.2.3. Chữ ký của hàm thể hiện được nội dung cần thực thi
Ở mục trước, chúng ta nói về việc hàm viết ngắn gọn sẽ giúp người đọc nhanh chóng hiểu được logic của hàm. Nhưng sẽ còn tốt hơn nếu chỉ cần nhìn vào chữ ký của hàm, người đọc có thể đoán được các bước mà hàm sẽ thực thi.
5.3. Nguyên tắc viết comment
5.3.1. Bổ sung thông tin cho code
// regex cho date với định dạng yyyy-mm-dd
dateMatcher := regexp.Compile("^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$
")
Comment trong ví dụ bên trên cung cấp nhanh thông tin về định dạng của pattern được khai báo. Khi có thêm comment, người đọc sẽ nhanh chóng nắm được logic của lệnh này nhanh hơn rất nhiều so với việc phải hiểu chuỗi pattern truyền vào cho hàm Compile
.
5.3.2. Bổ sung thông tin cho công việc
Comment có thể được sử dụng trong một số tình huống khác để người đọc biết được các công việc mà tác giả đã hoặc sẽ thực hiện:
- Những việc cần xử lý trong tương lai cho một hàm hay một class.
- Cảnh báo về việc sử dụng một hàm có thể tạo ra những tác động không mong muốn như thế nào.
- Giải thích về lý do lựa chọn phương án này thay vì phương án khác trong trường hợp có nhiều phương án được biết đến.
- Giải thích cho việc lựa chọn giá trị cho hằng và biến bằng giá trị nào đó thay vì một giá trị khác.
5.3.3. Không dùng comment nếu có thể
Trong nhiều trường hợp, chúng ta có thể tách một đoạn logic thành một hàm riêng rồi đặt tên cho hàm đó thay vì phải viết comment để nói lên ý nghĩa của đoạn code đó. Ví dụ đoạn code kiểm tra điều kiện như bên dưới kèm với comment
// Kiểm tra employee có đủ điều kiện
if ((employee.flags & HOURLY_FLAG) &&
(employee.age > 65))
Chúng ta hoàn toàn có thể tạo hàm mới với tên isEligibleForFullBenefits
rồi đưa logic trong if
vào làm nội dung cho hàm đó. Như vậy vừa có thể loại bỏ comment, vừa có thể tái sử dụng logic của hàm isEligibleForFullBenefits
ở những chỗ khác.
Ngoài ra, hãy cố gắng đặt tên biến và sử dụng class với tên gợi nhớ và có ý nghĩa để có thể không cần dùng comment mà người đọc vẫn có thể hiểu được.
5.3.4. Loại bỏ các comment thừa
Có một số loại comment thừa cần được loại bỏ trong chương trình của chúng ta:
- Comment cho các đoạn code không dùng nữa hoặc với ý định là sau này sẽ dùng lại khi cần.
- Comment cho các tham số của hàm mà ngay khi đọc tên và kiểu dữ liệu của tham số ta đã biết được ý nghĩa của nó, và comment đó không cung cấp thêm thông tin gì khác.
- Comment để lưu lại sự thay đổi theo theo từng lần chỉnh sửa của file. Chúng ta không cần tới những comment như này, do git đã làm quá tốt việc ghi nhận thay đổi trong code của chúng ta rồi.
5.4. Nguyên tắc xử lý lỗi
5.4.1. Sử dụng exception thay vì trả về mã lỗi
Đối với những ngôn ngữ không hỗ trợ exception, có một cách để xử lý lỗi, đó là trả về mã lỗi. Và nếu lập trình viên vẫn sử dụng cách này để báo lỗi phát sinh trong hàm trong những ngôn ngữ có sử dụng exception thì sẽ làm cho người đọc dễ bị rối do không nhanh chóng xác định được giá trị trả về đó là lỗi hay giá trị thực sự. Vì vậy hãy bắn ra exception khi gặp phải lỗi thay vì trả về một mã lỗi nào đó.
5.4.2. Sử dụng Try-Catch-Finally ngay đầu hàm
Khi sử dụng try-catch-finally
, chúng ta có vẻ như đang mong muốn thực hiện một transaction với các hành động chính sẽ nằm trong block của try
, còn trong block của catch
giống như việc đảm bảo cho trạng thái của hệ thống vẫn giữ được sự nhất quán ngay cả khi có lỗi xảy ra. Vì vậy nên đặt try-catch-finally
ở đầu hàm, điều này sẽ làm cho người đọc hiểu được ý định của bạn ngay khi đọc những dòng đầu tiên.
5.4.3. Thêm thông tin về ngữ cảnh cho exception
Khi gặp lỗi, chúng ta nên thêm những thông tin hữu ích về ngữ cảnh mà lỗi đó xảy ra để khi lưu lại thông tin về lỗi đó, lập trình viên sẽ dễ dàng lần theo các thông tin đã lưu và từ đó có thể nhanh chóng xác định nguyên nhân gốc rễ xảy ra lỗi.
Có một số cách để cung cấp thông tin về lỗi như:
- Định nghĩa các class riêng cho lỗi, người đọc có thể dựa vào tên class hoặc các thuộc tính trong class để có thể hiểu thêm về ngữ cảnh khi xảy ra lỗi.
- Thêm thông tin vào chuỗi mô tả lỗi.
5.4.4. Không trả về null
Khi một hàm có thể trả về null
, thì nơi gọi hàm đó sẽ cần phải kiểm tra xem kết quả nhận được có phải null
hay không rồi mới có thể xử lý tiếp được. Việc này tạo ra nhiều đoạn kiểm trong code mà không thể hiện được các ý định và nội dung chính mà tổng thể của đoạn code đó đang muốn thể hiện.
Trong trường hợp các hàm của thư viện có thể trả về giá trị null, chúng ta nên viết hàm riêng của mình để bọc các hàm đó lại rồi bắn ra exception hoặc trả về một giá trị đặc biệt.
5.4.5. Không nên bỏ qua lỗi
Rất nhiều trường hợp lập trình viên sẽ vô tình hoặc cố ý không xử lý gì trong trường hợp gặp lỗi, điều này gây khó khăn hoặc thậm làm cho người bảo trì không thể tìm được dấu vết của nơi xảy ra lỗi. Chúng ta chỉ nên bỏ qua lỗi khi biết chắc chắn rằng lỗi đó không ảnh hưởng hoặc không có nguy cơ ảnh hưởng tới hoạt động của chương trình.
Vì vậy, hãy luôn xử lý lỗi một cách hợp lý khi gặp phải nó.
5.5. Nguyên tắc viết unit test
5.5.1. Sử dụng logic thật đơn giản
Khi phát triển phần mềm, chúng ta viết unit test để đảm bảo code của chương trình chính hoạt động chính xác, nhưng điều gì đảm bảo cho unit test hoạt động đúng? Không lẽ viết test cho unit test? Và nếu đặt tiếp câu hỏi thì chắc hẳn bạn sẽ nhận thấy một vòng lặp vô hạn về việc viết test ở đây.
Vì vậy, để đảm bảo ít sai sót nhất có thể xảy ra, thì logic của unit test phải thật đơn giản. Có một số cách để làm được điều này:
- Tổ chức các bước trong unit test theo pattern AAA (arange, act, assert).
- Mỗi bài test nên chứa 1 lệnh assert.
- Mỗi bài test chỉ nên kiểm tra cho một trường hợp cụ thể.
5.5.2. Diễn đạt theo ngôn ngữ của nghiệp vụ
Unit test không chỉ có tác dụng đảm bảo code trong chương trình chính hoạt động chính xác, mà nó còn như một loại tài liệu mô tả về chương trình đang viết. Vì vậy hãy sử dụng các ngôn ngữ của nghiệp vụ để diễn tả các trường hợp trong unit test thay vì dùng các ngôn ngữ trong lập trình (kiểu dữ liệu, design pattern ...)
5.5.3. Nguyên tắc F.I.R.S.T
Nguyên tắc này là viết tắt của 5 từ :
- Fast: Unit test cần chạy nhanh để lập trình viên có thể chạy rất nhiều bài test trong thời gian ngắn, do nếu unit test chạy chậm thì chúng ta sẽ ngại trong việc phải chờ đợi, và các bài test không được chạy thường xuyên, kết quả là chương trình không đảm bảo.
- Independent: Các bài test không nên phụ thuộc vào nhau, tức sự thành công hay thất bại của một bài test không nên là đầu vào cho bài test khác. Điều này là quan trọng để chúng tra có thể chạy các bài test theo bất cứ thứ tự nào và chạy chúng song song với nhau.
- Repeatable: Các bài test cần chạy một cách độc lập với môi trường bên ngoài để bài test có thể được chạy lặp đi lặp lại ở bất cứ môi trường nào mà không bị gián đoạn. Hay nói cách khác, trước khi chạy các bài test, chúng ta không nên giả định về việc hệ thống đã có sẵn dữ liệu ban đầu. Trong lúc chạy test không nên phụ thuộc vào các dịch vụ có thể không tồn tại như database, file, network. Và sau khi chạy test không nên để lại dữ liệu hay gây ra tác động tới các hệ thống khác.
- Self-Validating: Kết quả của bài test chỉ nên trả về là đúng hoặc sai. Sau khi chạy test xong, chúng ta cần ngay lập tức xác định được bài test đó thành công hay thất bại thay vì việc phải tự so sánh một cách thủ công các giá trị hoặc các thông tin được trả về.
- Timely: Các bài test cần được viết đúng thời điểm, lý tưởng nhất là ngay trước khi viết production code. Bởi nếu viết test sau khi viết production code, chúng ta rất dễ rơi vào tình huống khó tạo ra unit test cho production code đã viết. Thường các lập trình viên sẽ sử dụng TDD (Test driven development) để đạt được điều này.
6. Tổng kết về Clean code
Việc thực hành các nguyên tắc để viết clean code là rất quan trọng đối với bất kỳ dự án phát triển phần mềm nào. Viết clean code không chỉ có lợi cho cá nhân lập trình viên mà còn cho cả nhóm phát triển và cho cả tổ chức nói chung.
Bằng việc tuân thủ các nguyên tắc clean code, các lập trình viên có thể cải thiện chất lượng tổng thể của chương trình, làm cho mã nguồn dễ hiểu, dễ sửa đổi và dễ gỡ lỗi hơn. Clean code giảm thiểu nợ kỹ thuật, giảm thiểu lỗi và nâng cao khả năng cộng tác giữa các thành viên trong nhóm.
Thông qua việc tìm hiểu về Clean Code và nguyên tắc viết mã sạch trong lập trình, chúng ta đã đặt nền móng cho một phong cách lập trình chuyên nghiệp và hiệu quả. Clean Code không chỉ đơn giản là việc tạo ra mã nguồn dễ đọc và dễ hiểu, mà còn là một triết lý, một tư duy mang tính bền vững giúp đội ngũ phát triển xây dựng và duy trì sản phẩm một cách hiệu quả.
Nguyên tắc viết Clean Code không chỉ là việc tuân thủ cú pháp và quy tắc, mà còn là việc hiểu rõ và tôn trọng những người sẽ đọc và làm việc với mã nguồn của bạn. Đây là sự tận tâm và sự tôn trọng đối với cộng đồng lập trình mà chúng ta nên thể hiện.
Việc viết Clean Code không chỉ mang lại lợi ích ngắn hạn về sự dễ bảo trì, mở rộng và tái sử dụng mã nguồn, mà còn xây dựng nền tảng cho một sản phẩm chất lượng và mang tính bền vững. Điều này không chỉ thúc đẩy sự tiến bộ cá nhân mà còn góp phần vào sự phát triển toàn diện của ngành công nghiệp lập trình.
Tóm lại, Clean Code không chỉ đơn thuần là một tập hợp nguyên tắc hay quy tắc, mà là một triết lý mang ý nghĩa sâu hơn trong lập trình, mang lại lợi ích cho cả người viết và những người sẽ sử dụng mã nguồn.
Bạn hãy thường xuyên theo dõi các bài viết hay về Lập Trình & Dữ Liệu trên 200Lab Blog nhé. Cũng đừng bỏ qua những khoá học Lập Trình tuyệt vời trên 200Lab nè.
Một vài bài viết mới bạn sẽ thích:
Bài viết liên quan
Apple lên tiếng về AI: Chúng ta có đang đánh giá quá cao Trí tuệ của nó?
Nov 21, 2024 • 8 min read
Whisper AI là gì? Công cụ chuyển giọng nói thành văn bản của Open AI
Oct 17, 2024 • 8 min read
Cursor AI là gì? Hướng dẫn Sử dụng Cursor AI cơ bản
Sep 16, 2024 • 13 min read
IDE là gì? Những công cụ IDE phổ biến nhất hiện nay
Aug 22, 2024 • 11 min read
Cookies là gì? Cookies được sử dụng như thế nào?
Aug 12, 2024 • 9 min read
SDLC là gì? Các mô hình Software Development Life Cycle phổ biến
Jul 13, 2024 • 27 min read