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