Cách riêng của tôi để phát triển phần mềm nhanh
(evanhahn.com)- Cân bằng giữa sự hoàn hảo và tốc độ không hề dễ, nhưng mức chất lượng phù hợp và đúng hạn mới là điều quan trọng tùy theo bối cảnh
- Cách làm hiệu quả là phát triển bản nháp ban đầu trước, rồi sau đó mới cải thiện chất lượng mã
- Nới lỏng yêu cầu hoặc giảm bớt những đòi hỏi quá mức có thể giúp tăng tốc độ và hiệu quả
- Cần có thói quen tránh xao nhãng, commit thường xuyên với thay đổi nhỏ, và tập trung vào điều cốt lõi
- Có những kỹ năng cụ thể thực sự giúp phát triển nhanh hơn như đọc mã, mô hình hóa dữ liệu, viết script, gỡ lỗi, thiên về hàm thuần
“Mã cần tốt đến mức nào?” – Tiêu chuẩn chất lượng và lựa chọn thực tế
- Thời kỳ đầu, tôi muốn mọi đoạn mã đều hoàn hảo
- Tôi từng mơ về mã không có bất kỳ lỗi nào, nơi mọi hàm đều được kiểm thử kỹ lưỡng, tên biến thanh nhã, trừu tượng rõ ràng
- Nhưng theo thời gian, tôi học được thực tế rằng “không có đáp án đúng duy nhất”
- Chất lượng mã cần có sẽ khác nhau tùy tình huống
- Game jam 24 giờ: mã hoàn thành không nhất thiết phải sạch đẹp hay không có lỗi
- Điều quan trọng hơn là tạo ra thứ gì đó chạy được trong thời gian giới hạn
- Phần mềm cho máy tạo nhịp tim: chỉ một sai sót nhỏ cũng có thể đe dọa tính mạng con người, nên
- Độ tin cậy và an toàn ở mức cao nhất là bắt buộc
- Phần lớn dự án nằm ở giữa hai thái cực này
- Có công ty yêu cầu giao hàng thật nhanh nên chấp nhận một ít lỗi
- Có dự án đòi hỏi chất lượng cao nhưng lịch trình lại dư dả
- Trong công việc thực tế, khả năng nhìn ra điểm cân bằng này là rất quan trọng
- Trước hết cần hiểu tiêu chuẩn “đủ tốt (good enough)” của cả nhóm là gì
- Cùng xác định các tiêu chí thực tế như phạm vi lỗi có thể chấp nhận, hay phần nào không cần hoàn hảo
- Tiêu chuẩn cá nhân của tôi là
- “Đạt chất lượng 8/10 trong thời hạn”
- Mã phải hoàn thành đúng mục đích, không có vấn đề nghiêm trọng, nhưng có thể vẫn còn vài lỗi nhỏ
- Điều quan trọng nhất là giao được đúng hạn
- Tuy vậy, tiêu chuẩn này cũng được điều chỉnh linh hoạt theo bối cảnh dự án
- Có lúc theo đuổi sự hoàn hảo và chấp nhận trễ tiến độ là hợp lý,
- cũng có lúc chất lượng chưa cao nhưng hoàn thành thật nhanh trước lại có giá trị hơn
- “Đạt chất lượng 8/10 trong thời hạn”
Rough drafts – Cách tận dụng thực tế và lợi ích của bản nháp, nguyên mẫu
- Phát triển phần mềm cũng như viết lách, việc làm bản nháp (rough draft, spike, walking skeleton) rất hữu ích
- Tôi cố gắng triển khai bản nháp nhanh nhất có thể, rồi sau đó tinh chỉnh nó thành giải pháp hoàn chỉnh
- Mã bản nháp của tôi thường đầy lỗi, test fail, TODO rải khắp nơi, ngoại lệ chưa xử lý, lạm dụng print/log,
không quan tâm hiệu năng, commit với thông điệp WIP, thêm package không cần thiết, mã lặp, hardcode, cảnh báo từ linter — nói chung là rất lộn xộn - Cách làm này có vẻ kém hiệu quả, nhưng mục tiêu là đạt đến trạng thái “ít nhất đã hiểu được bản chất của vấn đề”
- Dĩ nhiên, tôi không bao giờ đưa mã ở trạng thái bản nháp như vậy lên production, mà luôn dọn dẹp nó trước khi phát hành thực tế
(đôi khi trong nhóm có áp lực muốn ship nguyên bản nháp, nhưng tôi cố chống lại điều đó nhiều nhất có thể) -
Những lợi ích chính của cách tiếp cận bản nháp
- Làm lộ ra sớm các “điều chưa biết mà mình cũng không biết” (unknown unknowns)
- Tìm ra chướng ngại chưa lường trước ở giai đoạn prototype sớm sẽ có lợi hơn nhiều so với đợi đến lúc hoàn thành rồi mới vứt bỏ mã
- Nhiều vấn đề tự nhiên biến mất ngay trong lúc làm prototype
- Một hàm chậm hay cấu trúc sai có khi về sau lại không còn cần thiết nữa, nhờ vậy tránh lãng phí thời gian
- Không cần dồn quá nhiều công sức vào tối ưu hóa hay kiểm thử quá sớm
- Giúp tăng khả năng tập trung
- Nó ngăn bạn bị kéo sang refactor không cần thiết, suy nghĩ quá lâu về naming, hay sửa những phần khác của codebase,
để bạn chỉ tập trung vào vấn đề đang cần giải quyết
- Nó ngăn bạn bị kéo sang refactor không cần thiết, suy nghĩ quá lâu về naming, hay sửa những phần khác của codebase,
- Ngăn trừu tượng hóa quá sớm một cách không cần thiết
- Khi ưu tiên tạo ra lời giải chạy được thật nhanh, ta sẽ bớt cố dựng những lớp trừu tượng cho tương lai mà chưa chắc cần
- Chỉ tập trung vào vấn đề trước mắt để tránh thiết kế phức tạp không cần thiết
- Trao đổi tiến độ rõ ràng hơn
- Bản nháp giúp dự đoán chính xác hơn còn bao nhiêu việc ở phía trước
- Bạn có thể sớm cho mọi người thấy thứ gì đó đang chạy, từ đó nhận phản hồi và đổi hướng nhanh hơn
- Làm lộ ra sớm các “điều chưa biết mà mình cũng không biết” (unknown unknowns)
-
Cách vận hành bản nháp trong thực tế
- Những quyết định khó đảo ngược (binding decision) phải được thử nghiệm ngay ở giai đoạn nháp
- Ví dụ: ngôn ngữ, framework, schema DB và các định hướng lớn nên được kiểm tra từ sớm
- Mọi giải pháp tạm thời/hack đều phải được ghi lại bằng TODO hoặc cách tương tự
- Ở giai đoạn polish, có thể dùng
git grep TODOđể rà soát toàn bộ và xử lý bổ sung
- Ở giai đoạn polish, có thể dùng
- Phát triển theo thứ tự Top-Down (từ trên xuống dưới)
- Viết scaffold từ cách sử dụng như UI, API trước; logic bên trong có thể hardcode hoặc làm tạm thời
- Trên thực tế, khi UI/trải nghiệm sử dụng được chốt thì logic phía dưới thường thay đổi theo, nên bắt đầu từ lớp trên sẽ có lợi hơn
- Làm ngược lại, tức hoàn thiện lớp dưới thật kỹ rồi mới ép lớp trên theo, thường kém hiệu quả
- Tách riêng các thay đổi nhỏ thành patch riêng
- Nếu trong lúc làm bản nháp mà phát hiện cần cải thiện codebase hoặc cập nhật dependency,
hãy tách riêng phần đó thành PR/commit độc lập để đưa vào nhanh hơn - Việc này giúp giảm độ phức tạp của toàn bộ thay đổi và tăng tốc review/tích hợp
> Tham khảo: “Hãy vứt bỏ bản nháp đầu tiên của mã”, “Hệ thống đơn giản nhất cho hiện tại là tốt nhất”, “YAGNI(You Aren’t Gonna Need It)”
- Nếu trong lúc làm bản nháp mà phát hiện cần cải thiện codebase hoặc cập nhật dependency,
- Những quyết định khó đảo ngược (binding decision) phải được thử nghiệm ngay ở giai đoạn nháp
Thử thay đổi yêu cầu
- Tác giả nhấn mạnh nguyên tắc làm ít hơn thì sẽ nhanh và dễ hơn
- Trong công việc thực tế, tôi luôn nghĩ xem có thể nới lỏng yêu cầu của nhiệm vụ đã nhận hay không
- Ví dụ các câu hỏi nên đặt ra:
- Có thể gộp nhiều màn hình thành một không?
- Có thực sự cần xử lý hết mọi edge case khó nhằn không?
- Nếu yêu cầu hỗ trợ 1000 đầu vào, liệu chỉ hỗ trợ 10 có được không?
- Có thể thay bản hoàn chỉnh bằng prototype không?
- Có thể bỏ hẳn tính năng này đi không?
- Ví dụ các câu hỏi nên đặt ra:
- Cách tiếp cận như vậy giúp tăng tốc độ và hiệu quả phát triển
- Tôi cũng cố gắng định hướng văn hóa tổ chức theo nhịp độ chậm hơn một chút nhưng hợp lý hơn
- Những thay đổi đột ngột và quá lớn thường không hiệu quả
- Thay vào đó là từng bước đề xuất, thay đổi cách thảo luận để dần dần đổi không khí làm việc
Tránh xao nhãng (Distraction) trong lúc viết mã
- Không chỉ môi trường bên ngoài như thông báo hay cuộc họp, mà cả việc lạc sang những chuyện không liên quan trong lúc làm code cũng là trở ngại lớn
- Tôi cũng thường đang sửa bug thì lại bắt đầu đụng đến những chỗ chẳng liên quan, và kết quả là nhiệm vụ ban đầu bị trì hoãn
- Hai cách thực hành cụ thể:
- Đặt hẹn giờ: đặt giới hạn thời gian cho từng việc, và khi chuông reo thì kiểm tra lại mình đang tiến đến đâu
- Nó giúp cảnh tỉnh khi một việc mất nhiều thời gian hơn dự kiến
- Nếu kết hợp báo thức với một lần git commit, bạn còn có cảm giác đạt được thành quả nhỏ
- (cách này cũng hữu ích để luyện ước lượng thời gian)
- Lập trình cặp: làm cùng người khác giúp giảm việc đi chệch hướng vô ích và giữ tập trung tốt hơn
- Đặt hẹn giờ: đặt giới hạn thời gian cho từng việc, và khi chuông reo thì kiểm tra lại mình đang tiến đến đâu
- Với một số lập trình viên, việc tránh xao nhãng có thể là tự nhiên, nhưng với tôi nó đòi hỏi sự tập trung có chủ đích và hình thành thành thói quen
Thay đổi nhỏ, chia nhỏ công việc
- Trước đây tôi từng có sếp khuyến khích những patch lớn và thay đổi diện rộng, nhưng
trải nghiệm thực tế cho thấy điều đó rất kém hiệu quả - Tôi cảm thấy diff nhỏ, tập trung gần như luôn tốt hơn
- Gánh nặng khi viết mã thấp hơn
- Review code dễ và nhanh hơn, giảm mệt mỏi cho đồng nghiệp, đồng thời lỗi của tôi cũng dễ bị phát hiện hơn
- Khi có sự cố, rollback cũng dễ và an toàn hơn
- Phạm vi thay đổi mỗi lần nhỏ nên nguy cơ phát sinh bug mới cũng giảm
- Ngay cả tính năng lớn hay bổ sung chức năng cũng được hoàn thành bằng cách tích lũy nhiều thay đổi nhỏ
- Ví dụ: nếu cần thêm một màn hình, hãy tách riêng sửa bug/nâng cấp dependency/thêm tính năng thành các patch độc lập
- Tác giả nhấn mạnh rằng thay đổi ở đơn vị nhỏ giúp phát triển phần mềm vừa nhanh hơn vừa chất lượng hơn
Những kỹ năng cụ thể thực sự giúp phát triển nhanh hơn
Những điều nói ở trên có phần trừu tượng, nhưng cũng có các kỹ năng thực chiến thực sự hiệu quả cho việc phát triển nhanh
-
Đọc mã (Reading code): đây là năng lực quan trọng nhất của lập trình viên mà tôi đã học được cho đến nay
- Nếu có thể đọc và hiểu tốt mã hiện có, việc debug sẽ dễ hơn rất nhiều
- Bạn cũng bớt sợ bug hoặc tài liệu thiếu sót trong các thư viện mã nguồn mở/thư viện bên thứ ba
- Lượng kiến thức học được từ việc đọc code của người khác là khổng lồ, và nó trực tiếp nâng cao khả năng giải quyết vấn đề nói chung
-
Mô hình hóa dữ liệu (Data modeling): dù tốn thời gian, thiết kế mô hình dữ liệu đúng cách là rất quan trọng
- Schema cơ sở dữ liệu thiết kế sai sẽ dẫn đến nhiều vấn đề và chi phí chỉnh sửa phức tạp về sau
- Thiết kế sao cho trạng thái không hợp lệ không thể được biểu diễn ngay từ đầu sẽ giúp giảm bug tận gốc
- Càng phải thận trọng hơn khi dữ liệu được lưu trữ hoặc trao đổi với bên ngoài
-
Viết script (Scripting): khả năng nhanh chóng viết script ngắn bằng Bash, Python... giúp tối đa hóa hiệu suất phát triển
- Tôi dùng việc này nhiều lần mỗi tuần cho các tác vụ tự động hóa như sắp xếp Markdown, dọn dữ liệu, tìm file trùng lặp
- Với Bash, có thể dùng công cụ như Shellcheck để phòng lỗi cú pháp từ sớm
- Với những việc không cần quá robust, có thể tận dụng LLM để hoàn thành nhanh hơn
-
Dùng debugger: sử dụng debugger là thiết yếu để chẩn đoán vấn đề nhanh và hiểu luồng chạy của mã theo cách mà chỉ print/log không làm được
- Việc tìm nguyên nhân gốc rễ của bug phức tạp trở nên nhanh hơn rất nhiều
-
Biết nghỉ đúng lúc: khi bị kẹt, hãy mạnh dạn nghỉ ngơi
- Có rất nhiều lần một vấn đề không giải được sau nhiều giờ vật lộn, nhưng chỉ nghỉ 5 phút rồi quay lại là xử lý được ngay
- Điều này cũng quan trọng để duy trì hiệu suất tập trung
-
Ưu tiên hàm thuần và dữ liệu bất biến: lập trình hàm — nếu ưu tiên hàm thuần và immutable data thì
- Sẽ giảm bug, giảm gánh nặng theo dõi trạng thái, tăng độ rõ ràng và khả năng dự đoán của mã
- Nhiều trường hợp nó đơn giản và hiệu quả hơn việc thiết kế hệ phân cấp class phức tạp
- Không phải lúc nào cũng làm được, nhưng đây là hướng tôi mặc định cân nhắc trước
-
Tận dụng LLM (mô hình ngôn ngữ lớn): LLM (ví dụ: ChatGPT...) tuy có nhược điểm, nhưng mang lại lợi ích tăng tốc rất lớn trong các công việc phát triển lặp lại hoặc có thể tự động hóa
- Tôi chủ động sử dụng sau khi hiểu đủ rõ cách gắn LLM vào code của mình và biết giới hạn của nó
- Tôi cũng tham khảo nhiều kinh nghiệm, mẹo và ví dụ đa dạng từ cộng đồng
Tất cả những kỹ năng này đều được tôi rèn luyện lặp đi lặp lại trong thời gian dài, và thực sự đã trở thành tài sản lớn giúp tôi phát triển nhanh hơn
Tóm tắt
- Những bài học cốt lõi tôi rút ra khi phát triển phần mềm nhanh là:
- Xác định rõ tiêu chuẩn chất lượng mã cần có cho từng nhiệm vụ
- Viết nhanh bản nháp (rough draft) để nắm toàn bộ khung sườn
- Luôn tìm cơ hội nới lỏng yêu cầu
- Không để bị xao nhãng và giữ sự tập trung
- Thay đổi nhỏ và commit thường xuyên, tránh các patch lớn
- Liên tục rèn luyện các kỹ năng thực chiến cụ thể (đọc mã, mô hình hóa dữ liệu, debug, scripting...)
- Mọi điều này nghe có vẻ hiển nhiên, nhưng để thực sự rút ra được các bài học đó thì tôi đã mất rất nhiều thời gian
2 bình luận
Có nhiều ý rất đáng đồng cảm.
Các bình luận cũng hay, nhưng khi có ai đó sắp xếp và nói lại như thế này, tức là tạo sẵn một khuôn khổ cho cuộc thảo luận, thì mình thấy qua phản biện, ủng hộ và bổ sung, nội dung sẽ trở nên hoàn thiện hơn.
P.S. Gần đây mình hay thấy cách diễn đạt "công nghệ nhàm chán", hóa ra trong tiếng Anh là boring technology.
Ý kiến trên Hacker News
Trong vài năm gần đây, tôi đã học được cách xây dựng các hệ thống nhanh mà vẫn đủ vững chắc
Tôi nhận ra việc hiểu thật sâu một công cụ là rất quan trọng. Một công cụ tôi dùng thành thạo hiệu quả hơn nhiều so với công cụ nhìn bề ngoài có vẻ phù hợp hơn. Trên thực tế, với đa số dự án thì Django là lựa chọn vừa khít
Thỉnh thoảng tôi bắt đầu dự án với nỗi lo Django có thể quá nặng, nhưng rốt cuộc dự án lại phát triển vượt xa ý định ban đầu. Ví dụ, tôi từng làm một ứng dụng trang trạng thái và nhanh chóng nhận ra việc cố né giới hạn của Django là không hiệu quả
Với hầu hết ứng dụng phù hợp với mô hình của Django, mô hình dữ liệu là cốt lõi. Dù chỉ là prototype, nếu trì hoãn việc refactor mô hình dữ liệu thì chi phí và độ khó về sau sẽ tăng theo cấp số nhân
Phần lớn ứng dụng không cần single-page app hay framework frontend nặng. Một số phần có thể cần, nhưng 80% trang chỉ cần các view Django truyền thống là đủ. Phần còn lại có thể cân nhắc AlpineJS hoặc HTMX
Trong đa số trường hợp, tự phát triển còn dễ hơn. Có thể nhanh chóng làm CRM, trang trạng thái, hệ thống hỗ trợ, quy trình bán hàng và nhiều thứ khác bằng Django. Nhanh hơn rất nhiều so với tích hợp CRM thương mại
Hãy chọn công nghệ bình thường đến mức nhàm chán. Bộ Python/Django/Postgres là đủ giải quyết đa số vấn đề. Có thể quên Kubernetes, Redis, RabbitMQ, Celery đi. Alpine/HTMX là ngoại lệ, vì chúng giúp tránh được phần lớn stack JS
Với tôi, Redis và Kubernetes lại chính là “công nghệ nhàm chán” của năm 2025. Cả hai đều cực kỳ ổn định, mục đích sử dụng rõ ràng, nhược điểm cũng đã được biết rõ nên rất đáng tin. Cá nhân tôi là fan của cả hai. Chúng làm đúng những gì tôi cần nên tôi rất tin tưởng
Tôi cũng thực sự rất thích Django. Có thể khởi động và deploy dự án cực kỳ nhanh
Nếu thực sự chọn “công nghệ nhàm chán”, thì ngay cả Postgres cũng nên nghĩ lại một lần
Tôi dùng Celery khá thường xuyên trong các dự án Django. Tôi không thích độ phức tạp của nó, nhưng trong môi trường PaaS thì lại là lựa chọn ít đau khổ nhất
Có vẻ như nhận định “đa số ứng dụng không cần SPA hay framework frontend nặng” mâu thuẫn với lời khuyên “hãy đào sâu một công cụ”
Khi để lại code ở dạng bản nháp thô, quản lý thường sẽ cứ thế đẩy nó thành “bản cuối”
Vì vậy tôi viết code robust ngay từ đầu. Ngay cả test harness tôi cũng làm gần như chắc chắn ở mức sẵn sàng deploy
Điều cốt lõi là tạo ra các module thật chất lượng. Những phần gần như không đổi hoặc nếu đổi sẽ gây vấn đề rất lớn thì nên tách hẳn thành module độc lập rồi import như dependency
Nhờ những module như vậy mà có thể phát triển ứng dụng mới rất nhanh và vẫn duy trì chất lượng cao
Một số ví dụ tôi từng dùng là RVS_Checkbox, ambiamara, RVS_Generic_Swift_Toolbox v.v.
Tôi có một câu hỏi: trong Swift, việc dùng mẫu comment marker như "* ##################################################################" có phải là tiêu chuẩn không
Cách tiếp cận thay đổi rất nhiều tùy theo quy mô dự án
Nếu là dự án cá nhân hoặc nhóm nhỏ, phát triển “nhanh và thô” là tối ưu. Đó là thế mạnh của phát triển quy mô nhỏ
Ở quy mô nhỏ, có bug thì cũng sửa rất nhanh, và mọi thành viên gần như hiểu toàn bộ code một cách trọn vẹn
Khi quy mô lớn hơn, chi phí của sai lầm kiến trúc hoặc sửa bug tăng vọt. Kiến trúc tất yếu trở nên phức tạp, còn refactor quy mô lớn thì gần như bất khả thi. Trong môi trường như vậy, độ chính xác ở từng bước phải được ưu tiên hàng đầu
Ngữ cảnh thực sự rất quan trọng. “Quy mô lớn” có thể mang ý nghĩa khác nhau, nhưng theo trải nghiệm của tôi thì việc sớm thống nhất API giữa các ứng dụng để cả frontend lẫn backend đều nhanh chóng có môi trường làm việc luôn là điều đúng đắn
Trong tình huống như vậy, nên vận hành hệ thống ở quy mô nhỏ hơn. Ai cũng muốn một hệ thống khổng lồ, nhưng thực tế thì chẳng cần đến mức đó
Có người nói “trong game jam 24 giờ thì không cần quan tâm chất lượng code”, nhưng theo phần lớn trải nghiệm hackathon/code review của tôi, những đội đạt kết quả tốt nhất cũng chăm chút chất lượng code và cả môi trường test sơ khai
Hai nhận định trên (muốn nhanh thì phải hy sinh chất lượng code vs đội đạt thành tích tốt thường có chất lượng cao hơn) thực ra không mâu thuẫn. Đội làm tốt chưa chắc đã chỉ chăm chăm vào việc làm code thật gọn gàng
Trong ví dụ game jam, nếu quá ám ảnh chuyện code sạch thì ngược lại có thể khiến kết quả cuối cùng kém đi. Những hệ thống như UE blueprint cho thấy vì sao đôi khi phải ưu tiên kết quả hơn là “độ sạch”
Có người đánh giá “độ sạch” của code một cách tổng thể, còn người khác thì đánh giá chi phí/lợi ích chi tiết của những cải tiến code không cần thiết
Trái với ý “khi prototype sẽ lộ ra những ‘unknown unknowns’ không lường trước”, mỗi khi tôi thử đụng vào cái gì mới thì lúc đầu tôi luôn chỉ thấy ưu điểm chứ khó thấy nhược điểm
Trên thực tế, chỉ đến giai đoạn hoàn thiện tính năng thực sự như xử lý edge case, thông báo lỗi thân thiện cho người dùng hay loại bỏ tác dụng phụ thì vấn đề thật sự (unknown unknowns) mới lộ ra
Có lẽ những unknown unknowns tôi gặp phát sinh từ chính công cụ/framework/thư viện, còn tác giả đang nói đến unknown unknowns trong chính miền bài toán
Tôi cũng đồng ý rằng rough draft không được quá thô. Nếu làm qua loa ở những phần không nên qua loa, vấn đề thật sự sẽ nổ ra.
Khi làm công cụ để tự dùng thì có thể làm sơ sài mà vẫn dùng ổn, và những công cụ được làm nhanh như vậy dù đầy lỗ hổng cũng chưa chắc gây ra vấn đề gì
Trong ngành công nghệ hiện nay, nơi tái cơ cấu diễn ra thường xuyên, đó mới là mối đe dọa lớn nhất đối với chất lượng phần mềm và năng suất kỹ sư
Nỗi lo bị sa thải và áp lực phải ra kết quả nhanh giết chết sự sáng tạo, tinh thần thử nghiệm và gây burnout
Mọi người bị cuốn theo tâm lý đám đông với các chủ đề hot như AI, đến mức không còn môi trường để phê phán nữa
Đây còn cấp bách hơn cả tự động lập trình bằng LLM
Từ trước tới nay, mối đe dọa lớn nhất với chất lượng phần mềm luôn là việc người tiêu dùng không chịu trả tiền cho chất lượng
Vendor lock-in ở cấp độ lập trình trên thực tế còn mang tính hủy diệt hơn SaaS lock-in rất nhiều
Trong các chu kỳ nhanh như game jam 24 giờ, tôi lại thấy code tệ là thứ chí mạng
Code càng gọn gàng thì càng ít sai sót, giảm gánh nặng bộ nhớ làm việc, và giúp việc thay đổi, thêm tính năng hay sửa lỗi vào phút chót dễ hơn rất nhiều
Điều phá hỏng dự án 24 giờ nhiều nhất không phải là viết code chậm, mà là tự dồn mình vào góc hoặc đụng phải các vấn đề khó lường rồi trật bánh
Dĩ nhiên không có nghĩa là phải bắt hết mọi bug. Nhưng nếu chất lượng nền tảng thấp thì toàn bộ trải nghiệm dự án sẽ rất vất vả
Nguyên tắc này cũng áp dụng cho các dự án có nhiều thời gian hơn. Có thêm thời gian không có nghĩa là viết cẩu thả sẽ tốt hơn
Nếu biến việc viết code tốt thành thói quen, có thể đảm bảo chất lượng mà không phát sinh thêm chi phí. Và kể cả có tốn thêm thời gian thì cuối cùng đó vẫn là việc đáng làm
Tôi cũng nghĩ vậy. Tôi đã tham gia nhiều game jam, nhưng “code cẩu thả” chỉ được chấp nhận trong 1-2 giờ cuối trước deadline, và chỉ ở những file mà người khác sẽ không đụng vào
Muốn viết code vừa nhanh vừa tốt thì cuối cùng chỉ có cách là viết thật nhiều
Khi gấp, tôi không bận tâm đến những thứ như fancy asset loader mà cứ dùng file tĩnh luôn
Tôi cho rằng nhận thức “viết code tốt thì mất nhiều thời gian hơn” là một hiểu lầm. Nếu phải đạt một mức yêu cầu tối thiểu nào đó, code tốt không phải là vật cản đối với tốc độ
Tiêu chuẩn “đủ tốt” là mức nào khác nhau giữa các nhóm, và đó là nguồn gốc xung đột lớn nhất trong sự nghiệp của tôi
Người từng ở big tech thì khó chịu vì thiếu test, còn người từng ở startup lại khó chịu vì tốc độ chậm
Sẽ hữu ích nếu ghi lại rõ ràng tiêu chuẩn “đủ tốt” thành tài liệu và chia sẻ trong nhóm
Đó chính là team charter, tức tài liệu “cách chúng ta làm việc”
Một yếu tố quan trọng mà bài viết chưa nhắc tới là tốc độ phát triển sẽ chậm dần theo thời gian
Khi dự án và quy mô nhóm tăng lên, tốc độ phát triển tự nhiên sẽ chậm lại
Nói cách khác, dù có phải hy sinh đôi chút tốc độ phát triển tức thời, vẫn cần chuẩn bị sớm các thứ như test, tài liệu, decision log, họp Agile... để tốc độ phát triển dài hạn giảm ít hơn
Nếu không chuẩn bị trước các thứ như observability hay cấu trúc code dễ kiểm thử, về sau tác động xấu sẽ rất lớn
Tôi là solo developer nhưng cũng cảm nhận rõ tầm quan trọng của decision log, test và tài liệu
Đây cũng là một kiểu mẫu quen thuộc với tôi. Tôi bắt đầu bằng rough draft, hoặc một đoạn code nhỏ để kiểm chứng ý tưởng, thường là ghép nhiều ngôn ngữ script khác nhau hay các bước chạy thủ công lại