- Trong văn hóa kỹ nghệ phần mềm, những người tạo ra hệ thống phức tạp thường được công nhận hơn, còn người chọn giải pháp đơn giản lại không được đánh giá đúng mức
- Trong đánh giá thăng chức, phỏng vấn và review thiết kế, sự phức tạp thường bị nhầm là “tầm ảnh hưởng”, khiến xu hướng thêm các lớp trừu tượng hóa và khả năng mở rộng không cần thiết ngày càng mạnh hơn
- Cách triển khai đơn giản thường trở thành “thành quả vô hình”, trong khi cấu trúc phức tạp thì dễ lấp đầy hồ sơ thăng chức bằng những mô tả hào nhoáng và tài liệu hóa
- Năng lực thực sự không nằm ở việc dùng nhiều công cụ hơn, mà ở khả năng phán đoán và sự tự tin để biết khi nào cần loại bỏ sự phức tạp
- Cả kỹ sư lẫn lãnh đạo đều phải làm cho sự đơn giản trở nên hữu hình và xây dựng hệ thống đánh giá - tưởng thưởng chính thức công nhận điều đó
Đơn giản vs phức tạp: sự bất đối xứng trong câu chuyện thăng chức
- Ví dụ về hai kỹ sư trong cùng một nhóm: Engineer A phát hành tính năng chỉ trong vài ngày với 50 dòng code gọn gàng, còn Engineer B mất 3 tuần để hoàn thành sau khi đưa vào một lớp trừu tượng mới, hệ thống pub/sub và framework cấu hình
- Công việc của Engineer B có thể được mô tả trong hồ sơ thăng chức là “thiết kế kiến trúc hướng sự kiện có khả năng mở rộng, đưa vào lớp trừu tượng tái sử dụng, xây dựng framework cấu hình”
- Còn công việc của Engineer A chỉ được diễn đạt bằng ba từ: “triển khai tính năng X”
- Thực tế đó là công việc tốt hơn, nhưng vì được làm cho trông đơn giản nên trở thành đóng góp vô hình
- Không ai được thăng chức nhờ ‘sự phức tạp đã tránh được’ — sở dĩ sự phức tạp trông có vẻ thông minh là vì hệ thống đánh giá được thiết kế để thưởng cho nó
Cách sự phức tạp được củng cố trong phỏng vấn và review thiết kế
- Trong phỏng vấn thiết kế hệ thống, nếu đề xuất một giải pháp đơn giản (một cơ sở dữ liệu duy nhất, API trực quan, tầng cache), ứng viên sẽ bị chất vấn: “Nếu có 10 triệu người dùng thì sao?”
- Càng thêm service, queue và sharding, ứng viên càng có cảm giác người phỏng vấn hài lòng hơn
- Bài học ứng viên rút ra là: “Câu trả lời đơn giản là chưa đủ”
- Người phỏng vấn có thể có lý do hợp lý khi gây áp lực như vậy (để kiểm tra tư duy dưới áp lực và mức độ hiểu biết về hệ thống phân tán), nhưng thông điệp ứng viên nhận được vẫn là “phức tạp thì gây ấn tượng”
- Trong review thiết kế cũng lặp lại mô thức thêm các lớp và trừu tượng hóa không cần thiết trước câu hỏi “Có nên future-proof không?”
- Không phải vì vấn đề thực sự đòi hỏi, mà vì phòng họp kỳ vọng như vậy
- Có rất nhiều trường hợp lớp trừu tượng được tạo ra chỉ để tránh vài dòng code trùng lặp, nhưng cuối cùng lại khiến việc hiểu và bảo trì khó hơn
- Code trông “chuyên nghiệp” hơn, nhưng người dùng không nhận được tính năng sớm hơn, còn kỹ sư tiếp theo phải mất nửa ngày chỉ để hiểu lớp trừu tượng trước khi sửa đổi
Độ phức tạp phù hợp vs độ phức tạp không cần thiết (Unearned Complexity)
- Bản thân sự phức tạp không phải lúc nào cũng là vấn đề — để xử lý hàng triệu giao dịch cần hệ thống phân tán, và khi 10 đội cùng xây một sản phẩm thì cần có ranh giới dịch vụ
- Vấn đề là độ phức tạp không cần thiết: khác nhau giữa “đã chạm giới hạn cơ sở dữ liệu nên cần sharding” và “có thể 3 năm nữa sẽ chạm giới hạn nên hãy sharding ngay từ bây giờ”
- Code và kiến trúc của những kỹ sư hiểu điều này thường mang lại cảm giác “đương nhiên là thế”, không có ma thuật hay vẻ quá lanh lợi, cũng không khiến người khác cảm thấy mình ngu vì không hiểu
- Con đường thật sự để trở thành senior không phải là học thêm nhiều công cụ và pattern hơn, mà là biết khi nào không nên dùng chúng — ai cũng có thể thêm phức tạp, nhưng để bỏ bớt nó cần kinh nghiệm và sự tự tin
Cách thực hành dành cho kỹ sư
- Cần làm cho sự đơn giản trở nên hữu hình — vì bản thân công việc không tự lên tiếng, và hệ thống đánh giá cũng không được thiết kế để lắng nghe nó
- Thay vì viết “triển khai tính năng X”, hãy mô tả là “sau khi đánh giá ba cách tiếp cận gồm kiến trúc hướng sự kiện và lớp trừu tượng tùy biến, đã kết luận rằng cách triển khai đơn giản đáp ứng cả nhu cầu hiện tại lẫn nhu cầu dự kiến, phát hành trong 2 ngày và vận hành 6 tháng không sự cố”
- Quyết định không xây một thứ gì đó cũng là một quyết định, và là quyết định quan trọng — cần được tài liệu hóa tương xứng
- Trong review thiết kế, thay vì đơn thuần nhượng bộ trước câu hỏi “có nên future-proof không?”, hãy trình bày rằng “nếu thêm sau này thì sẽ mất ngần này công, nếu thêm bây giờ thì tốn ngần này chi phí, nên chờ sẽ tốt hơn”
- Đây không phải phản bác, mà là cho thấy bạn đã xem xét kỹ
- Hãy nói thẳng với manager rằng “tôi muốn cách tài liệu hóa công việc phản ánh không chỉ code mà còn những quyết định tôi đã đưa ra” — từ góc nhìn của manager, điều này cũng cung cấp ngôn ngữ để họ bảo vệ bạn
- Nếu đã làm tất cả như vậy mà đội vẫn chỉ thăng chức cho người xây hệ thống tinh vi nhất, thì đó cũng là thông tin hữu ích — một số tổ chức thực sự coi trọng sự đơn giản, còn một số khác chỉ nói vậy nhưng lại thưởng cho điều ngược lại
Cách thực hành dành cho lãnh đạo kỹ thuật
- Thiết lập incentive là trách nhiệm của lãnh đạo — phần lớn tiêu chí thăng chức được thiết kế theo hướng thưởng cho sự phức tạp, và “impact” thường được đo bằng quy mô và phạm vi của thứ đã xây
- Đánh giá không chỉ thứ đã xây mà cả những gì đã tránh phải xây
- Trong review thiết kế, thay vì hỏi “đã cân nhắc khả năng mở rộng chưa?”, hãy đổi thành “phiên bản đơn giản nhất có thể phát hành là gì, và đâu là tín hiệu cụ thể cho thấy cần thứ phức tạp hơn?”
- Chỉ một câu hỏi này cũng thay đổi cuộc chơi: lấy sự đơn giản làm mặc định, và đặt gánh nặng chứng minh lên sự phức tạp
- Trong thảo luận thăng chức, trước một hồ sơ đầy danh sách hệ thống ấn tượng, cần hỏi ngược lại: “tất cả những thứ đó có thực sự cần thiết không? Hệ thống pub/sub có thật sự cần, hay chỉ trông đẹp trên giấy tờ?”
- Khi thành viên trong nhóm phát hành một thứ gọn gàng, đơn giản, lãnh đạo phải giúp họ xây dựng câu chuyện — “đã đánh giá nhiều cách tiếp cận và chọn cách đơn giản nhất để giải quyết vấn đề” chỉ trở thành một ví dụ thăng chức thuyết phục khi lãnh đạo thực sự đối xử với nó như vậy
- Hãy chú ý đến những gì bạn công khai chúc mừng trong kênh của nhóm — nếu chỉ khen các dự án lớn và phức tạp, mọi người sẽ tối ưu theo hướng đó
- Cần công nhận những kỹ sư đã xóa bớt code, những người dám nói “chưa cần đâu” và đã đúng
10 bình luận
thiết kế theo định hướng résumé...
Tôi không nghĩ những đề xuất trong bài này là vô nghĩa, nhưng tôi cho rằng chúng quá yếu để thắng được "thiết kế đồ sộ". Bên đó quá, quá dễ để giải thích :(
Ý kiến trên Hacker News
Trong một câu hỏi phỏng vấn, tôi được đưa ra tình huống hai người gửi qua lại một bảng tính bằng email
Tôi trả lời rằng sẽ chuyển sang Google Sheets, nhưng có vẻ người phỏng vấn muốn tôi tự thiết kế công cụ
Khi đó khá gượng gạo, và đến giờ tôi vẫn không chắc nên rút ra bài học gì từ chuyện đó
Họ nên công nhận đó là một câu trả lời tốt, rồi dẫn tiếp bằng kiểu “đây là tình huống giả định để đánh giá thiết kế kỹ thuật, vậy hãy thử thiết kế một hệ thống mới”
Nếu ứng viên không chấp nhận tiền đề đó thì lại là một tín hiệu khác để đánh giá
Nếu là tôi, tôi sẽ hỏi: “Ta có nên giả định là chưa có giải pháp sẵn có nào và thiết kế mới từ đầu không?”
Đây giống như phiên bản thiết kế hệ thống của những cuộc cãi vã về thuật toán, nơi người phỏng vấn chỉ muốn nghe đúng đáp án họ mong đợi
Thực tế đó là quyết định đúng, nhưng Patrick Collison đã trực tiếp gọi điện và hỏi: “bạn không qua vòng phỏng vấn, nhưng bạn có hiểu dụng ý của nó không?”
Cuối cùng anh ấy phỏng vấn lại và đậu
Đây là một giai thoại cho thấy việc hiểu mục đích của buổi phỏng vấn quan trọng đến mức nào
Một công ty phà lớn quản lý vị trí tàu và phân công nhân sự bằng Google Sheets, và bạn tôi nói “đây không phải việc một tập đoàn lớn nên làm”
Nhưng tôi lại thấy việc giải quyết vấn đề bằng một công cụ đã được kiểm chứng là rất tuyệt
Nhờ vậy họ có thể vận hành mà không cần đội phát triển nội bộ hay thuê ngoài đắt đỏ
Đó là một trải nghiệm khiến tôi phải chôn sâu sự tự phụ của mình
Sau khi đối phương giải thích cụ thể điểm nào không ổn, lúc đó mới nên bắt đầu thiết kế kỹ thuật
Có rất nhiều lý do khiến người ta không dùng được Sheets — giới hạn tính năng, hạn chế truy cập tại Trung Quốc, chính sách công ty, vấn đề mạng, v.v.
Khách hàng có thể đã muốn một giải pháp tùy biến chính vì những lý do đó
Nói cách khác, vai trò của lập trình viên không phải chỉ là bảo “hãy dùng Google Sheets”, mà là hiểu bối cảnh của khách hàng
Các công cụ lập trình AI đang làm vấn đề này tệ hơn theo cách tinh vi hơn
Giờ đây có thể tạo ra kiến trúc phức tạp trong 5 phút, nhưng chi phí bảo trì thì vẫn y nguyên
Kết quả là những cấu trúc hào nhoáng hơn được dựng lên rất nhanh, và cả tài liệu phục vụ thăng tiến cũng hoàn thành trong chốc lát
Nhưng trên thực tế chẳng ai hiểu hoàn toàn đoạn mã đó
Thước đo thật sự của sự đơn giản là “người tiếp theo có thể hiểu mà không cần hỏi gì không?”, và mã do AI tạo ra vẫn chưa vượt qua được bài kiểm tra đó
Giờ chuyện đó chỉ càng tệ hơn
Vì vậy tôi lấy văn hóa hiểu code trong tổ chức làm tiêu chí khi chọn công việc
Tôi không muốn trải qua lại tình cảnh không ai hiểu hệ thống nữa
Nếu mục tiêu là giải quyết vấn đề, thì dù là công cụ do AI tạo ra hay công cụ mua sẵn, cuối cùng nó cũng phải giải quyết được vấn đề
Nhưng nếu sản phẩm có sẵn không phù hợp, thì các giải pháp tùy biến tự tạo sẽ ngày càng nhiều
Chỉ là nếu không ai hiểu chúng, thì người tiếp theo lại sẽ làm lại từ đầu
Dù vậy, ở khía cạnh đưa người dùng và người tạo ra sản phẩm lại gần nhau hơn thì cũng có thể xem là một cải thiện
Ví dụ, ghi rõ các chỉ dẫn như “KISS”, “YAGNI” trong
AGENTS.mdsẽ rất hữu íchVấn đề là “người tiếp theo” rốt cuộc lại chính là bản thân tôi sau 6 tháng
AI cũng gặp vấn đề tương tự do giới hạn context window
Nhiều lập trình viên chỉ chạy theo stack đang thịnh hành mà không nghĩ đến khả năng vận hành
AI cũng sẽ không nói với bạn “cái này đang thiết kế quá tay đấy”
Nếu bạn muốn Kubernetes và ElasticSearch, nó sẽ cứ thế tạo ra cho bạn
Với trải nghiệm ở cả FAANG lẫn startup, điểm cốt lõi là cân bằng giữa phức tạp và đơn giản
Ở công ty lớn, các cách vá víu tạm bợ có thể làm hại năng suất của hàng nghìn người,
còn ở startup, hạ tầng quá mức có thể giết chết công ty
Một kỹ sư thật sự lão luyện là người phân biệt được hai tình huống đó và biết dùng kinh nghiệm để chọn trade-off phù hợp
Khi còn làm ở Amazon (2005~2008), có hai giải thưởng tượng trưng cho văn hóa công ty vào thời đó
Giải “Just Do It” tượng trưng cho việc chủ động giải quyết vấn đề, còn giải “Door Desk” tượng trưng cho sự tiết kiệm và đơn giản
Có một giai thoại là một nhân viên được trao giải vì dọn đi một cái TV vô dụng, và phần thưởng lại chính là cái TV đó
Sự đơn giản như một phép ẩn dụ ngoài đời thật lại hơi mơ hồ
Nếu muốn bảo vệ cho sự đơn giản thì phải diễn đạt bằng ngôn ngữ kinh doanh
Kiểu như “giảm 80% số sự cố”, “cắt giảm 40% chi phí”, “cải thiện 33% hiệu năng”
Bản thân sự đơn giản thì không được đánh giá, nhưng kết quả của nó lại được đánh giá rất cao
Tôi đã chuyển việc refactor thành mô hình chi phí để đo KPI, và giảm MTTR tới 60%
Phải trực tiếp cho thấy những con số như vậy thì mới được công nhận
Với vai trò quản lý, tôi thích code đơn giản
Nhưng đó là vì đội của tôi gồm những người có kỹ năng tốt
Với một đội ít kinh nghiệm hơn, những chuyện như The Parable of The Toaster sẽ xảy ra
Càng lớn tuổi, tôi càng chống lại sự phức tạp
Nhưng lãnh đạo thường hiểu lầm rằng đó là vì “không hiểu nên phản đối”
Những dự án sống sót lâu nhất đều là những thứ đơn giản và dễ thay thế
Công cụ AI giúp cách tiếp cận này dễ hơn — thử nghiệm component bằng các sample project độc lập, rồi tích hợp phần code đã được kiểm chứng vào dự án chính
Do môi trường mạng nội bộ nên tôi không kết nối AI trực tiếp, nhưng cách này cực kỳ hữu ích
Vì vậy tôi hay đề xuất “ta vẫn có thể làm bản phức tạp, nhưng trước hết hãy bắt đầu bằng phiên bản đơn giản”
Phần lớn thời gian, phiên bản đơn giản đó cuối cùng lại trở thành code production chạy nhiều năm
Một lập trình viên đưa ra giải pháp đơn giản một cách nhanh chóng có thể tận dụng thời gian còn lại để làm thêm nhiều tính năng khác
Ngược lại, người bám vào giải pháp phức tạp sẽ dành hàng tuần chỉ cho một tính năng
Vì thế trong các chỉ số năng suất, cách tiếp cận đơn giản trông hấp dẫn hơn nhiều
Bản thân tôi cũng đã xây dựng sự nghiệp như một người đều đặn tạo ra kết quả, hơn là người có “ý tưởng lớn”
Một trong các bài phỏng vấn ở công ty chúng tôi là bài toán thiết kế hệ thống thư viện công cộng
Ban đầu bắt đầu ở quy mô một thư viện thị trấn nhỏ, rồi mở rộng thành kịch bản toàn quốc
Câu trả lời tốt nhất là: “ngay cả ở quy mô lớn nhất thì một máy chủ tầm trung cùng Postgres là đủ”
Trên thực tế thì 10 hay 10.000 cũng không khác biệt lớn lắm, và người phỏng vấn thiếu kinh nghiệm thường chỉ đọc prompt có sẵn
Sau đó, hạ tầng quá mức và phát triển vì CV mới khiến vấn đề phình to ra
Cuối cùng, tôi cho rằng AI là công cụ khuếch đại năng lực của người dùng
Với lập trình viên giỏi, nó nâng cao năng suất; còn với người chưa vững, nó trở thành công cụ lan truyền hỗn loạn với tốc độ cao
Trái lại, nó có xu hướng thêm các hàm wrapper và chuyển đổi kiểu không cần thiết
Tôi cảm giác AI nghiêng về phía “cứ thêm nhiều code hơn”
Dù vậy, việc “vibe coding” hời hợt ngày càng nhiều vẫn khiến tôi lo ngại
Những người phỏng vấn mà tôi từng gặp dường như cũng thích sự phức tạp hơn.
Tôi cũng chẳng mong sự đơn giản được đánh giá cao. Thực tế là, có khi người ta còn được thăng chức vì xử lý hậu quả của chính mớ rắc rối họ tạo ra do làm mọi thứ trở nên phức tạp.
Thiết kế quá mức không phải để phục vụ sản phẩm mà để phô trương năng lực thì nhan nhản khắp nơi.
Tôi cho rằng người đánh giá cần có mức độ hiểu biết tốt.
Và đúng là họ cũng cần nghe giải thích đầy đủ.
Nếu có người ở vị trí cao hơn đủ khả năng để đánh giá những điều đó thì mọi thứ sẽ ổn, nhưng ngay từ đầu điều đó đã không làm được, nên những kiểu năng lực này không được đánh giá một cách xứng đáng, vì thế những người như vậy cũng không thể đi lên cao hơn...
Đây chính là một vòng luẩn quẩn...
Từ góc nhìn của công ty, có vẻ như chỉ khi thành công với tư cách một kỹ sư cân bằng và đi lên các vị trí cao hơn thì mới có thể giữ vững được những nguyên tắc của kỹ sư/kỹ thuật tốt.
Phần lớn thực tế chẳng phải là kiểu chỉ biết hiện thực chức năng một cách đơn giản so với kiểu vừa có thể thiết kế với khả năng mở rộng, vừa xử lý tốt các trade-off sao?
Dù làm công việc một cách phức tạp thì cũng vẫn chỉ có thể gọi là triển khai tính năng X thôi,
khác biệt nằm ở chỗ bạn diễn đạt điều đó với người đánh giá theo cách nào.