KISS (Keep It Simple, Stupid): Vì sao những hệ thống sống lâu nhất lại thường... rất đơn giản


Đặt vấn đề

Có một điều khá thú vị.

Nếu bạn hỏi một lập trình viên mới vào nghề:

“Nếu có thêm một tuần để làm tính năng này, em sẽ làm gì?”

Rất có thể câu trả lời sẽ là:

  • Thêm cache.
  • Thêm message queue.
  • Thêm AI.
  • Thêm microservice.
  • Thêm dashboard.
  • Thêm vài design pattern cho “chuẩn”.

Nhưng nếu hỏi cùng câu đó với một kỹ sư đã vận hành hệ thống nhiều năm, câu trả lời thường lại rất khác.

“Anh sẽ cố xóa bớt vài thứ.”

Nghe hơi kỳ.

Người mới nghĩ đến việc thêm. Người nhiều kinh nghiệm lại nghĩ đến việc bớt đi.

Đó cũng chính là tinh thần của một nguyên tắc đã tồn tại hơn nửa thế kỷ.

KISS — Keep It Simple, Stupid.

Nghe hơi “phũ”, nhưng ý của nó không phải chê ai ngốc cả.

Nó chỉ muốn nhắc chúng ta một điều:

Nếu có hai cách giải quyết một vấn đề, hãy chọn cách đơn giản hơn, miễn là nó vẫn đáp ứng được yêu cầu.

Nghe thì quá hiển nhiên.

Nhưng làm được mới khó.


Phần mềm không chết vì thiếu tính năng

Có một nghịch lý mình gặp khá nhiều.

Một project mới tạo.

Khoảng vài nghìn dòng code.

Ai cũng hiểu.

Deploy nhanh.

Bug ít.

Rồi khách hàng cần thêm tính năng.

Lại thêm vài API.

Lại thêm authentication.

Lại thêm cache.

Lại thêm MQ.

Lại thêm scheduler.

Lại thêm Kafka.

Lại thêm Redis.

Lại thêm Elasticsearch.

Lại thêm AI Agent.

Lại thêm MCP.

Lại thêm Workflow.

Mỗi lần thêm vào đều rất hợp lý.

Không ai sai.

Nhưng sau ba năm.

Không còn ai hiểu toàn bộ hệ thống nữa.

Điều đáng sợ không phải là số dòng code.

Mà là số lượng mối liên kết giữa chúng.


Một tính năng nhỏ có thể kéo theo cả dây chuyền

Giả sử khách hàng yêu cầu rất đơn giản.

“Hiển thị số lượt xem sản phẩm.”

Nghe có vẻ chỉ cần thêm một cột.

Nhưng nếu hệ thống đã quá phức tạp, rất có thể nó sẽ trở thành:

 1Frontend
 2 3API Gateway
 4 5Recommendation Service
 6 7User Profile Service
 8 9Analytics Service
1011Kafka
1213Consumer
1415ClickHouse
1617Materialized View
1819Redis
2021API
2223Frontend

Một con số nhỏ.

Nhưng đi qua mười hệ thống.

Nếu ở giữa Kafka bị chậm.

Redis hết RAM.

ClickHouse replication delay.

Consumer chết.

Thì cái số “123 lượt xem” cũng biến mất.

Không phải vì thuật toán khó.

Mà vì hệ thống đã quá nhiều tầng.


Độ phức tạp giống như nợ lãi kép

Nghe thì có vẻ mỗi module chỉ thêm một chút.

Nhưng độ phức tạp không tăng tuyến tính.

Nó tăng gần giống số lượng mối quan hệ.

Giả sử có:

  • 5 service

Mỗi service đều gọi nhau.

Số kết nối cần quản lý có thể lên tới:

$$ \frac{N(N-1)}{2} $$

Khi đó:

  • 5 service → 10 kết nối
  • 10 service → 45 kết nối
  • 20 service → 190 kết nối
  • 50 service → 1225 kết nối

Điều làm đội vận hành mất ngủ không phải là số service.

Mà là số lượng quan hệ giữa chúng.

Mỗi quan hệ đều có:

  • timeout
  • retry
  • circuit breaker
  • authentication
  • version
  • logging
  • monitoring
  • permission

Và tất cả đều có thể hỏng.


KISS không có nghĩa là viết ít code

Đây là chỗ nhiều người hiểu nhầm nhất.

KISS không nói:

Viết càng ít càng tốt.

Nó nói:

Đừng làm mọi thứ phức tạp hơn mức cần thiết.

Ví dụ.

Có người viết:

1if user.age >= 18:
2    return True
3else:
4    return False

