Code sáng tập 1: Vấn đề đặt tên

Cuốn sách Clean Code: A Handbook of Agile Software Craftsmanship là một kho tàng tri thức quý giá mà bất cứ lập trình viên nào cũng nên đọc nhiều lần trong sự nghiệp của mình. Với mong muốn giúp cuốn sách đến với những bạn đọc gặp khó khăn trong đọc hiểu tiếng Anh (hay đơn giản là thích tiếng Việt), tôi ghi chú lại những kiến thức quý giá này, bằng ngôn ngữ và ví dụ của bản thân, dưới dạng loạt bài blog.

Tôi bỏ qua chương đầu trong cuốn sách, là chương nói về tác hại của code tối nghĩa, các định nghĩa khác nhau của code sáng nghĩa. Vì nếu bạn đang đọc bài này, khả năng cao là bạn đã dính đòn khi làm việc với code rối rồi, và đang muốn tìm giải pháp viết code trong sáng hơn (hoặc đơn giản là sếp bạn bắt đọc).

Hi vọng loạt bài sẽ hữu ích với nhiều bạn đọc, hay ít nhất là với những người em lập trình viên trái ngành yêu dấu của tôi :)

Do tính chất công việc cá nhân, các ví dụ trong loạt bài này sẽ dùng ngôn ngữ JavaScript và có hơi hướm của game development, thay vì ngôn ngữ Java như trong sách gốc.

Tập 1: Vấn đề đặt tên

Đặt tên chưa bao giờ là bài toán dễ dàng. Một cái tên đúng nghĩa, dễ hiểu, sẽ giúp code “sáng” lên nhiều lần.

Sử dụng tên rõ nghĩa

Chắc hẳn ai cũng có ý thức phải đặt tên rõ nghĩa, nhưng tôi vẫn muốn nhấn mạnh thêm, việc này rất quan trọng.

Tên của hàm, biến, class, cần trả lời được những câu hỏi lớn: tại sao nó tồn tại, nó làm gì, và dùng như thế nào.

Một cái tên chung chung, ví dụ như:

// duration between touch began and ended in seconds
int d;

Sẽ rất khó hiểu, trót hiểu rồi cũng rất dễ quên, so với:

int touchDurationInSeconds;
int touchElapsedInSeconds;
int secondsSinceTouchBegan;

Tên rõ nghĩa giúp cho code dễ hiểu và dễ thay đổi. Hãy cùng đoán đoạn code dưới đây làm gì?

function filter(users) {
    let t = Date.now();

    let u = [];
    for (let i = 0; i < users.length; i++) {
        if (users[i].timestamp >= t - 86400000) {
            u.push(users[i]);
        }
    }

    return u;
}

Bạn có đoán được không? Tuy đoạn code rất ngắnđơn giản, nhưng không hề dễ hiểu nếu chỉ đọc qua.

Vấn đề không phải ở việc code ngắn hay đơn giản thế nào, mà là nó rõ nghĩa đến đâu. Đoạn code trên ngầm định rằng người đọc biết câu trả lời cho những câu hỏi như:

  1. Hàm này dùng làm gì? Filter là lọc, những lọc cái gì? Lọc với điều kiện như thế nào?
  2. t = Date.now(); là mốc thời gian gì và trong đơn vị nào?
  3. Số 86400000 có nghĩa gì?
  4. user.timestamp là mốc thời gian gì?

Nhiều khi để hiểu, người đọc không chỉ cần đọc nội dung hàm, mà còn phải tìm những chỗ sử dụng để đoán ý nghĩa, cách dùng; hoặc tệ hơn, phải đi hỏi người viết ra hàm (tệ hơn nữa nếu người này nghỉ công ty rồi, mà việc này thì hay xảy ra lắm).

Là hàm lọc những người dùng hoạt động trong vòng 24h vừa qua, chúng ta có thể viết lại tốt hơn như sau:

const ONE_DAY_IN_MS = 24 * 60 * 60 * 1000;

function getActiveUsers(allUsers) {    
    const nowInMs = Date.now();
    const lastAcceptTimestamp = nowInMs - ONE_DAY_IN_MS;

    let activeUsers = [];

    for (let i = 0; i < users.length; i++) {
        if (users[i].lastActiveAt >= lastAcceptTimestamp) {
            activeUsers.push(users[i]);
        }
    }

    return activeUsers;
}

Với những thay đổi đặt tên đơn giản, rõ ràng đoạn code đã trở nên rõ nghĩa hơn nhiều!

