Điểm chính
1. Sự phức tạp là gốc rễ của những thách thức trong thiết kế phần mềm
Sự phức tạp đến từ sự tích lũy của các phụ thuộc và những phần mã khó hiểu.
Sự phức tạp tích lũy dần dần. Khi các hệ thống phần mềm phát triển, chúng có xu hướng trở nên phức tạp hơn do sự tích lũy dần dần của các phụ thuộc giữa các thành phần và các phần mã khó hiểu. Sự phức tạp này thể hiện qua ba cách chính:
- Khuếch đại thay đổi: Những thay đổi nhỏ đòi hỏi phải sửa đổi ở nhiều nơi
- Tải nhận thức: Các nhà phát triển cần hiểu một lượng lớn thông tin để thực hiện thay đổi
- Những điều chưa biết: Không rõ mã nào cần được sửa đổi hoặc thông tin nào là liên quan
Đơn giản là giải pháp. Để chống lại sự phức tạp, các nhà thiết kế phần mềm nên tập trung vào việc tạo ra các thiết kế đơn giản, rõ ràng, giảm thiểu các phụ thuộc và những phần mã khó hiểu. Điều này bao gồm:
- Thiết kế mô-đun: Chia hệ thống thành các mô-đun độc lập
- Ẩn thông tin: Bao bọc các chi tiết triển khai trong các mô-đun
- Trừu tượng rõ ràng: Cung cấp các giao diện đơn giản che giấu sự phức tạp bên dưới
2. Lập trình chiến lược vượt trội hơn các phương pháp tiếp cận chiến thuật
Cách tiếp cận tốt nhất là thực hiện nhiều đầu tư nhỏ liên tục.
Suy nghĩ dài hạn mang lại kết quả tốt hơn. Lập trình chiến lược tập trung vào việc tạo ra một thiết kế tuyệt vời mà tình cờ hoạt động, thay vì chỉ làm cho mã hoạt động. Cách tiếp cận này bao gồm:
- Đầu tư thời gian vào thiết kế ban đầu
- Liên tục thực hiện các cải tiến nhỏ
- Tái cấu trúc mã để duy trì thiết kế sạch
Lập trình chiến thuật dẫn đến nợ kỹ thuật. Mặc dù các phương pháp tiếp cận chiến thuật có thể nhanh hơn trong ngắn hạn, chúng thường dẫn đến:
- Tích lũy các sửa chữa nhanh và các giải pháp tạm thời
- Khó khăn ngày càng tăng trong việc thực hiện thay đổi theo thời gian
- Chi phí phát triển dài hạn cao hơn
Bằng cách áp dụng tư duy chiến lược, các nhà phát triển có thể tạo ra các hệ thống dễ bảo trì và phát triển, cuối cùng tiết kiệm thời gian và công sức trong dài hạn.
3. Các mô-đun nên sâu, không nên nông
Các mô-đun tốt nhất là những mô-đun cung cấp chức năng mạnh mẽ nhưng có giao diện đơn giản.
Độ sâu tạo ra sự trừu tượng. Các mô-đun sâu che giấu sự phức tạp triển khai đáng kể đằng sau các giao diện đơn giản. Cách tiếp cận này:
- Giảm tải nhận thức cho người dùng của mô-đun
- Cho phép dễ dàng sửa đổi triển khai
- Khuyến khích ẩn thông tin và bao bọc
Các mô-đun nông thêm sự phức tạp. Các mô-đun có giao diện phức tạp so với chức năng của chúng được coi là nông. Những mô-đun này:
- Tăng sự phức tạp tổng thể của hệ thống
- Tiết lộ các chi tiết triển khai không cần thiết
- Làm cho hệ thống khó hiểu và sửa đổi
Để tạo ra các mô-đun sâu, hãy tập trung vào việc thiết kế các giao diện đơn giản, trực quan che giấu sự phức tạp bên dưới. Cố gắng tối đa hóa tỷ lệ giữa chức năng và độ phức tạp của giao diện.
4. Giao diện tốt là chìa khóa để quản lý sự phức tạp
Giao diện của một mô-đun chứa hai loại thông tin: chính thức và không chính thức.
Giao diện được thiết kế tốt đơn giản hóa hệ thống. Giao diện tốt cung cấp một sự trừu tượng rõ ràng về chức năng của mô-đun mà không tiết lộ các chi tiết không cần thiết. Chúng nên:
- Đơn giản và dễ sử dụng
- Che giấu sự phức tạp của triển khai
- Cung cấp cả thông tin chính thức (ví dụ: chữ ký phương pháp) và không chính thức (ví dụ: mô tả hành vi cấp cao)
Giao diện nên phát triển một cách cẩn thận. Khi sửa đổi mã hiện có:
- Xem xét tác động đến giao diện của mô-đun
- Tránh tiết lộ các chi tiết triển khai
- Cố gắng duy trì hoặc cải thiện sự trừu tượng được cung cấp bởi giao diện
Bằng cách tập trung vào việc tạo và duy trì các giao diện tốt, các nhà phát triển có thể quản lý sự phức tạp và làm cho hệ thống của họ trở nên mô-đun và dễ hiểu hơn.
5. Bình luận là yếu tố quan trọng để tạo ra sự trừu tượng
Bình luận cung cấp cách duy nhất để nắm bắt đầy đủ các sự trừu tượng, và các sự trừu tượng tốt là nền tảng của thiết kế hệ thống tốt.
Bình luận hoàn thiện sự trừu tượng. Trong khi mã có thể biểu đạt các chi tiết triển khai, bình luận là cần thiết để nắm bắt:
- Các quyết định thiết kế cấp cao
- Lý do đằng sau các lựa chọn
- Kỳ vọng và ràng buộc
- Các sự trừu tượng không rõ ràng từ mã
Viết bình luận trước. Bằng cách viết bình luận trước khi triển khai mã:
- Bạn làm rõ suy nghĩ của mình về thiết kế
- Bạn có thể đánh giá và tinh chỉnh các sự trừu tượng sớm
- Bạn đảm bảo tài liệu luôn được cập nhật
Tập trung vào cái gì và tại sao, không phải làm thế nào. Bình luận tốt nên:
- Mô tả những điều không rõ ràng từ mã
- Giải thích mục đích và hành vi cấp cao của mã
- Tránh lặp lại những gì mã làm
Bằng cách ưu tiên các bình luận rõ ràng, thông tin, các nhà phát triển có thể tạo ra các sự trừu tượng tốt hơn và cải thiện thiết kế tổng thể của hệ thống.
6. Đặt tên và định dạng nhất quán tăng cường khả năng đọc
Tên tốt là một dạng tài liệu: chúng làm cho mã dễ hiểu hơn.
Nhất quán giảm tải nhận thức. Bằng cách thiết lập và tuân theo các quy ước về đặt tên và định dạng, các nhà phát triển có thể:
- Làm cho mã dễ dự đoán và dễ đọc hơn
- Giảm nỗ lực tinh thần cần thiết để hiểu mã
- Làm nổi bật các sự không nhất quán có thể chỉ ra lỗi hoặc vấn đề thiết kế
Chọn tên cẩn thận. Tên tốt nên:
- Chính xác và không mơ hồ
- Tạo ra hình ảnh rõ ràng về thực thể được đặt tên
- Được sử dụng nhất quán trong toàn bộ mã
Định dạng quan trọng. Định dạng nhất quán giúp:
- Làm rõ cấu trúc của mã
- Nhóm các yếu tố liên quan một cách trực quan
- Nhấn mạnh thông tin quan trọng
Bằng cách chú ý đến việc đặt tên và định dạng, các nhà phát triển có thể cải thiện đáng kể khả năng đọc và bảo trì mã của họ.
7. Tinh chỉnh liên tục là cần thiết để duy trì thiết kế sạch
Nếu bạn muốn một cấu trúc phần mềm sạch, cho phép bạn làm việc hiệu quả trong dài hạn, thì bạn phải dành thêm thời gian ban đầu để tạo ra cấu trúc đó.
Thiết kế là một quá trình liên tục. Thiết kế phần mềm sạch đòi hỏi:
- Tái cấu trúc thường xuyên để cải thiện mã hiện có
- Đánh giá liên tục các quyết định thiết kế
- Sẵn sàng thực hiện thay đổi khi hệ thống phát triển
Đầu tư vào cải tiến. Để duy trì thiết kế sạch:
- Phân bổ thời gian cho việc dọn dẹp và tái cấu trúc
- Giải quyết các vấn đề thiết kế kịp thời, trước khi chúng tích lũy
- Xem mỗi thay đổi mã là cơ hội để cải thiện thiết kế tổng thể
Cân bằng giữa hoàn hảo và tiến bộ. Trong khi cố gắng đạt được thiết kế sạch:
- Nhận ra rằng một số thỏa hiệp có thể là cần thiết
- Tập trung vào việc thực hiện các cải tiến nhỏ
- Ưu tiên các thay đổi mang lại lợi ích đáng kể nhất
Bằng cách coi thiết kế là một quá trình tinh chỉnh liên tục, các nhà phát triển có thể giữ cho hệ thống của họ sạch và dễ quản lý khi chúng phát triển và tiến hóa.
8. Xử lý lỗi nên được đơn giản hóa, không nên lan tràn
Cách tốt nhất để loại bỏ sự phức tạp trong xử lý ngoại lệ là định nghĩa API của bạn sao cho không có ngoại lệ nào cần xử lý: định nghĩa lỗi ra khỏi sự tồn tại.
Giảm các trường hợp ngoại lệ. Để đơn giản hóa xử lý lỗi:
- Thiết kế API để giảm thiểu các điều kiện ngoại lệ
- Sử dụng các hành vi mặc định để xử lý các trường hợp biên phổ biến
- Xem xét liệu các ngoại lệ có thực sự cần thiết hay không
Tổng hợp xử lý lỗi. Khi các ngoại lệ không thể tránh khỏi:
- Xử lý nhiều ngoại lệ ở một nơi duy nhất khi có thể
- Sử dụng các hệ thống phân cấp ngoại lệ để đơn giản hóa việc xử lý các lỗi liên quan
- Tránh bắt các ngoại lệ mà bạn không thể xử lý một cách có ý nghĩa
Làm cho các trường hợp bình thường trở nên dễ dàng. Tập trung vào việc làm cho con đường không có lỗi qua mã của bạn trở nên đơn giản và rõ ràng nhất có thể. Cách tiếp cận này:
- Giảm tải nhận thức cho các nhà phát triển
- Giảm thiểu khả năng giới thiệu lỗi
- Làm cho mã dễ hiểu và bảo trì hơn
Bằng cách đơn giản hóa xử lý lỗi, các nhà phát triển có thể tạo ra các hệ thống mạnh mẽ và dễ hiểu hơn.
9. Mã đa dụng thường tốt hơn các giải pháp đặc dụng
Ngay cả khi bạn sử dụng một lớp theo cách đặc dụng, thì việc xây dựng nó theo cách đa dụng vẫn ít tốn công hơn.
Tính tổng quát thúc đẩy khả năng tái sử dụng. Mã đa dụng:
- Có thể được áp dụng cho nhiều vấn đề hơn
- Thường đơn giản và trừu tượng hơn
- Có xu hướng có giao diện sạch hơn
Tránh chuyên môn hóa sớm. Khi thiết kế chức năng mới:
- Bắt đầu với cách tiếp cận đa dụng
- Chống lại sự cám dỗ để tối ưu hóa cho các trường hợp sử dụng cụ thể quá sớm
- Cho phép thiết kế phát triển dựa trên các mẫu sử dụng thực tế
Cân bằng giữa tính tổng quát và đơn giản. Trong khi cố gắng đạt được các giải pháp đa dụng:
- Tránh quá kỹ thuật hoặc thêm sự phức tạp không cần thiết
- Đảm bảo thiết kế đa dụng vẫn dễ sử dụng cho các trường hợp phổ biến
- Sẵn sàng tạo ra các giải pháp đặc dụng khi thực sự cần thiết
Bằng cách ưu tiên các thiết kế đa dụng, các nhà phát triển có thể tạo ra các hệ thống linh hoạt và dễ bảo trì hơn, sẵn sàng xử lý các yêu cầu trong tương lai.
10. Viết mã để dễ đọc, không phải để dễ viết
Phần mềm nên được thiết kế để dễ đọc, không phải để dễ viết.
Ưu tiên khả năng bảo trì dài hạn. Khi viết mã:
- Tập trung vào việc làm cho nó dễ hiểu cho người đọc trong tương lai
- Tránh các lối tắt hoặc thủ thuật thông minh làm mờ mục đích của mã
- Đầu tư thời gian vào việc tạo ra các sự trừu tượng rõ ràng và tài liệu
Làm cho mã rõ ràng. Cố gắng viết mã mà:
- Có thể được hiểu nhanh chóng với ít nỗ lực tinh thần
- Sử dụng các quy ước đặt tên rõ ràng và nhất quán
- Có cấu trúc logic và dễ theo dõi
Tái cấu trúc để rõ ràng. Thường xuyên xem xét và cải thiện mã hiện có:
- Tìm kiếm cơ hội để đơn giản hóa các phần phức tạp
- Chia nhỏ các phương pháp dài thành các phần nhỏ hơn, tập trung hơn
- Loại bỏ sự trùng lặp và không nhất quán
Bằng cách ưu tiên khả năng đọc hơn sự dễ viết, các nhà phát triển có thể tạo ra các hệ thống dễ bảo trì, gỡ lỗi và mở rộng theo thời gian. Cách tiếp cận này có thể đòi hỏi nhiều nỗ lực hơn ban đầu nhưng sẽ mang lại lợi ích trong việc giảm sự phức tạp dài hạn và cải thiện năng suất của nhóm.
Cập nhật lần cuối:
Đánh giá
Triết Lý Thiết Kế Phần Mềm, Ấn Bản Thứ 2 nhận được những đánh giá trái chiều. Nhiều người khen ngợi những hiểu biết sâu sắc về quản lý độ phức tạp và thiết kế các module sâu, trong khi một số người chỉ trích sự nhấn mạnh vào các chú thích và thiếu chiều sâu ở một số khía cạnh. Độc giả đánh giá cao lối viết rõ ràng và lời khuyên thực tiễn, đặc biệt là đối với các nhà phát triển mới. Tuy nhiên, một số lập trình viên có kinh nghiệm cho rằng cuốn sách quá cơ bản hoặc không đồng ý với một số khuyến nghị. Sự tập trung của cuốn sách vào lập trình hướng đối tượng và góc nhìn học thuật được ghi nhận, với một số người mong muốn có thêm ví dụ về ngôn ngữ đa dạng và ứng dụng thực tế.