Trong khi chỉ cần:

1return user.age >= 18

Hay:

1if status == 1:
2    process()

Đơn giản.

Dễ đọc.

Dễ hiểu.

Không cần tạo thêm năm lớp abstraction chỉ để gọi một hàm.


Đơn giản không phải là sơ sài

Đây là điểm khác biệt rất lớn.

Một cây cầu đơn giản không có nghĩa là cây cầu yếu.

Một chiếc máy bay đơn giản không có nghĩa là nó ít an toàn.

Ngược lại.

Trong ngành hàng không.

Người ta loại bỏ mọi thứ không cần thiết.

Vì mỗi một bộ phận thêm vào đều có xác suất hỏng.

Phần mềm cũng vậy.

Mỗi class mới.

Mỗi service mới.

Mỗi dependency mới.

Mỗi framework mới.

Đều là một thứ cần cập nhật.

Một thứ có thể có CVE.

Một thứ có thể hết người maintain.

Một thứ có thể gây lỗi sau vài năm.


Vì sao kỹ sư nhiều kinh nghiệm thường thích “xóa code”?

Có một câu nói khá nổi tiếng:

“Code tốt nhất là code không tồn tại.”

Nghe hơi cực đoan.

Nhưng thử nghĩ.

Một đoạn code:

  • không có bug
  • không cần test
  • không cần review
  • không cần maintain
  • không cần migrate
  • không cần update

…chính là đoạn code đã được xóa.

Rất nhiều lần tối ưu hệ thống, kết quả cuối cùng không phải là viết thêm.

Mà là:

  • bỏ một lớp cache không cần thiết
  • bỏ một service trung gian
  • bỏ một cron job
  • bỏ vài nghìn dòng code cũ
  • gộp hai API thành một

Hiệu năng tăng.

Bug giảm.

Đội vận hành nhẹ đầu hơn.


KISS trong thời đại AI

Đây là điều mình thấy khá thú vị vài năm gần đây.

AI khiến việc sinh code trở nên cực kỳ dễ.

Bạn chỉ cần gõ:

“Viết giúp tôi hệ thống chatbot.”

Mười giây sau.

Bạn có vài nghìn dòng code.

Có Redis.

Có Kafka.

Có Docker.

Có Kubernetes.

Có CQRS.

Có Event Sourcing.

Có đủ mọi thứ.

Vấn đề là…

Bạn có thật sự cần chúng không?

AI rất giỏi viết code.

Nhưng AI không chịu trách nhiệm vận hành hệ thống của bạn lúc 2 giờ sáng.

Người trực production mới là người chịu.

Đó là lý do kỹ năng quan trọng hơn bao giờ hết không phải là:

“Làm sao viết thêm?”

Mà là:

“Làm sao bỏ bớt?”


Một bài học mình rất thích

Có lần mình đọc được một câu nói đại ý như thế này:

“Mọi kẻ ngốc đều có thể làm cho một hệ thống phức tạp hơn. Thiên tài là người làm cho nó đơn giản đi.”

Nghe có vẻ hơi ngạo mạn.

Nhưng nghĩ kỹ lại khá đúng.

Làm một kiến trúc nhiều tầng không khó.

Ghép thêm framework không khó.

Copy một repository trên GitHub cũng không khó.

Điều khó là sau ba năm, năm năm, thậm chí mười năm…

Một kỹ sư mới vào công ty vẫn có thể đọc hiểu hệ thống chỉ sau vài ngày.

Đó mới là giá trị của sự đơn giản.


Tổng kết

KISS không phải là lời khuyên để viết ít code.

Cũng không phải lời khuyên chống lại công nghệ mới.

Nó chỉ nhắc chúng ta một điều rất đơn giản:

Mỗi dòng code mới đều là một lời hứa rằng bạn sẽ phải bảo trì nó trong tương lai.

Trước khi thêm một framework, một service hay một lớp abstraction mới, hãy tự hỏi:

  • Có thật sự cần không?
  • Có cách nào đơn giản hơn không?
  • Nếu một kỹ sư mới đọc đoạn code này sau hai năm, họ có hiểu ngay không?
  • Nếu bỏ nó đi, hệ thống còn hoạt động không?

Đôi khi, tiến bộ không nằm ở việc xây thêm một tầng kiến trúc.

Mà nằm ở việc đủ can đảm để xóa đi một tầng không còn cần thiết.

Đó cũng chính là tinh thần của KISS.

Không phải vì lập trình viên lười.

Mà vì sự đơn giản là thứ khó đạt được nhất sau khi đã hiểu đủ nhiều về sự phức tạp.

Tham khảo

Bình luận