27 điểm bởi GN⁺ 16 ngày trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Hoàn thiện trong thời gian ngắn một bộ công cụ phát triển chất lượng cao cho SQLite vốn đã thiếu hụt từ lâu với sự hỗ trợ của AI
  • Thiếu đặc tả ngữ pháp chính thức và codebase C phức tạp khiến việc xây dựng parser trở thành trở ngại lớn nhất
  • Tận dụng các AI coding agent như Claude Code để đẩy nhanh triển khai ban đầu, nhưng do vấn đề mã spaghetti nên đã viết lại trên nền tảng Rust
  • AI cho thấy hiệu quả lớn trong sinh mã, refactor, hỗ trợ học tập, cải thiện UX, nhưng cũng gây ra tác dụng phụ như trì hoãn thiết kế, đứt gãy với code, nghiện phụ thuộc
  • Kết luận, AI chỉ là công cụ tăng tốc triển khai, còn thiết kế và định hướng phần mềm phải do con người chịu trách nhiệm

Ghi chép 3 tháng xây dựng công cụ phát triển SQLite bằng AI

  • Từ lâu đã mong muốn có một bộ công cụ phát triển chất lượng cao cho SQLite, nhưng các công cụ mã nguồn mở hiện có đều thiếu về độ tin cậy, tốc độ và tính linh hoạt
    • Trong quá trình bảo trì PerfettoSQL, đã có nhu cầu về formatter, linter, extension cho editor và các tính năng khác, nhưng không có công cụ phù hợp
    • Từng muốn tự làm một công cụ mới như dự án cá nhân, nhưng vì độ khó và gánh nặng công việc lặp đi lặp lại nên đã trì hoãn suốt nhiều năm

Những điểm khó của dự án

  • SQLite không có đặc tả ngữ pháp chính thức hay parser API ổn định
    • Nội bộ không tạo parse tree, nên phải trích xuất trực tiếp logic parser từ mã nguồn
    • Phải map thủ công hơn 400 quy tắc ngữ pháp, trong khi việc viết test và debug cực kỳ lặp lại và mệt mỏi
  • Codebase C của SQLite phức tạp và dày đặc, nên rất khó hiểu
    • Cấu trúc khó nhằn đến mức chỉ riêng việc nắm được virtual table API và cách triển khai của nó cũng mất vài ngày

Quá trình phát triển cùng AI

  • Từ cuối năm 2025, bắt đầu tận dụng nghiêm túc các AI coding agent như Claude Code
    • Ban đầu giao phần lớn thiết kế và triển khai cho AI, theo kiểu “vibe-coding”
    • Kết quả là có thứ chạy được, nhưng codebase trở nên rối như mì spaghetti, phức tạp đến mức gần như không thể bảo trì
  • Sau đó viết lại toàn bộ bằng Rust để tái thiết lập cấu trúc
    • Dùng Rust thay vì C giúp việc phát triển các thành phần cấp cao hơn (validator, language server, v.v.) dễ dàng hơn
    • Giới hạn AI vào vai trò “công cụ tăng cường tự động hoàn thành”, còn thiết kế, review và test thì trực tiếp chủ động thực hiện
    • Xây dựng scaffolding để kiểm chứng đầu ra của AI như linting, validation, tự động hóa test

Những gì AI đã giúp làm được

  • Vượt qua quán tính

    • AI chia nhỏ công việc thành các đơn vị vấn đề cụ thể, giúp bắt đầu dễ hơn
    • Thay vì “phải hiểu cách parse SQLite”, quá trình được chuyển thành “review cách tiếp cận do AI đề xuất”, từ đó tăng tốc độ thực thi
  • Tốc độ sinh mã và refactor

    • Khi yêu cầu rõ ràng, AI có thể nhanh chóng viết ra mã tiêu chuẩn và nhất quán
    • Nhưng ở các thiết kế phi tiêu chuẩn (như cấu trúc parser), AI lại trở thành vật cản, nên phải tự viết trực tiếp
    • Sau khi sinh lượng lớn mã, refactor liên tục là điều bắt buộc để giữ chất lượng
  • Vai trò trợ lý học tập

    • AI có thể giải thích theo thời gian thực các khái niệm mới như thuật toán định dạng Wadler-Lindig
    • Có thể nhanh chóng nhập cuộc cả ở những mảng chưa quen như Rust hay extension cho VS Code
    • Khi bị mất ngữ cảnh dự án, chỉ cần hỏi kiểu “hãy giải thích component này” là có thể khôi phục ngữ cảnh ngay lập tức
  • Nâng cao mức độ hoàn thiện

    • Giảm chi phí phát triển các tính năng phụ trợ như extension cho editor, Python binding, playground WASM, site tài liệu
    • Nhờ gánh nặng triển khai giảm xuống, có thể tập trung hơn vào cải thiện UX, như thông báo lỗi, thiết kế CLI và trải nghiệm người dùng

