Hãy làm điều đơn giản nhất có thể
(seangoedecke.com)- Trong thiết kế phần mềm, việc luôn chọn “điều đơn giản nhất có thể” là một lời khuyên hiệu quả
- Thiết kế hệ thống xuất sắc không trông hoành tráng, mà thực tế giải quyết vấn đề chỉ với số lượng thành phần tối thiểu
- Khi theo đuổi lời giải đơn giản, có thể lấy nguyên tắc YAGNI (You Aren't Gonna Need It) làm triết lý thiết kế cốt lõi: chỉ mở rộng dần khi phát sinh yêu cầu mới
- Dù có tranh luận về định nghĩa của “đơn giản”, thì một hệ thống có ít thành phần, liên kết nội bộ lỏng lẻo và ổn định là gần với sự đơn giản nhất
- Việc ám ảnh với khả năng mở rộng quá mức khiến codebase kém linh hoạt, vì vậy một thiết kế đơn giản bám sát yêu cầu thực tế sẽ có lợi hơn về lâu dài
Theo đuổi điều đơn giản nhất có thể
Khi thiết kế hệ thống phần mềm, điều quan trọng là làm “điều đơn giản nhất có thể”. Cách tiếp cận này có thể áp dụng trong gần như mọi tình huống như sửa lỗi, bảo trì hệ thống hiện có hay thiết kế kiến trúc mới. Nhiều kỹ sư mơ về một hệ thống “lý tưởng” — được tổ chức tốt, gần như có thể mở rộng vô hạn và có cấu trúc phân tán gọn gàng — nhưng trên thực tế, hiểu sâu hệ thống hiện tại rồi chọn lời giải dễ nhất lại hiệu quả hơn.
Sự đơn giản bị đánh giá thấp
- Thiết kế hệ thống đòi hỏi khả năng sử dụng nhiều công cụ như app server, proxy, database, cache, queue, v.v.
- Kỹ sư càng junior càng dễ muốn dùng nhiều công nghệ để tạo ra cấu trúc phức tạp, nhưng trình độ thành thạo thực sự lại nằm ở việc lược bỏ những thứ không cần thiết
- Thiết kế phần mềm xuất sắc thường trông khá nhạt nhòa, thậm chí tạo cảm giác rằng vấn đề được giải quyết dễ hơn ta tưởng
- Ví dụ, Unicorn và Rails REST API tận dụng các chức năng cơ bản của Unix để hiện thực các đảm bảo cốt lõi như cô lập, mở rộng, khôi phục bằng cấu trúc tối thiểu, nên là những thiết kế rất xuất sắc
Cách tư duy để hiện thực đơn giản
- Ví dụ, khi thêm tính năng rate limiting vào một ứng dụng Golang, có thể dùng storage bên ngoài như Redis, nhưng nếu chưa thật sự cần thì có thể thử cách đơn giản hơn trước như đếm trong bộ nhớ
- Nếu cách đơn giản là đủ, ta có thể trì hoãn việc bổ sung hạ tầng nặng nề
- Nhờ đó có thể mở rộng triển khai theo hướng tăng dần chỉ khi các yêu cầu mới thực sự xuất hiện
- Đây là cách tiếp cận đặt nguyên tắc YAGNI lên ưu tiên cao nhất trong thiết kế
Cạm bẫy của sự đơn giản và giới hạn thực tế
1. Hiện tượng Big Ball of Mud
- Nếu cứ xử lý ngay mọi yêu cầu, codebase có nguy cơ biến thành một “đống bùn(big ball of mud)” phức tạp và khó bảo trì
- Tuy nhiên, các chỉnh sửa chắp vá (hack) không phải là sự đơn giản, mà ngược lại còn tạo ra nhiều phức tạp hơn trong việc hiểu và bảo trì
- Để tìm ra lời giải thực sự đơn giản, cần so sánh nhiều phương án và thực hiện kỹ thuật phần mềm có hệ thống
2. Định nghĩa của sự đơn giản
- Không dễ để đạt được sự đồng thuận về việc “đơn giản” là gì
- Nhìn chung, một hệ thống đơn giản có ít bộ phận chuyển động (yếu tố vận hành), liên kết giữa các thành phần lỏng lẻo và giao diện rõ ràng
- Ví dụ thực tế: tiến trình Unix và Unicorn không chia sẻ bộ nhớ nên có mức độ đơn giản cao; so với Puma hay Redis thì mức độ liên kết nội bộ cũng thấp hơn
- Khi khó lựa chọn, có thể xem phương án cần ít công bảo trì hơn là phương án đơn giản hơn
3. Phê phán sự ám ảnh với khả năng mở rộng
- “Cách làm đơn giản” có thể không phù hợp với lưu lượng rất lớn
- Nhưng việc thiết kế phức tạp từ trước để chuẩn bị cho sự tăng trưởng quy mô đột ngột trong tương lai phần lớn là nỗ lực vô ích
- Phần lớn code trên thực tế chỉ cần chuẩn bị cho lưu lượng tăng khoảng 2–5 lần; vượt quá mức đó thì hợp lý hơn là xử lý khi vấn đề thực sự phát sinh
- Thiết kế quá thiên về khả năng mở rộng làm tổn hại tính linh hoạt của code, việc phân tách cấu trúc nhiều hơn mức cần thiết còn có thể khiến một số tính năng khó triển khai hơn, thậm chí đòi hỏi quản lý transaction phức tạp
Kết luận
- Càng theo thời gian, người ta càng trở nên bi quan hơn về khả năng dự đoán các yêu cầu tương lai của hệ thống
- Trong thực tế, chỉ riêng việc nắm bắt chính xác trạng thái hiện tại của hệ thống cũng đã đủ khó, và đây là trở ngại chính cản trở thiết kế tốt
- Có thể chia phát triển phần mềm thành hai cách lớn
- Thiết kế bằng cách dự đoán yêu cầu tương lai
- Lặp lại việc làm điều đơn giản nhất có thể để bám sát yêu cầu hiện tại
- Cách thứ hai thực tế hiệu quả hơn, và tư duy lấy YAGNI cùng sự đơn giản làm trung tâm sẽ tạo ra thiết kế tốt về lâu dài
Phụ lục: Thảo luận trên Hacker News và nguồn gốc thuật ngữ
- Trước ý kiến cho rằng sự đơn giản về kiến trúc sẽ mất ý nghĩa khi quy mô tăng lên, tác giả lại cho rằng quy mô càng lớn thì cấu trúc đơn giản càng quan trọng hơn (để đối phó với độ phức tạp của tương tác giữa các tính năng)
- Cụm “Do the simplest thing that could possibly work” do Ward Cunningham và Kent Beck đặt ra
1 bình luận
Ý kiến Hacker News
Tôi nghĩ cách tiếp cận này có thể hiệu quả trong những miền bài toán đơn giản. Nhưng ngay cả sau khi đã làm việc lâu năm ở các công ty công nghệ lớn, tôi vẫn luôn ngạc nhiên trước mức độ phức tạp được yêu cầu. Ngay cả những bài toán kinh doanh tưởng như đơn giản nhất cũng có thể mất hơn một năm mới giải quyết xong, hoặc thường xuyên hỏng vì vô số edge case và vấn đề về quy mô. Những người hô hào sự đơn giản có lẽ là chưa từng có kinh nghiệm ở quy mô lớn. Ngay cả khi tham khảo codebase 10 năm tuổi, vẫn có quá nhiều thứ phải cân nhắc nên việc rewrite cũng thường thất bại. Giống như ẩn dụ Chesterton's Fence, nếu không biết vì sao một thứ tồn tại thì cần có sự khôn ngoan để không xóa nó đi một cách tùy tiện
Tôi nghĩ đây là một hiểu lầm kinh điển do các kỹ sư phần mềm giao tiếp với nhau chưa tốt. Ý ở đây là hãy làm "điều đơn giản nhất có thể", đúng như tiêu đề bài viết. Với các bài toán phức tạp thì sự phức tạp là không thể tránh khỏi, nhưng ý nghĩa ở đây là hãy cẩn thận đừng vô tình làm nó phức tạp hơn mức cần thiết. Không phải là phải tránh hoàn toàn sự phức tạp, mà là phải cảnh giác với thói quen khiến mọi thứ trở nên quá rối rắm
Như đã chỉ ra, sự phức tạp có thể không đến từ bản thân miền bài toán. Nó có thể là vấn đề phát sinh từ thiết kế phần mềm không tốt. Nếu hệ thống đầy rẫy dependency và side effect, thì đó là vì việc tách biệt mối quan tâm và quản lý coupling đã không được làm tốt. Việc refactor gần như trở nên bất khả thi, và nếu văn hóa tổ chức không được cải thiện thì trong lúc refactor chỉ có thêm từng lớp vấn đề mới dính chồng lên. Dù vậy, chỉ với việc tách biệt mối quan tâm và kết hợp đơn giản cũng có thể giải quyết những bài toán phức tạp. Việc này khó, nhưng nếu các lập trình viên senior giữ vững góc nhìn này thì khả năng thành công sẽ cao hơn
Tác giả có nhắc rằng người viết là staff engineer ở GitHub, nên tôi nghĩ người này cũng có đủ kinh nghiệm với các hệ thống quy mô lớn
Hệ thống legacy tồn tại ở các vùng biên. Ngay trong các hệ thống thực, cũng giống như trong không gian đa chiều khi số chiều tăng lên thì các điểm dồn về mặt biên, người dùng thực tế cũng chủ yếu làm việc gần giới hạn của hệ thống. Hệ thống cũ đang tồn tại chính là thứ cuối cùng đã tối ưu để bao quát tất cả những vùng biên đó
Ở công ty cũ của tôi, một phần lớn sự phức tạp đến từ những nỗ lực refactor hoặc cải tiến bị thất bại, bị bỏ dở giữa chừng, hoặc không bao giờ hoàn thiện. Tôi thường tự hỏi nếu ngăn được những chuyện đó từ sớm thì liệu mình đã được thừa hưởng một hệ thống đơn giản hơn không. Không phải là không nên refactor hay cải tiến, mà tôi nghĩ phải lập kế hoạch sao cho chắc chắn bao phủ 100% use case, có ngân sách và milestone rõ ràng, rồi mới đảm bảo cải tiến dần dần theo lộ trình
Tôi rất muốn bài viết nói rõ nguồn gốc của cụm từ "điều đơn giản nhất có thể". Cụm này là một nguyên tắc mà Ward Cunningham, người phát minh ra wiki, và Kent Beck thường dùng khi làm việc cùng nhau vào cuối những năm 80. Trong lúc cả hai cùng code, họ liên tục nhắc nhau về nguyên tắc này, và sau đó nó trở thành một chủ đề quan trọng trong các bài nói chuyện và bài viết của họ. Bài này cũng nhắc tới điểm tương tự như ví dụ về cánh cửa đóng: trông có vẻ đơn giản, nhưng tùy tình huống mà cái gọi là "đơn giản" lại khác nhau. Nghĩa là, tìm ra lời giải đơn giản không phải lúc nào cũng đơn giản. Họ cũng ý thức được rằng cách làm này có thể để lại technical debt, nhưng ưu tiên khi đó là làm cho code chạy được trước. Cá nhân tôi nghĩ bài viết lần này cũng nên nói thêm về khía cạnh technical debt
Sau đó Kent Beck đã chính thức hóa Extreme Programming. Phương pháp này là một tập hợp các thực hành giúp một hệ thống đơn giản có thể tự nhiên tiến hóa khi yêu cầu thay đổi
Tôi từng nghe cụm này từ đồng nghiệp và thấy họ dùng nó như một phương châm sống, nhưng không biết Ward Cunningham là người khởi xướng. Có lẽ mức vinh dự cao nhất là khi một câu nói được dùng rộng rãi đến mức chẳng còn ai biết tác giả gốc là ai
Việc nhắc đến Wiki khá thú vị. Ở công ty cũ, chúng tôi quản lý dự án bằng Lotus Notes, và nó hữu ích vì mặc định sẽ highlight tài liệu nào đã thay đổi, thay đổi khi nào. Ở dự án sau đó, chúng tôi chỉ dùng Wiki, nhưng không thể biết ngay tài liệu nào đã thay đổi nên trên thực tế nó gần như trở nên vô dụng. Nó đơn giản thật, nhưng lại quá đơn giản đến mức giảm tính thực dụng
Trong suốt sự nghiệp của tôi, chủ đề gây tranh cãi nhiều nhất là định nghĩa của từ "hoạt động được". Câu "chạy được không có nghĩa là nó không hỏng" rất dễ được những người từng trực tiếp sửa chữa thứ gì đó cảm nhận một cách trực quan. Thợ sửa chữa khi vá víu bằng công cụ hỏng thì sớm muộn cũng sẽ quyết định thay nó đi, còn lập trình viên có vẻ không cảm nhận rõ nhu cầu "phải sửa cho đúng"
Giai đoạn khó khăn nhất trong sự nghiệp của tôi là ở một công ty có đội ngũ rất thích làm prototype. Họ nhanh chóng dựng proof of concept, demo cho lãnh đạo xem rồi lập tức đem đi triển khai. Khi đó lãnh đạo lại ngộ nhận rằng nếu làm xong nhanh như vậy thì chắc có thể triển khai ngay. Sau đó, khi đội phụ trách mở code ra xem thì thấy thiếu toàn bộ những thứ bắt buộc như bảo mật end-to-end, validation, xử lý lỗi. Cuối cùng phải làm lại từ đầu, còn lãnh đạo lại hiểu nhầm rằng đội triển khai đang cố làm mọi thứ phức tạp một cách vô ích
Tôi từng thấy một câu trích dẫn rất ấn tượng ở đâu đó: "Không đủ nếu chương trình chỉ hoạt động. Nó phải hoạt động vì những lý do đúng đắn." Về bản chất thì cũng là cùng một thông điệp
Những cuộc trao đổi như thế này là phần quan trọng trong công việc chuyên môn. Một hệ thống có thể được coi là "hoạt động" theo nghĩa nó tạo ra đầu ra mong muốn, nhưng xét về độ tin cậy hay chi phí thì vẫn có thể xem là thất bại
Với công việc tôi phụ trách, định nghĩa của "hoạt động được" phụ thuộc vào việc nhà tuyển dụng muốn đầu tư tài nguyên, tức thời gian của tôi, vào đâu. Nếu họ cho phép dành thời gian để nâng chất lượng thì tôi sẽ làm hết sức. Ngược lại, nếu họ chỉ muốn đạt chỉ tiêu hay hoàn thành checklist thì tôi sẽ làm theo hướng đó. Tôi nghĩ kết quả luôn đi theo thứ được đo lường, nên tôi có thể đưa ra lời khuyên nhưng quyền quyết định không nằm ở tôi
Điều mỉa mai của kiểu lời khuyên này là người thật sự áp dụng tốt thường lại là các chuyên gia đã rất dày dạn kinh nghiệm. Ví dụ, làm sao biết cái gì mới là "điều đơn giản nhất", và làm sao đánh giá nó có thực sự ổn hay không. Gần đây tôi gặp lỗi khi tự viết một trình nhập XLSX vì xử lý sai XML namespace, do đã giả định rằng Excel luôn dùng default namespace. Rồi sau đó bạn nhận được một file dùng namespace khác là vỡ ngay. Cứ xóa prefix rồi xử lý thì sẽ đơn giản hơn, nhưng vì tương lai của chính mình, tôi đã dành 4 tiếng để viết lại toàn bộ parser theo hướng thân thiện với namespace. Làm "điều đơn giản nhất" thực ra không hề đơn giản như thế, và đúng là càng có kinh nghiệm thì càng đánh giá tốt hơn. Nhưng đến mức kinh nghiệm đó rồi thì cũng có thể nói là chẳng còn cần lời khuyên này nữa
Tôi nghĩ ngay trong bài cũng đã nói tới lý do vì sao lời khuyên này khó áp dụng. Điểm cốt lõi là: để tìm ra lời giải đơn giản nhất, bạn phải cân nhắc nhiều cách tiếp cận khác nhau, và cuối cùng vẫn cần tư duy kỹ thuật
Ở công ty chúng tôi có nguyên tắc là "đừng thêm code theo hướng sai". Dù chỉ là triển khai một phần, vẫn phải code theo hướng dễ phát triển tiếp về sau. Đó là KISS, nhưng tuyệt đối không chấp nhận workaround
Tôi đánh giá sự đơn giản theo tiêu chí "thứ dễ chuyển giao nhất". Một service đơn lẻ không phụ thuộc vào các abstraction hay hạ tầng phức tạp cuối cùng sẽ dễ chuyển giao hơn. Người đọc có thể hiểu ngay, việc bàn giao và debug cũng nhẹ nhàng hơn. Tuy nhiên, khi cần abstraction thì tôi vẫn thêm, và khi hạ tầng thực sự cần thiết thì tôi cũng bổ sung. Điều quan trọng là luôn nghĩ xem cấu trúc này có phải là thứ dễ giải thích nhất khi bàn giao code hay không. Trước đây tôi từng cố gắng trừu tượng hóa toàn bộ, tách theo service, cấu hình hóa mọi thứ để gần như không còn code, nhưng trên thực tế việc chuyển giao và bàn giao đều thất bại hoàn toàn. Giờ tôi chỉ làm phức tạp cấu trúc khi thực sự cần, còn mặc định vẫn giữ sự đơn giản trực quan. Cuối cùng điều này có lợi cho việc onboarding người mới, sửa bug và chuyển giao thực tế
AI vibecoding cũng tương tự. Càng có nhiều kinh nghiệm và bí quyết thì càng dễ chọn đúng tác vụ và quản lý agent hiệu quả hơn
Tôi nghĩ nhiều người bỏ qua việc "điều đơn giản nhất" không có nghĩa là workaround hay vá víu tạm bợ. Cách đơn giản thường lại đòi hỏi nhiều suy nghĩ và hiểu biết hệ thống hơn, và đó cũng chính là điều phần mở đầu bài viết muốn nói. Có vẻ nhiều người chỉ đọc tiêu đề rồi trút bực bội của mình vào
Nói chung, cứ nghe thấy những nguyên tắc kiểu này hay các khẳng định mạnh mẽ như vậy là tôi có chút cảnh giác. Nếu ai đó nói về phát triển phần mềm như thể tồn tại một đáp án phổ quát thì thường là họ chưa thực sự hiểu nhiều. Kết luận của những lập trình viên thật sự nhiều kinh nghiệm là phần mềm rất khó và cần sự cẩn trọng. Không có đáp án vạn năng nào cả. Cần tư duy cởi mở và sự thấu đáo
Sự đơn giản, tức mặt đối lập với độ phức tạp, gần như là tiêu chí ưu tiên hàng đầu khi so sánh các phương án thiết kế phần mềm. Lý do là cuối cùng con người vẫn phải lên kế hoạch, đồng thuận, triển khai và bảo trì nó. Nhưng việc đánh giá cái gì là đơn giản lại quá khó, và kỹ sư ở mức trung bình trong ngành thì không đủ đáng tin để đưa ra phán đoán này. Hơn nữa, bản thân khái niệm "đơn giản" cũng bị lan truyền như một thứ khẩu hiệu rỗng, đến mức thường chỉ được dùng để phản bác một đề xuất nghiêm túc bằng câu "cái này đơn giản hơn". Lẽ ra quản lý nhóm phải nhận ra những vấn đề như thế, nhưng năng lực quản lý ngày càng thấp đến mức khó mà tin tưởng được, nên mọi chuyện càng khó hơn
Trong bài cũng có một đoạn rất ấn tượng. Bậc thầy thật sự biết "làm ít đi" chứ không phải "thêm vào", giống như cảnh người mới thì ra nhiều đòn màu mè, còn cao thủ chỉ di chuyển ít nhưng tung ra đúng một đòn quyết định
Khi đọc bài này, ban đầu tôi cũng hơi khó chịu, nhưng tôi nghĩ nhận định rằng "workaround" chỉ thêm một lớp phức tạp khác đã chạm đúng bản chất của quá trình thử-sai. Vấn đề là những nguyên tắc như vậy khi bị áp dụng quá mức như mệnh lệnh từ ban lãnh đạo thì người ta lại phản ứng quá đơn giản với các bài toán phức tạp, khiến việc truyền đạt kiến thức trở nên khó hơn và về sau chỉ còn lại những màn xử lý hậu quả còn phức tạp hơn. Ngược lại, lý do khiến mọi thứ phức tạp hơn mức cần thiết thường là vì bị đè nặng bởi các biện pháp tình thế/workaround kéo dài, rồi đến lúc muốn xử lý một lần cho xong thì lại làm quá tay theo hướng ngược lại. Cuối cùng, lập trình viên phải can thiệp tích cực vào các cuộc họp để dẫn dắt những quyết định sáng suốt ngay từ đầu
Tôi không nghĩ đây là thứ đáng xem như một đèn cảnh báo. Sự phức tạp không cần thiết tăng lên mỗi ngày, nên nhất định phải có người lên tiếng bảo vệ sự đơn giản. Designer, product manager, thậm chí cả khách hàng và kiến trúc sư cũng đều có bản năng muốn thêm phức tạp vào
Tôi cũng đồng cảm với ý của bạn, nhưng đồng thời muốn lưu ý rằng cuối cùng mọi thứ cũng sẽ quy về kiểu "mọi thứ đều là đánh đổi" hay "không có bữa trưa miễn phí". Bất kỳ nguyên lý tổng quát nào cũng là kết tinh của kinh nghiệm thực tế nên không thể loại bỏ hoàn toàn. Vấn đề là có những khái niệm thực dụng đến một lúc nào đó lại bị biến dạng thành thứ được đồn thổi quá mức hoặc gần như tôn giáo, rồi cuối cùng chỉ còn tranh cãi kiểu đặt tên thư mục
Sau khi xây vài hệ thống 0-1 ở các startup giai đoạn Seed đến Series C, tôi đã thấm một nguyên tắc: "đơn giản chính là vững chắc". Ở giai đoạn thiết kế ban đầu hay cả khi cải thiện hệ thống sẵn có, người ta rất dễ thiết kế quá mức. Yêu cầu của khách hàng liên tục thay đổi, và dù có dự đoán nhu cầu tương lai thì cuối cùng cũng vẫn dễ đoán sai. Tôi nghĩ sự đơn giản không chỉ làm giảm lỗi mà còn là nền tảng để có thể thay đổi cấu trúc một cách dễ dàng. Hãy chuẩn bị cho những khả năng X, Y, Z nếu có thể, nhưng vẫn theo đuổi hướng xây dựng "điều đơn giản nhất" để giữ không gian cho mở rộng trong tương lai. Phức tạp tất yếu làm tăng ràng buộc, và càng tích tụ theo thời gian thì stack càng yếu đi
Tôi nghĩ phải thử thiết kế "hệ thống lý tưởng" ở một mức độ nào đó thì cuối cùng mới có thể đi đến "điều đơn giản nhất". Để tạo ra một hệ thống dễ đọc, dễ thay đổi cũng cần rất nhiều bí quyết. Những cải tiến thật sự "đơn giản" cũng xuất phát từ kinh nghiệm và sự thấu hiểu sâu sắc
Điều này cùng ngữ cảnh với Gall's law. Theo lý thuyết đó, một hệ thống phức tạp vận hành tốt luôn bắt đầu từ một hệ thống đơn giản rồi dần dần được thêm phức tạp vào. Một hệ thống được làm phức tạp ngay từ đầu thì thường không thành công. Vì vậy, trước tiên cần làm hệ thống đơn giản nhất rồi dần bổ sung độ phức tạp theo yêu cầu
Tôi đồng ý với tinh thần của bài viết, nhưng nghĩ rằng sự xuất hiện của hạ tầng cloud đã làm thay đổi định nghĩa của "đơn giản". Trước đây thường là thế đối lập giữa "đơn giản nhưng không mở rộng được" và "phức tạp nhưng mở rộng tốt", nhưng bây giờ không còn như vậy nữa. Một giải pháp rate-limiting trong bộ nhớ có thể đơn giản trên một server đơn, nhưng chỉ cần hai server là lập tức thành vấn đề trạng thái phân tán. Trong khi đó, các managed service như DynamoDB hay ElastiCache lại trở thành một nguồn chân lý duy nhất bất kể là một node hay 1000 node, từ đó giảm mạnh độ phức tạp. Nếu nhìn từ góc độ "hệ thống đơn giản thì vững chắc", thì dùng managed service mới là đơn giản ở tầng gốc hơn. Vì nó loại bỏ những vấn đề lặp đi lặp lại như mất dữ liệu hay quản lý trạng thái phân tán. Giờ đây định nghĩa của "điều đơn giản nhất" dường như đã chuyển thành việc tận dụng tốt các managed service mà không phải tự vận hành. Ngày nay, thay vì tránh phụ thuộc bên ngoài, việc tận dụng hiệu quả các hệ thống đã được kiểm chứng và cô lập hóa lại thường giúp tiết kiệm thời gian và chi phí bằng cách giảm độ phức tạp
Tôi đồng ý với câu nói nổi tiếng: "Hãy làm mọi thứ đơn giản nhất có thể, nhưng đừng đơn giản hơn mức đó." Tôi luôn cố làm theo nguyên tắc này, nhưng vẫn thường băn khoăn liệu mình có đang bỏ lỡ những cách loại bỏ phức tạp không cần thiết vì chưa theo kịp công nghệ mới, hay ngược lại là mọi người đang tự lao vào độ phức tạp không cần thiết. Nếu không trực tiếp dùng trong dự án thực tế thì cũng khó biết nó có thực sự hữu ích hay không, nhưng ngược lại tôi cũng đã thấy việc cố ép công cụ mới vào môi trường thực chỉ để phục vụ việc tự học gây hại cho cả đội
Tôi đang trải qua một cơn ác mộng tương tự. Vì cấp trên lúc nào cũng hứng thú với phần mềm mới nhất, tôi phải liên tục đánh giá những công cụ chưa biết có ý nghĩa gì trong thực tế hay không. Tuần nào cũng bị yêu cầu làm việc khám phá như vậy bất kể có liên quan đến kết quả công việc hay không nên khá áp lực
Trên thực tế, tôi nghĩ nên làm cho nó hoạt động bằng cách đơn giản nhất trước đã, kể cả phải làm thủ công nếu cần, rồi chỉ đến lúc thực sự cần mới bổ sung toàn bộ tính năng. Kể cả nếu ban đầu bạn đã tốn thời gian vô ích để tự động hóa hay công cụ hóa mọi thứ, thì trải nghiệm hiểu rõ sau này vì sao điều đó cần thiết vẫn quan trọng hơn
Cảm giác này rất quen thuộc. Tôi cũng luôn đồng cảm với những bài viết như thế này và cố gắng thực hành sự đơn giản, nhưng lúc nào cũng phân vân liệu đó có thực sự là sự khôn ngoan và tính thực dụng, hay chỉ đơn giản là mình còn thiếu kinh nghiệm và năng lực
Chính vì thế tôi luôn cố cẩn thận để không rơi vào kiểu "phát triển vì CV"