80 điểm bởi GN⁺ 2025-07-15 | 2 bình luận | Chia sẻ qua WhatsApp
  • Cân bằng giữa sự hoàn hảotốc độ không hề dễ, nhưng mức chất lượng phù hợpđú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

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
    • 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
  • 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
    • 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

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?
  • 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
  • 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

 
nicewook 2025-07-15

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.

 
GN⁺ 2025-07-15
Ý 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

      • Ở công ty tôi dùng Go, nhưng để làm cùng một API endpoint thì lượng code dài gấp 10 lần. Mỗi khi thêm query parameter, phân trang hay các tính năng khác thì code lại dài ra. Thêm mô hình phân quyền nữa thì còn tệ hơn
      • Dĩ nhiên chênh lệch hiệu năng là có thật, nhưng thực tế phần lớn hiệu năng lại do truy vấn DB quyết định. Python cũng đã đủ 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

      • Sqlite có quy mô lớn hơn nhiều so với điều nhiều người nghĩ. Điều này đặc biệt đúng trong môi trường phát triển cục bộ hoặc CI instance cô lập, và với ứng dụng nhỏ thì ngay cả production cũng dùng đủ tốt
    • 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

      • Lần nào tôi cũng bắt đầu với ý định thử làm mà không có Celery, nhưng cuối cùng các tác vụ được kích hoạt qua HTTP lại đụng timeout nên vẫn phải dùng Celery. Đến bước đó thì chỉ còn chọn giữa thread, cron job (đặc biệt khó trong PaaS) hoặc Celery. Tôi tò mò người khác xử lý chuyện này thế nào
    • 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ụ”

      • Tôi làm mọi trang bằng React. Không phải vì nhất thiết cần SPA, mà vì cuối cùng kiểu gì cũng sẽ có lúc cần quản lý state phía client, nên tôi thấy cứ làm mọi thứ bằng React ngay từ đầu sẽ tiện hơn. Ban đầu có thể thấy nặng, nhưng rốt cuộc lại hiệu quả hơn
  • 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

      • Trong source code nó rất nổi bật về mặt thị giác
  • 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

      • Deploy lên server production càng sớm càng tốt để bộc lộ các vấn đề kiểm thử và vấn đề giữa các nhóm là cách hiệu quả
      • Có vẻ tác giả đang tập trung vào góc nhìn code, nhưng tôi nghĩ ở các nhóm lớn điều này còn quan trọng hơn nữa
      • Dù vậy, tôi không thích kiến trúc có phụ thuộc phân tầng giữa các nhóm, nhưng ngoài thực tế thì điều này lại khá phổ biế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

      • Theo tôi, cách thứ hai cho kết quả tốt hơn nhiều trong mọi hoàn cảnh. Dù là ở hackathon hay code sản phẩm đòi hỏi độ ổn định cao cũng vậy
  • 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.

      • Ví dụ, nếu tay đua rally nghiên cứu đường đua một cách hời hợt từ trước, họ có thể gặp những nguy hiểm không ngờ tới như gờ giảm tốc ngay trước khúc cua
    • 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

      • Dù có một nhóm người dùng có thể “cảm nhận” chất lượng, chừng đó vẫn chưa đủ để một sản phẩm mới thành công chỉ nhờ chất lượng
      • Ở các lĩnh vực ngoài phần mềm như ô tô hay đồ gia dụng, giá cả khác nhau theo chất lượng, còn phần mềm thì không như vậy
    • 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

      • Thị trường phần cứng vốn đã bị một số ít bên độc chiếm, và rồi sẽ đến ngày phần mềm cũng bị chính những công ty đó độc chiếm
      • Kết cục là thay vì lập trình viên máy tính, chỉ còn lại những người viết prompt cho LLM
  • 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

      • Việc dọn dẹp code như gom logic dùng chung thực ra không tốn lâu như người ta nghĩ
      • Một cách thực tế, bug phát sinh từ code vụng về nguy hiểm hơn và tốn kém hơn rất nhiều so với thời gian tiết kiệm được nhờ không dọn code
      • Tuy nhiên, với các tính năng na ná nhau nhưng khác biệt, ví dụ fade out ánh sáng và fade out màu sắc, tôi lại để code lặp lại. Vì yêu cầu của chúng rất dễ tách nhánh về sau
    • 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

      • Có thể bạn ghét công việc lặp đi lặp lại, nhưng đó thực sự là cách hiệu quả
      • Người có thể code gọn gàng trong thời gian ngắn là người đã có nhiều kinh nghiệm viết kiểu code đó
    • 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

      • Nếu cần tìm đường dẫn các kiểu thì tôi chỉ xử lý bằng thứ đơn giản như breadth first search
      • Đó không phải là “code tệ”, mà chỉ là biện pháp tạm thời và lời giải nhanh
      • Dĩ nhiên đôi khi quy định cấm dùng các module như vậy, và khi đó thì phải tuân theo luật chơi đã cho
    • 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

      • Tôi ghi lại lịch sử thiết kế theo thời gian thực trong thứ tôi gọi là “lab notebook”, và đó trở thành nền tảng cho test và tài liệu về sau
      • Có lab notebook thì dù bắt đầu viết tài liệu muộn vẫn có thể viết tài liệu tốt nhanh hơn. Test cũng giúp xác minh rằng thiết kế chưa bị thay đổi
      • Với công cụ dùng một lần và rất ngắn hạn thì có thể cứ lao vào làm, nhưng với hệ thống dùng lâu dài thì dù chậm hơn một chút, xây nền móng vững chắc ngay từ đầu cuối cùng vẫn cho kết quả hợp lý và dễ bảo trì hơn
      • Đây có thể là ý kiến không mấy phổ biến, nhưng làm thiết kế trước trên giấy rồi mới chuyển sang dạng số thực sự hiệu quả
  • Đâ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

    • Không ít lần sau quá trình đó, chúng tôi đi đến kết luận rằng thật ra không cần xây thứ mà ban đầu nghĩ mình muốn
    • Tôi rất đồng cảm với chuyện mất tập trung khi đang code. Trong lúc dọn dẹp rất dễ rơi vào rabbit hole, khiến phạm vi commit phình to và đồng nghiệp khó review. Kết quả là nhiều khi phải bỏ hết phần đã làm rồi quay lại làm nhỏ hơn, tập trung đúng mục tiêu hơn
    • Đôi khi vẫn có thể tách riêng vài mảnh hữu ích và đưa lên thành PR khác
    • Phía business luôn muốn kết quả thật nhanh, và thường không hiểu các trade-off của code cho đến khi technical debt chất đống khiến tốc độ phát triển chậm khủng khiếp
    • Điều quan trọng là sự cân bằng, và mỗi dự án có thể áp dụng tiêu chuẩn khác nhau
    • Vì vậy, thực hiện các thay đổi nhỏ, tập trung và đơn giản một cách thường xuyên là rất hữu ích
    • Nhưng chia một lời giải lớn thành các mảnh nhỏ không hề dễ như người ta tưởng
    • Tôi thường thấy người ta commit những đoạn code chẳng liên quan, thậm chí còn chưa dùng tới, chỉ vì “sau này có thể cần”. Nhưng rồi khi ưu tiên thay đổi, con người chuyển chỗ, thì một năm sau tất cả đều thành code vô dụng, và cũng chẳng còn ai biết kế hoạch lúc đó là gì nữa