Cách Viết Mã Sạch Bằng Cách Suy Nghĩ Như Kiến Trúc Sư
Bạn đã từng thấy một codebase mà mọi tệp đều giống như mở một ngăn kéo đồ của người khác? Các biến được đặt tên như data2 và temp_fix_dont_delete. Các hàm làm rất nhiều việc nhưng lại được gọi là handleSubmit. Các chú thích mâu thuẫn với mã mà chúng đang cố gắng giải thích.
Hầu hết các lập trình viên coi mã như là việc giải quyết các vấn đề tức thời. Sửa lỗi. Thêm tính năng. Gửi nó đi nhanh chóng. Nhưng các kiến trúc sư nghĩ khác. Họ nhìn thấy tòa nhà sẽ được sống trong nhiều thập kỷ, chứ không chỉ là căn phòng đang được sơn hôm nay.
Tư Duy Của Kiến Trúc Sư
Các kiến trúc sư thực sự không bắt đầu với vật liệu. Họ bắt đầu với hành vi của con người. Con người sẽ di chuyển qua không gian này như thế nào? Họ sẽ muốn tụ tập ở đâu? Điều gì xảy ra khi không gian đông đúc, khi nó vắng vẻ, hay khi nó đã được sống trong suốt hai mươi năm?
Các kiến trúc sư phần mềm cũng suy nghĩ theo cách tương tự. Họ không bắt đầu với các hàm và lớp. Họ bắt đầu với lập trình viên sẽ duy trì mã này vào lúc 3 giờ sáng khi cơ sở dữ liệu gặp sự cố và khách hàng đang tức giận. Họ thiết kế cho lập trình viên mới gia nhập đội ngũ và cần hiểu quy trình thanh toán. Họ suy nghĩ về người sẽ kế thừa hệ thống này khi mọi người khác đã rời đi.
Sự thay đổi trong quan điểm này thay đổi mọi thứ về cách bạn cấu trúc mã.
Thay vì hỏi "Làm thế nào để làm cho điều này hoạt động?" bạn hỏi "Làm thế nào để làm cho điều này rõ ràng?" Thay vì tối ưu hóa cho máy tính, bạn tối ưu hóa cho con người sẽ đọc mã sáu tháng sau. Thay vì giải quyết vấn đề ngay lập tức, bạn giải quyết loại vấn đề mà điều này đại diện.
Các codebase sạch nhất mà tôi đã gặp không phải được viết bởi những lập trình viên thông minh nhất. Chúng được viết bởi những lập trình viên hiểu rằng mã là một cuộc hội thoại với bản thân trong tương lai và các đồng đội của bạn, không phải là một câu đố cần giải quyết một lần và quên đi.
Cấu Trúc Như Một Hình Thức Giao Tiếp
Kiến trúc là về mối quan hệ giữa các không gian, không phải là các phòng riêng lẻ. Trong các tòa nhà, bạn hiểu nhà bếp bằng sự gần gũi với phòng ăn, phòng ngủ chính bằng sự tách biệt khỏi các khu vực chung, và phòng thay đồ bằng vị trí giữa bên ngoài và bên trong.
Mã hoạt động theo cách tương tự. Mã sạch giao tiếp cấu trúc của nó thông qua các mối quan hệ giữa các phần của nó.
Xem xét cách bạn đặt tên cho các thứ. Một kiến trúc sư không gán nhãn các phòng là "Không gian 1" và "Không gian 2". Họ sử dụng những cái tên ngay lập tức truyền đạt mục đích và mối quan hệ: "suite chính," "phòng tắm khách," "góc ăn sáng." Các tên biến của bạn cũng nên hoạt động tương tự. userEmailForValidation kể một câu chuyện mà email không thể. calculateMonthlyRecurringRevenue() giải thích ý định theo cách mà calculate() không thể làm.
Tổ chức tệp theo các nguyên tắc tương tự. Bạn không thể đặt nhà bếp trong tầng hầm và gara ở tầng ba. Tuy nhiên, các lập trình viên thường rải rác chức năng liên quan khắp các thư mục ngẫu nhiên, hoặc đổ mọi thứ vào các tệp khổng lồ phục vụ mười bảy mục đích khác nhau.
Mã sạch nhóm các khái niệm liên quan lại với nhau và tách biệt các khái niệm không liên quan. Cấu trúc tệp của bạn nên kể câu chuyện của ứng dụng của bạn. Ai đó nên có thể hiểu các khái niệm kinh doanh chính chỉ bằng cách nhìn vào cây thư mục của bạn.
Luồng Phụ Thuộc
Các kiến trúc sư rất chú ý đến luồng giao thông. Con người di chuyển từ lối vào đến các khu vực khác như thế nào? Nơi nào hình thành các điểm tắc nghẽn? Điều gì xảy ra khi mọi người cần rời đi cùng một lúc?
Trong mã, điều này chuyển thành luồng phụ thuộc. Các kiến trúc sạch thiết lập các quy tắc rõ ràng về những gì có thể phụ thuộc vào điều gì. Logic kinh doanh cốt lõi không phụ thuộc vào chi tiết cơ sở dữ liệu hoặc các framework giao diện người dùng. Các chính sách cấp cao không phụ thuộc vào các chi tiết thực hiện cấp thấp.
Điều này không phải là lý thuyết trừu tượng. Nó có những lợi ích thực tiễn ngay lập tức. Khi logic xử lý thanh toán của bạn không phụ thuộc trực tiếp vào cơ sở dữ liệu cụ thể của bạn, bạn có thể kiểm tra nó mà không cần thiết lập cơ sở dữ liệu. Khi các quy tắc kinh doanh của bạn không nhập các thành phần React, bạn có thể tái sử dụng chúng trong các ngữ cảnh khác nhau. Khi miền cốt lõi của bạn không biết về các API bên ngoài, bạn có thể giả lập các API đó mà không cần thay đổi logic chính của bạn.
Các codebase sạch nhất mà tôi đã làm việc theo một quy tắc đơn giản: Các phụ thuộc chỉ hướng vào trong. Các vấn đề bên ngoài như cơ sở dữ liệu, API và framework phụ thuộc vào logic kinh doanh của bạn, không phải theo chiều ngược lại. Điều này tạo ra các hệ thống linh hoạt, có thể kiểm tra và chịu được thay đổi.
Thiết Kế Để Thay Đổi
Các tòa nhà rất tốn kém để sửa đổi. Bạn không thể dễ dàng di chuyển một cầu thang hoặc thêm một phòng tắm mà không cần công việc cấu trúc lớn. Nhưng các kiến trúc sư tốt nhất thiết kế cho sự linh hoạt trong các ràng buộc. Họ sử dụng các hệ thống mô-đun, tạo ra các không gian có thể phục vụ nhiều mục đích, và thiết lập các mẫu có thể mở rộng.
Phần mềm có vấn đề ngược lại. Nó rẻ để thay đổi nhưng tốn kém để hiểu. Chi phí không nằm ở việc di chuyển mã xung quanh—mà là trong việc tìm hiểu mã làm gì và cách nó tương tác.
Mã sạch dự đoán sự thay đổi bằng cách làm cho cấu trúc hiện tại trở nên rõ ràng. Khi bạn cần sửa đổi quy trình đăng ký người dùng, bạn nên ngay lập tức biết tệp nào chứa logic đó. Khi một quy tắc kinh doanh thay đổi, bạn nên có thể tìm và cập nhật nó ở một nơi rõ ràng.
Điều này đòi hỏi bạn phải suy nghĩ vượt ra ngoài tính năng ngay lập tức. Những điều gì khác có thể thay đổi theo cách tương tự? Những khái niệm nào có khả năng phát triển cùng nhau? Những phần nào của hệ thống nên được tách biệt khỏi nhau?
Sử dụng các công cụ AI như Claude để phân tích cấu trúc mã hiện tại của bạn. Hãy để nó xác định các vấn đề liên kết tiềm ẩn hoặc đề xuất cách tổ chức tốt hơn chức năng liên quan. Để GPT-4o mini giúp bạn tư duy về các tác động của các quyết định kiến trúc khác nhau trước khi bạn cam kết thực hiện chúng.
Mục tiêu không phải là dự đoán mọi thay đổi có thể xảy ra—mà là tạo ra mã giao tiếp cấu trúc của nó rõ ràng đến mức các thay đổi trở nên rõ ràng thay vì bí ẩn.
Trọng Lượng Của Các Trừu Tượng
Các kiến trúc sư hiểu rằng mỗi quyết định thiết kế đều có trọng lượng. Một mái nhà vòm tạo ra sự kịch tính nhưng làm phức tạp việc sưởi ấm. Một kế hoạch mở cải thiện luồng nhưng giảm tính riêng tư. Mỗi lựa chọn đều liên quan đến sự đánh đổi.
Các lập trình viên thường đối xử với các trừu tượng như thể chúng miễn phí. Họ tạo ra các lớp cơ sở và các hệ thống kế thừa và các giao diện tổng quát mà không xem xét gánh nặng nhận thức mà những quyết định này đặt lên những người duy trì mã trong tương lai.
Mã sạch sử dụng trừu tượng một cách chiến lược. Nó trừu tượng khi sự trừu tượng thực sự đơn giản hóa việc hiểu hoặc loại bỏ sự trùng lặp có ý nghĩa. Nó duy trì cụ thể khi sự trừu tượng chỉ thêm các lớp mà không làm tăng độ rõ ràng.
Bài kiểm tra không phải là liệu bạn có thể tạo ra một trừu tượng hay không—mà là liệu trừu tượng đó có làm cho mã dễ hiểu và sửa đổi hơn không. Một UserService xử lý xác thực, cập nhật hồ sơ và đặt lại mật khẩu không thực sự trừu tượng bất kỳ điều gì có ý nghĩa—nó chỉ là một túi các chức năng liên quan lỏng lẻo với một cái tên sang trọng.
Tốt hơn nên có ba lớp tập trung mà mỗi lớp thực hiện một việc tốt hơn là một lớp thực hiện mọi thứ kém.
Công Cụ Để Suy Nghĩ Kiến Trúc
AI hiện đại có thể giúp bạn phát triển tư duy kiến trúc, nhưng chỉ khi bạn sử dụng nó đúng cách. Đừng yêu cầu nó tạo ra toàn bộ mô-đun hoặc giải quyết các vấn đề thiết kế phức tạp từ đầu. Thay vào đó, hãy sử dụng nó để phân tích và tinh chỉnh tư duy của bạn.
Tải mã của bạn lên Document Summarizer và yêu cầu nó xác định các trách nhiệm cốt lõi của các mô-đun khác nhau. Chúng có tập trung và nhất quán không, hay là chúng đang làm quá nhiều việc không liên quan?
Sử dụng Code Explainer không chỉ để hiểu cú pháp không quen thuộc, mà còn để phân tích các mẫu kiến trúc trong các codebase mà bạn ngưỡng mộ. Điều gì làm cho cấu trúc của họ rõ ràng? Họ tổ chức logic miền phức tạp như thế nào?
Thử Mind Mapping Tool để hình dung các mối quan hệ giữa các phần khác nhau của hệ thống của bạn. Đôi khi việc nhìn thấy các kết nối một cách đồ họa sẽ tiết lộ các vấn đề liên kết mà không rõ ràng trong cấu trúc tuyến tính của các tệp mã.
Mục tiêu là phát triển trực giác kiến trúc của bạn—khả năng nhìn vào mã và ngay lập tức thấy cấu trúc của nó, điểm yếu và tiềm năng cải thiện.
Tầm Nhìn Dài Hạn
Hầu hết các lập trình viên tối ưu hóa cho sprint tiếp theo. Các kiến trúc sư tối ưu hóa cho thập kỷ tiếp theo.
Điều này không có nghĩa là thiết kế quá mức hoặc xây dựng cho các yêu cầu tương lai giả định. Nó có nghĩa là xây dựng các hệ thống vẫn có thể hiểu và sửa đổi khi chúng phát triển. Nó có nghĩa là chọn các giải pháp nhàm chán, dự đoán hơn là những cái thông minh. Nó có nghĩa là viết mã tự giải thích hơn là mã ấn tượng với những lập trình viên khác.
Các codebase sạch nhất không phải là những cái tinh vi nhất về mặt kỹ thuật. Chúng là những cái được tổ chức một cách suy nghĩ. Chúng là những cái mà các thành viên mới trong nhóm có thể trở nên năng suất nhanh chóng, nơi mà các lỗi dễ dàng được cô lập và sửa chữa, nơi việc thêm các tính năng mới không yêu cầu hiểu toàn bộ hệ thống.
Mức độ rõ ràng này không xảy ra tình cờ. Nó yêu cầu suy nghĩ như một người sẽ sống trong hệ thống mà bạn đang xây dựng, không chỉ là một người đang đi qua.
Khi bạn ngồi xuống viết mã, hãy hỏi bản thân: Câu chuyện này cấu trúc này kể gì? Ai đó sẽ hiểu điều này như thế nào khi tôi không ở đây để giải thích? Điều này sẽ trông như thế nào khi lớn gấp mười lần?
Bản thân bạn trong tương lai—và các đồng đội của bạn—sẽ cảm ơn bạn vì đã suy nghĩ như một kiến trúc sư thay vì chỉ đơn thuần là lập trình viên.
Nền Tảng Của Mọi Thứ
Mã sạch không phải là về việc tuân theo quy tắc hay ghi nhớ các mẫu. Nó về việc phát triển sự đồng cảm với những người sẽ tương tác với mã của bạn—bao gồm cả bản thân bạn trong sáu tháng tới khi bạn đã quên lý do tại sao bạn đã đưa ra một số quyết định nhất định.
Kiến trúc là sự đồng cảm được hiện thực hóa. Mỗi quyết định về cấu trúc, đặt tên và tổ chức thực sự là một quyết định về giao tiếp. Bạn đang chọn cách kể câu chuyện của hệ thống của bạn theo cách mà người khác có thể hiểu, mở rộng và duy trì.
Các kiến trúc sư tốt nhất không chỉ thiết kế các tòa nhà đứng vững—họ thiết kế các tòa nhà nâng cao cuộc sống của những người sử dụng chúng. Các lập trình viên tốt nhất không chỉ viết mã hoạt động—họ viết mã giúp các lập trình viên khác thực hiện công việc tốt nhất của họ.
Hãy bắt đầu suy nghĩ như một kiến trúc sư. Codebase của bạn sẽ trở thành một nơi mà mọi người muốn làm việc, không phải là một mê cung mà họ phải điều hướng.