Đừng ngại nếu tên bị dài, hãy dùng miễn là nó rõ nghĩa. Nếu tên bị quá dài, tức là bạn mắc phải một vấn đề khác mang tính hệ thống hơn, hãy đón đọc tập sau để hiểu rõ hơn nhé!

Tránh "dương Đông kích Tây"

Lập trình viên cần tránh đặt tên dễ làm người đọc lạc lối. Ví dụ, không đặt tên biến là accountList nếu trong hệ thống có class List nhưng biến này không phải kiểu dữ liệu đó. Để chỉ một mảng các account thì accounts là đủ rồi.

Tránh dùng những cái tên nhìn quá giống nhau. Ví dụ, MainCharacterHealthControllerMainCharacterHealerController dễ bị nhầm lẫn. Tương tự, sẽ có người tốn hàng giờ tìm lỗi nếu bạn có cảnodeNamenodename trong một đoạn code.

Dùng tên dễ tìm kiếm

Tìm kiếm (và thay đổi hàng loạt) trong codebase là việc chúng ta thường xuyên phải làm. Vì thế, hãy đặt tên dễ tìm.

Tìm và sửa số 4 sẽ khó khăn hơn nhiều so với tìm constant NUM_USERS_IN_ROOM.

Tìm userIndex sẽ dễ hơn nhiều so với i, j hay k. Chỉ dùng tên biến 1 chữ cái cho các đoạn code cực ngắn và rõ nghĩa (ví dụ các vòng lặp ngắn). Độ dài tên cần tương ứng với kích cỡ phạm vi (scope) mà tên tồn tại.

Quy ước đặt tên

Tên class và object cần là danh từ, không dùng động từ. Viết hoa cho tên class và viết thường cho tên object. Ví dụ: class Customer, var customer, var payment.

Tên function cần là động từ hoặc cụm động từ. Các hàm truy xuất/thay đổi dữ liệu nên dùng tiền tố get, set hay is. Ví dụ: getAmount, setAmount, isEmpty.

Chọn một từ cho một khái niệm

Nếu bạn đã dùng get để đặt tên hàm lấy một dữ liệu nào đó, đừng dùng fetch, retrieve cho các hàm tương tự khác. Cũng như vậy, đừng dùng cả submitsend để đặt tên các hàm gửi dữ liệu đi. PlayerUser, AccountProfile đều là các cặp từ khó phân biệt.

Với mỗi khái niệm, hãy chọn một từ và chung thủy với nó.

Chú ý tới ngữ cảnh

Thông thường, hiếm có cái tên ngắn nào rõ nghĩa nếu không đặt vào ngữ cảnh cụ thể.

Ví dụ, state có thể là trạng thái của dữ liệu (ví dụ: trạng thái tắt, bật), cũng có thể là bang trong địa chỉ người dùng (ví dụ, bang California ở Mỹ). Thông thường mà nói, những cái tên như objectStateaddressState sẽ rõ nghĩa hơn là state. Tuy nhiên, nếu bạn đang viết class Address, thì rõ ràng member variable state là đủ tường minh và không cần viết dài ra thêm nữa. Như vậy, tùy ngữ cảnh mà ta lựa chọn tên cho phù hợp.

class Address {
    constructor(street, city, state) {
        this._street = street;
        this._city = city;
        this._state = state;
    },

    getState() {
        return this._state;
    }
}

// giả sử có object userAddress thuộc kiểu Address
var addressState = userAddress.getState();

Kết

Đặt tên luôn là một vấn đề học búa, phụ thuộc nhiều vào khả năng ngôn ngữ và diễn tả hơn là kĩ thuật. Đặc biệt, tiếng Anh lại không phải ngôn ngữ thuần thục của đa số lập trình viên Việt, khiến vấn đề càng trở nên khó khăn hơn.

Chúng ta không có cách nào khác ngoài trau dồi tiếng Anh và chăm chỉ đọc các codebase chất lượng (của người tiền nhiệm hoặc open-source projects) để học hỏi. Những nỗ lực trong việc đặt tên tốt sẽ mang lại sự trong sáng, dễ hiểu, từ đó tăng tính dễ bảo trì, dễ thay đổi của toàn hệ thống.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Son Tung

1 bài viết.
30 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Bài viết liên quan
White
4 0
Nếu cứ thấy số 6 gọi là số 6, thấy số 9 gọi là số 9, thì tổng của hai số hẳn là 9 + 6 và sinh ra kết quả là một số 15. Vạn vật sinh ra đều có cho ...
HVN_FAMILUG viết hơn 1 năm trước
4 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
1 bài viết.
30 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!