Tác dụng phụ của việc dùng AI

  • Tính gây nghiện

    • Cấu trúc phần thưởng kiểu máy đánh bạc khiến người ta lặp lại việc “thêm một prompt nữa”
    • Càng mệt, chất lượng prompt càng giảm, kết quả càng tệ, tạo thành vòng luẩn quẩn
  • Đứt gãy với codebase

    • Càng có nhiều mã do AI sinh ra, càng mất cảm giác về cấu trúc chi tiết
    • Khi mất ngữ cảnh, cả cuộc trò chuyện với AI cũng dài hơn và kém hiệu quả hơn
    • Để khắc phục, hình thành thói quen đọc trực tiếp mã ngay sau khi sinh ra và kiểm tra “nếu là mình, mình sẽ viết chỗ nào khác đi”
  • Trì hoãn và bào mòn thiết kế

    • Vì refactor quá dễ nên phát sinh xu hướng trì hoãn các quyết định thiết kế cốt lõi
    • Dù có nhiều test, vẫn khó che lấp được lỗi thiết kế gốc rễ, và cuối cùng vẫn phải viết lại toàn bộ
  • Thiếu cảm nhận về thời gian

    • AI không hiểu ngữ cảnh thời gian hay quá trình tiến hóa của mã
    • Điều này dẫn đến sự kém hiệu quả như lặp lại lỗi cũ hoặc lại đi khám phá những vấn đề đã giải quyết rồi
    • Có thể bù đắp bằng tài liệu hóa, nhưng rất khó ghi lại đầy đủ cả ý đồ thiết kế

Tính tương đối trong việc tận dụng AI

  • Trong những lĩnh vực đã hiểu sâu, AI phát huy rất tốt, có thể review nhanh và lặp lại hiệu quả
    • Ví dụ: sinh quy tắc parser hiệu quả vì có đáp án khá rõ ràng
  • Trong những lĩnh vực chỉ biết một phần, AI hữu ích như công cụ học tập nhưng vẫn cần chú ý liên tục
    • Ví dụ: học thuật toán formatter
  • Ở giai đoạn còn chưa biết phải làm gì, AI lại có thể gây hại
    • Ví dụ: tạo ra các vòng lặp thiếu hiệu quả ở giai đoạn thiết kế kiến trúc
  • AI mạnh với các bài toán có thể kiểm chứng (compile được, test pass), nhưng
    lại yếu với các vấn đề không có đáp án đúng duy nhất như thiết kế hay chất lượng API

Kết luận

  • Việc có thể hiện thực hóa công cụ SQLite đã ấp ủ suốt 8 năm chỉ trong 3 tháng là nhờ AI
    • Tuy nhiên, quá trình này không phải một câu chuyện thành công đơn giản, mà đi kèm với giới hạn và cái giá của sự phụ thuộc vào AI
  • AI là thiết bị tăng tốc cho triển khai, nhưng không phải vật thay thế cho thiết kế
    • Nó trả lời chính xác các câu hỏi kỹ thuật, nhưng thiếu lịch sử, gu thẩm mỹ và cảm nhận về người dùng
  • Bài học thực sự là, dù AI có giúp đâm vào bức tường nhanh hơn,
    con người vẫn phải chịu trách nhiệm về hướng đi của thiết kế và “linh hồn của phần mềm”
  • Điều cần thiết trong tương lai là chia sẻ các ví dụ dự án đủ sức chịu đựng người dùng thực tế và công việc bảo trì
    • Tức là tích lũy kinh nghiệm phát triển hợp tác với AI theo cách thực tế và bền vững, chứ không chỉ là các thử nghiệm đơn lẻ

