Giới thiệu
Đọc code là một kỹ năng thiết yếu cho lập trình viên. Nó không chỉ giúp hiểu rõ mã nguồn hiện tại mà còn hỗ trợ việc thêm tính năng mới, tìm lỗi hay thực hiện refactoring. Khi làm việc với các module quen thuộc, chúng ta thường chỉ cần tập trung vào một phạm vi nhỏ của mã nguồn. Nhưng khi phải làm việc với một module chưa biết, làm thế nào để bắt đầu và nhanh chóng nắm bắt 80% thông tin quan trọng nhất? Dưới đây là một số mẹo từ workshop đọc code mà chúng tôi đã tổng hợp.
Bắt đầu từ mô tả chức năng
Khi nhận một module mới, điều đầu tiên không phải là lao vào xem xét mã nguồn, mà là hiểu chức năng mà module đó phục vụ. Nếu đó là một module giao diện người dùng (UI), hãy tương tác với màn hình mà nó tạo ra. Nếu là module miền (domain), hãy hiểu logic kinh doanh cơ bản mà nó đại diện. Nếu là module cho một quy trình cụ thể, hãy nắm bắt các bước chính của quy trình. Chúng ta cần biết module đó phục vụ mục đích gì trước khi tìm hiểu mã nguồn làm thế nào để đạt được điều đó.
Tìm lớp điểm vào (entry point)
Lớp điểm vào định nghĩa ranh giới của mã nguồn. Lớp điểm vào thường trong suốt khi làm việc với một dự án đã biết vì chúng ta thường không cần phải chỉnh sửa điểm vào thường xuyên. Nhưng để làm việc với một dự án mà chúng ta không có kiến thức, điều tốt nhất là tìm lớp điểm vào đầu tiên. Điều này giúp chúng ta tập trung vào mã sau đó và bỏ qua tất cả mã trước lớp điểm vào. Bắt đầu từ đó, ít nhất chúng ta biết nơi để đặt debugger đầu tiên của mình.
Đặt câu hỏi cho bản thân: Mã nguồn phân tích như thế nào
Mục tiêu của phân tích ban đầu là trả lời câu hỏi về cách mã nguồn phân tích. Nếu không có mục tiêu, chúng ta dễ bị thu hút bởi một số triển khai và bị lạc trong rừng mã nguồn. Phân tích ban đầu nên tránh đi sâu quá mức. Thường thì, càng lớn mã nguồn, chúng ta nên đào sâu càng ít.
Một số cách để khám phá phân tích:
Nhìn lướt qua các package để có cái nhìn tổng quan
Cách tổ chức các package cho chúng ta manh mối phân tích cấp cao. Khi thấy một module UI có các package được đặt tên là models, views, controllers, chúng ta có thể đoán module đó sử dụng mô hình MVC. Khi thấy một module có các package được đặt tên là services, sessions, repositories, databases, chúng ta có thể tìm thấy mối quan hệ phân lớp giữa chúng. Một số package sử dụng ngôn ngữ miền của chúng như tên gọi như queues, aggregates, filters; nếu chúng ta không biết về miền, thật khó để hiểu chúng đại diện cho điều gì. Khi thấy các package như tools, helpers, hay utilities, chúng ta biết có thể bỏ qua chúng trong phân tích ban đầu. Tuy nhiên, đôi khi chúng ta có thể không tìm thấy điều gì có ý nghĩa do sự mơ hồ hoặc sự phát triển của module.
Imports giúp khám phá sự phụ thuộc
Bằng cách nhìn vào imports của mỗi lớp, chúng ta có thể nhanh chóng xây dựng một đồ thị sự phụ thuộc. Từ imports, chúng ta có thể phân tích các phụ thuộc nội bộ và bên ngoài. Trong một module được thiết kế tốt, nếu một lớp có nhiều phụ thuộc bên ngoài, nó thường là một lớp ranh giới mà nên có ít logic bên trong. Từ những lớp đó, chúng ta có thể xây dựng khung của module. UML được tạo ra bởi IntelliJ có thể là một trợ lý để khám phá sự phụ thuộc, nhưng nếu không cẩn thận về hướng khám phá đồ thị phụ thuộc, nó nhanh chóng trở nên rất phức tạp với các lớp và các mũi tên hướng đi khắp nơi.
Lấy thêm thông tin từ interfaces, thuộc tính và phương thức
Chúng ta đi qua các interfaces để hiểu chức năng chính. Từ các thuộc tính, chúng ta có thể thấy những gì được đóng gói. Chúng ta có thể phân chia chúng theo cái nào được sử dụng để đọc, cái nào được sử dụng để ghi hoặc cái nào được sử dụng cho cả hai. Hoặc chúng ta có thể phân chia chúng theo bước nào nó được sử dụng. Đôi khi, khi module không được thiết kế tốt hoặc nó khá đơn giản và nhỏ, phân tích có thể dựa trên phương thức thay vì lớp. Trong trường hợp này, chúng ta cần đào sâu vào phương thức để phân tích.
Nhận diện mẫu có thể tăng tốc phân tích
Khi chúng ta tìm thấy một số mẫu trong một phần của mã, chúng ta có thể giả định những gì phần còn lại của mã sẽ làm. Trong tình huống này, chúng ta không đọc mã, chúng ta chỉ xác minh giả thuyết của mình. Chúng ta biết nơi để đi và cái gì cần xem, vì vậy chúng ta có thể phân tích mã nhanh hơn. Điều này cũng có nghĩa nếu chúng ta thu thập được nhiều mẫu trong đầu, chúng ta sẽ đọc mã nhanh hơn.
Kiểm tra lịch sử commit nếu thấy điều gì đó lạ
Lịch sử commit cho chúng ta ý tưởng về mã là mới hay cũ, nó đã được sửa đổi thường xuyên hay hiếm khi được sửa đổi kể từ khi nó được tạo ra. Nếu chúng ta thấy một số mã không nhất quán với ngữ cảnh, chúng ta có thể kiểm tra lịch sử commit. Nếu nó nằm trong cùng một commit, có thể có lý do ẩn mà chúng ta không biết. Nếu không, thì sự không nhất quán có thể đến từ việc lập trình viên đã suy nghĩ khác với người trước đó. Chúng ta cũng có thể kiểm tra mô tả câu chuyện của commit này để biết lý do tại sao mã được thêm vào như vậy nếu chúng ta muốn tìm hiểu thêm.
Kiểm tra các bài kiểm tra để hiểu một phần cụ thể của mã
Đôi khi các bài kiểm tra cũng rất hữu ích. Các bài kiểm tra đơn vị có thể giúp chúng ta hiểu một lớp, các bài kiểm tra tích hợp có thể giúp chúng ta hiểu toàn bộ logic kinh doanh. Một số bài kiểm tra sử dụng phong cách Given-When-Then. Chúng là tài liệu có thể thực thi cung cấp cho chúng ta các ví dụ cụ thể về hành vi mong đợi.
Thực tiễn tốt nhất trong việc đọc mã
- Hiểu rõ ngữ cảnh: Trước khi đọc mã, hãy chắc chắn bạn đã nắm bắt được ngữ cảnh và mục đích của module.
- Sử dụng công cụ hỗ trợ: Sử dụng các công cụ như IntelliJ hoặc Eclipse để dễ dàng điều hướng mã.
- Ghi chú: Đừng ngần ngại ghi chú lại những điều quan trọng trong quá trình đọc mã.
Những cạm bẫy thường gặp
- Quá chú trọng vào chi tiết: Đôi khi chúng ta dễ bị cuốn vào các chi tiết nhỏ mà quên mất mục tiêu lớn hơn.
- Không hỏi đồng đội: Đừng ngần ngại hỏi đồng đội nếu bạn gặp khó khăn trong việc hiểu mã.
Mẹo tối ưu hóa hiệu suất
- Phân tích mã nguồn một cách hệ thống: Hãy chia mã thành các phần nhỏ có thể quản lý được.
- Sử dụng các kỹ thuật tìm kiếm: Sử dụng các chức năng tìm kiếm trong IDE để tìm nhanh các lớp và phương thức.
Kết luận
Đọc mã là một kỹ năng quan trọng mà mỗi lập trình viên cần rèn luyện. Bằng cách áp dụng những mẹo và phương pháp được nêu trên, bạn có thể cải thiện khả năng đọc mã của mình và làm việc hiệu quả hơn với các module mới. Hãy bắt đầu thực hành ngay hôm nay để nâng cao kỹ năng của mình!
Câu hỏi thường gặp (FAQ)
- Q: Tại sao việc đọc mã lại quan trọng?
A: Đọc mã giúp bạn hiểu cấu trúc, chức năng và logic của ứng dụng, từ đó dễ dàng hơn trong việc bảo trì và phát triển. - Q: Làm thế nào để cải thiện kỹ năng đọc mã?
A: Thực hành thường xuyên, tham gia vào các dự án mã nguồn mở và học hỏi từ đồng nghiệp.