Đơn giản hơn linh hoạt trong thiết kế API

Khi thiết kế thư viện hay API công khai, có hai trục thường mâu thuẫn: đơn giản (ít tuỳ chọn, đường dùng rõ ràng) và linh hoạt (nhiều tuỳ chọn, hỗ trợ nhiều use case). Quan điểm cân bằng thường thấy là cả hai đều quan trọng, nhưng kinh nghiệm xây sản phẩm cho thấy đơn giản nên thắng linh hoạt khi phải chọn — thừa tuỳ chọn không phải tài sản mà là gánh nặng cho cả người dùng và người duy trì.

Vì sao thừa tuỳ chọn là độc

Mỗi tuỳ chọn mới đẩy chi phí về ba phía:

Zen of Python (PEP 20) diễn đạt cùng triết lý này: “There should be one — and preferably only one — obvious way to do it”. Tiểu luận “Worse Is Better” của Richard Gabriel khẳng định rằng cài đặt đơn giản (dù không hoàn hảo) thường thắng cài đặt hoàn chỉnh phức tạp trong thực tế, vì người dùng và contributor đều ưu tiên cái mình hiểu được. Rich Hickey trong “Simple Made Easy” tách hai khái niệm bị nhầm lẫn: simple (không bện) khác với easy (gần tay), và software dài hạn phải đầu tư vào simple.

Trải nghiệm với xthread

xthread (viết tại Teko, 7/2023) là một dẫn chứng cá nhân của bài học này — nhìn từ phía ngược lại. API ban đầu có 6 callback (on_started, on_paused, on_unpaused, on_stopped, on_error, on_result), hai tham số ít dùng (autostart, pause_timeout), và cặp pause/unpause được thêm vì “muốn cho dev quyền tự quản lý” dù không có use case bắt buộc nào. Sau khi dùng và public PyPI, nhận ra phần lớn flexibility đó không có người dùng nhưng vẫn phải maintain và document. Nếu viết lại, một API tối thiểu chỉ cần start, stop, is_running đã đủ cho gần như mọi case.

Khi nào tuỳ chọn là chính đáng

Không phải mọi tuỳ chọn đều là độc. Một tuỳ chọn được coi là chính đáng khi:

Heuristic ngược chiều: nếu một tuỳ chọn chỉ “đẹp về khả năng” mà không có người dùng kêu thiếu, đó là dấu hiệu nên bỏ. Nguyên tắc YAGNI (“You Aren’t Gonna Need It”) của Extreme Programming nói cùng ý — chỉ thêm tính năng khi có nhu cầu thật, không vì tưởng tượng nhu cầu.

Cập nhật: 2026-05-29