1 bình luận

 
Ý kiến trên Hacker News
  • Thật mới mẻ khi thấy một góc nhìn cân bằng về AI coding
    Đây là trải nghiệm mà hầu hết các lập trình viên nghiêm túc đều sẽ đồng cảm — lúc đầu thì kinh ngạc vì AI viết code quá giỏi, nhưng nhìn lại sau đó thì codebase đã thành một đống spaghetti code hỗn loạn
    Có người thậm chí không review code mà đã hô hào “giờ thì coding thủ công đã kết thúc”, còn số khác lại khẳng định “AI coding vô dụng”
    Nhưng thực tế nằm ở đâu đó giữa hai thái cực đó. AI có thể là một bộ tăng tốc năng suất rất lớn, nhưng phải được tích hợp đúng cách vào workflow và con người vẫn phải tiếp tục tham gia

    • Tôi cũng đã dùng Claude làm giao diện coding chính trong 3 tháng qua
      Ban đầu chỉ là prototype nhưng nhanh chóng phát triển thành một dịch vụ thực tế. Sau đó tôi đã rất vất vả khi refactor để dọn đi đống code vô dụng
      Dù vậy, chính nhờ tốc độ làm prototype đó mà sản phẩm hiện tại mới tồn tại. Claude hữu ích như một chiếc cưa máy trong việc dọn dẹp code
      Gần đây tôi thêm type checker bằng pre-commit hook và sửa 90 lỗi chỉ trong 2 giờ.
      AI coding thật đáng kinh ngạc, nhưng với production code thì review và phán đoán của con người vẫn là điều bắt buộc
    • Điều tôi đặc biệt thích ở bài này là quan điểm cân bằng
      Tuy nhiên, vì đây là một greenfield project cá nhân nên khó áp dụng trực tiếp cho phát triển nhóm nói chung
      Dù vậy, nếu làm prototype với tiền đề là ‘sẽ bỏ đi’ thì tôi nghĩ spaghetti code cũng không sao.
      Vấn đề là tác giả đã lầm tưởng rằng có thể phát triển nó thành một sản phẩm thật.
      Nhưng tôi nghĩ chính thất bại đó đã giúp tác giả học được cách thiết kế tốt hơn
    • Thực ra tôi nghĩ những phản ứng cực đoan như vậy là giai đoạn mà mọi người mới tiếp xúc AI coding đều phải trải qua
      Ban đầu ngạc nhiên, sau đó thất vọng, cuối cùng tìm được sự cân bằng.
      Trông giống như một phiên bản AI của mô hình Kübler-Ross
    • Ngược lại, tôi cho rằng sự ám ảnh với chất lượng code lại là điểm mù trong thời đại AI
      Tất nhiên chất lượng là quan trọng, nhưng giờ đây bản thân chất lượng code đang dần bớt quan trọng hơn
      Ngày càng có nhiều code không cần bảo trì, như app cá nhân, và năng lực thiết kế của AI cũng đang cải thiện rất nhanh
      Cuối cùng, “sự thật về AI coding” vẫn đang liên tục thay đổi, và xu hướng này sẽ không dừng lại
    • Tôi nghĩ có hai lý do khiến những bài viết thực tế như vậy hiếm gặp
      Thứ nhất, đa số lập trình viên chỉ lặng lẽ tận hưởng mức tăng năng suất 2~50% và không thấy cần phải nói nhiều
      Thứ hai, AI coding thực sự thì nhàm chán và không đẹp để trình diễn.
      Suy cho cùng, LLM chỉ là ‘công cụ giúp không phải nhớ boilerplate’, còn bản chất của việc coding vẫn vậy
  • Tôi cũng gặp đúng vấn đề này với việc AI tạo test
    Khi số lượng test tăng lên thì cảm thấy yên tâm hơn, nhưng thực tế lại không xử lý được hết edge case
    Đặc biệt khi refactor legacy code không có test, các test do AI tạo ra chỉ xác nhận là nó chạy được chứ không đảm bảo tính nhất quán của hành vi
    Trong ứng dụng React, vấn đề này đặc biệt nghiêm trọng. Vì thế tôi đang suy nghĩ về cách kết hợp BDD + phát triển dựa trên đặc tả với AI

    • Tôi cảm thấy viết test tốt khó hơn viết code thật 10 lần
      Unit test cần thiết kế mock một cách sáng tạo, integration test thì cốt lõi là thao tác dữ liệu, còn e2e test thì trọng tâm là độ ổn định của selector
      Những phán đoán sáng tạo như vậy vẫn là thứ AI khó theo kịp
    • Không nên bị đánh lừa bởi con số coverage
      Dù coverage là 97% thì không gian đầu vào về mặt logic vẫn có rất nhiều lỗ hổng.
      Gần đây tôi đã tự động hóa các kỹ thuật cổ điển như equivalence partitioning bằng AI agent và áp dụng cho 60 model
    • Tôi khuyên dùng cách mô tả đặc tả hoạt động hệ thống bằng TLA+ rồi liên kết code với spec
      Cốt lõi là tách các pure function ra tối đa để có thể test hoàn chỉnh ánh xạ đầu vào-đầu ra
  • Về dài hạn, tôi nghĩ giá trị thực sự của AI là vai trò như một công cụ khuếch đại khả năng hiểu biết
    Ví dụ như phân tích các quy tắc trong C code phức tạp rồi tài liệu hóa cấu trúc của nó
    Nếu có thể làm được kiểu trích xuất tri thức này, thì cả tài liệu API, mapping quy tắc, phân tích bug và tối ưu kiến trúc đều có thể được tự động hóa
    Cuối cùng, năng lực cấu trúc hóa ngữ cảnh sẽ trở nên quan trọng hơn việc tạo code

    • Cách mỗi người dùng AI khác nhau một cách rất rõ rệt
      ① Kiểu oracle toàn tri: chỉ ném yêu cầu vào rồi để nó tạo cả ứng dụng
      ② Kiểu công cụ hỗ trợ: dùng trong IDE và review từng dòng một
      Nếu muốn xây dựng một dịch vụ bền vững thì hướng ② thực tế hơn nhiều
  • Câu “kiến trúc xuất hiện khi các mảnh cục bộ tương tác với nhau” thật ấn tượng
    AI mạnh ở việc thực thi cục bộ, nhưng yếu ở giai đoạn thiết kế mơ hồ
    Thực ra điều này với lập trình viên con người cũng vậy. Thiết kế là chuỗi những đánh đổi không có đáp án đúng tuyệt đối

    • Tôi cũng từng đi đến kết luận thiết kế nhờ các cuộc trò chuyện dài với AI
      Nó đặc biệt giúp ích rất nhiều trong việc thiết kế ClickHouse SQL
      Nhờ cách include SQL dựa trên template mà AI đề xuất, tôi đã giảm trùng lặp và cải thiện hiệu năng
      Cách tiếp cận này có thể trước đây đã từng tồn tại, nhưng nếu không có AI thì có lẽ tôi khó mà tìm ra
  • Lý do bài này đáng tin là vì nó dựa trên 250 giờ nỗ lực thực tế
    Tôi nghĩ quy mô dự án như vậy là một mô hình thực tế cho system programming có AI hỗ trợ

  • Cách nói “AI coding giống như máy đánh bạc” thật quá đúng
    Tôi cũng được công ty cấp quyền truy cập AI agent không giới hạn, nhưng cứ “thêm một prompt nữa thôi” rồi
    đến lúc nhận ra thì đã trôi qua 12 tiếng. Tính gây nghiện của trạng thái nhập tâm rất mạnh

  • Có lẽ bây giờ là thời kỳ AI coding khó nhất
    Những điều 6 tháng trước còn không tưởng thì giờ đã làm được
    Tôi đang làm dự án bằng nhiều ngôn ngữ, và AI tạo code nhanh đến mức
    giờ đây tốc độ review lại trở thành nút thắt cổ chai
    Khi một mức test nào đó đã pass thì lại nảy sinh câu hỏi “thế này đã đủ tốt chưa?”
    Tôi thường ghi rõ các thuộc tính chất lượng như nguyên tắc SOLID, coupling, cohesion vào prompt
    Hỏi AI ý tưởng refactor, nếu thấy ổn thì chỉ cần nói “được, làm đi”
    Cuối cùng, điều quan trọng là nghệ thuật thiết kế prompt
    Nhưng tôi nghĩ chẳng bao lâu nữa AI sẽ mặc định thực hiện những guardrail chất lượng như vậy

    • Cũng có người hỏi vì sao lại làm dự án bằng nhiều ngôn ngữ
      Bản thân ngôn ngữ không phải nút thắt hiệu năng, nhưng thử nghiệm ngôn ngữ mới có ích cho việc học
  • Điều này làm tôi nhớ đến triết lý “hãy bỏ đi một cái” của Fred Brooks
    AI là công cụ tối ưu để tạo ra phiên bản đầu tiên đó thật nhanh
    Việc kỳ vọng chất lượng production ngay lập tức là một cách tiếp cận ngây thơ
    Làm nhanh, học nhanh, rồi refactor sau mới là chính đạo
    Tôi cũng đồng cảm với ý rằng khi mệt thì prompt trở nên mơ hồ hơn và kết quả cũng tệ hơn

    • Tuy nhiên cũng thú vị là sau này Brooks đã chuyển quan điểm sang cải tiến lặp dần (iterative refinement)
  • Tôi ngạc nhiên khi biết parser SQL của SQLite không được tạo bằng lemon
    Khi port pikchr sang Go, tôi đã chuyển lemon trước, nhưng SQLite thậm chí còn không tạo parser tree
    Nhìn vào tài liệu lemon, điều này có vẻ là sự thiếu rõ ràng trong việc định nghĩa vấn đề ở giai đoạn thiết kế

  • Tôi hoàn toàn đồng ý với kết luận của bài này
    Đây là một ví dụ tốt cho thấy thực tế của AI coding một cách thẳng thắn, không phóng đại