Frontend·Hacker News·4 lượt xem

Tám năm thiếu thốn, ba tháng xây dựng với AI

Eight years of wanting, three months of building with AI

AI Summary

Sau tám năm ấp ủ, tác giả đã cho ra mắt `syntaqlite`, một bộ công cụ dành cho SQLite, nhờ vào ba tháng phát triển có sự hỗ trợ của AI. Dự án này lấp đầy khoảng trống về trải nghiệm phát triển chất lượng cao cho cơ sở dữ liệu SQLite phổ biến. Các developer Việt Nam cần lưu ý rằng AI coding agents có thể đẩy nhanh đáng kể quá trình xây dựng các dự án phức tạp, đã mong muốn từ lâu, đặc biệt là những dự án liên quan đến các khía cạnh khó nhằn như parsing SQL chính xác mà không có tài liệu kỹ thuật chính thức.

Trong tám năm, tôi đã muốn có một bộ devtools chất lượng cao để làm việc với SQLite. Với tầm quan trọng của SQLite đối với ngành công nghiệp 1, từ lâu tôi đã bối rối rằng không ai đầu tư vào việc xây dựng trải nghiệm nhà phát triển thực sự tốt cho nó 2. Một vài tuần trước, sau ~250 giờ nỗ lực trong ba tháng3 vào buổi tối, cuối tuần và ngày nghỉ, cuối cùng tôi đã phát hành syntaqlite (GitHub), thực hiện mong muốn từ lâu này. Và tôi tin rằng lý do chính khiến điều này xảy ra là do các tác nhân mã hóa AI4. Của

Trong tám năm, tôi đã mong muốn có một bộ công cụ dành cho nhà phát triển (devtools) chất lượng cao để làm việc với SQLite. Với tầm quan trọng của SQLite đối với ngành1, tôi luôn thắc mắc tại sao chưa ai đầu tư xây dựng trải nghiệm tốt thực sự cho nó2.

Vài tuần trước, sau khoảng 250 giờ nỗ lực trong ba tháng3 vào các buổi tối, cuối tuần và ngày nghỉ, cuối cùng tôi đã phát hành syntaqlite (GitHub), hoàn thành mong muốn ấp ủ bấy lâu nay. Và tôi tin rằng lý do chính khiến điều này xảy ra là nhờ các AI coding agents4.

Tất nhiên, không thiếu những bài viết tuyên bố AI đã hoàn thành dự án của họ chỉ trong một lần thử hoặc phản bác rằng AI chỉ toàn rác rưởi. Tôi sẽ tiếp cận rất khác, thay vào đó, tôi sẽ phân tích một cách có hệ thống kinh nghiệm xây dựng syntaqlite với AI, cả những khía cạnh nó đã giúp đỡ những khía cạnh nó gây cản trở.

Tôi sẽ thực hiện điều này trong khi đặt dự án và nền tảng của tôi vào ngữ cảnh để bạn có thể tự đánh giá mức độ tổng quát của kinh nghiệm này. Và bất cứ khi nào tôi đưa ra một tuyên bố, tôi sẽ cố gắng chứng minh bằng bằng chứng từ nhật ký dự án, bản ghi mã hóa hoặc lịch sử commit của tôi5.

Tại sao tôi muốn nó

Trong quá trình làm việc với Perfetto, tôi duy trì một ngôn ngữ dựa trên SQLite để truy vấn các dấu vết hiệu suất được gọi là PerfettoSQL. Về cơ bản, nó giống như SQLite nhưng có một vài tiện ích mở rộng để cải thiện trải nghiệm truy vấn dấu vết. Có khoảng 100K dòng PerfettoSQL nội bộ tại Google và nó được sử dụng bởi nhiều nhóm khác nhau.

Việc có một ngôn ngữ được sử dụng rộng rãi có nghĩa là người dùng của bạn cũng bắt đầu mong đợi những thứ như bộ định dạng (formatters), bộ kiểm tra lỗi (linters) và các tiện ích mở rộng cho trình soạn thảo (editor extensions). Tôi đã hy vọng chúng ta có thể điều chỉnh một số công cụ SQLite từ mã nguồn mở, nhưng càng tìm hiểu, tôi càng thất vọng. Những gì tôi tìm thấy hoặc không đủ tin cậy, không đủ nhanh6, hoặc không đủ linh hoạt để điều chỉnh cho PerfettoSQL. Rõ ràng có cơ hội để xây dựng một cái gì đó từ đầu, nhưng đó chưa bao giờ là “điều quan trọng nhất chúng ta có thể làm”. Chúng tôi đã miễn cưỡng sử dụng các công cụ có sẵn nhưng luôn ao ước có những thứ tốt hơn.

Mặt khác, lựa chọn để làm điều đó trong thời gian rảnh. Tôi đã xây dựng nhiều dự án mã nguồn mở khi còn là thiếu niên7 nhưng điều này đã phai nhạt dần trong thời gian đại học khi tôi cảm thấy mình không còn động lực nữa. Trở thành người duy trì còn nhiều hơn là chỉ “tung mã nguồn ra ngoài” và xem điều gì xảy ra. Đó là việc phân loại lỗi (triaging bugs), điều tra sự cố (investigating crashes), viết tài liệu, xây dựng cộng đồng và quan trọng nhất là có một định hướng cho dự án.

Nhưng khao khát về mã nguồn mở (đặc biệt là sự tự do làm những gì mình muốn trong khi giúp đỡ người khác) chưa bao giờ biến mất. Dự án devtools SQLite luôn nằm trong tâm trí tôi như “một thứ gì đó tôi muốn làm”. Nhưng còn một lý do nữa khiến tôi cứ trì hoãn: nó nằm ở giao điểm của việc vừa khó vừa tẻ nhạt.

Điều gì khiến nó khó và tẻ nhạt

Nếu tôi định đầu tư thời gian cá nhân vào dự án này, tôi không muốn xây dựng thứ gì đó chỉ giúp ích cho Perfetto: tôi muốn nó hoạt động cho bất kỳ người dùng SQLite nào8. Và điều này có nghĩa là phân tích cú pháp SQL chính xác như SQLite.

Cốt lõi của bất kỳ devtool nào định hướng ngôn ngữ là trình phân tích cú pháp (parser). Nó chịu trách nhiệm chuyển đổi mã nguồn thành một “cây phân tích cú pháp” (parse tree) hoạt động như cấu trúc dữ liệu trung tâm mà mọi thứ khác được xây dựng trên đó. Nếu trình phân tích cú pháp của bạn không chính xác, thì các bộ định dạng và bộ kiểm tra lỗi của bạn chắc chắn sẽ kế thừa những sai sót đó; nhiều công cụ tôi tìm thấy gặp vấn đề với các trình phân tích cú pháp chỉ xấp xỉ ngôn ngữ SQLite thay vì biểu diễn nó một cách chính xác.

Thật không may, không giống như nhiều ngôn ngữ khác, SQLite không có đặc tả chính thức mô tả cách nó nên được phân tích cú pháp. Nó cũng không cung cấp một API ổn định cho trình phân tích cú pháp của nó. Trên thực tế, khá độc đáo, trong triển khai của nó, nó thậm chí còn không xây dựng cây phân tích cú pháp nào cả9! Theo ý kiến của tôi, cách tiếp cận hợp lý duy nhất còn lại là cẩn thận trích xuất các phần liên quan của mã nguồn SQLite và điều chỉnh nó để xây dựng trình phân tích cú pháp mà tôi muốn.

Điều này có nghĩa là đi sâu vào mã nguồn SQLite, một mã nguồn cực kỳ khó hiểu. Toàn bộ dự án được viết bằng C theo một kiểu cực kỳ dày đặc; tôi đã dành nhiều ngày chỉ để hiểu API11triển khai của bảng ảo (virtual table). Việc cố gắng nắm bắt toàn bộ ngăn xếp phân tích cú pháp thật đáng sợ.

Ngoài ra còn có thực tế là có hơn 400 quy tắc trong SQLite để bao quát toàn bộ bề mặt ngôn ngữ của nó. Tôi sẽ phải chỉ định trong mỗi “quy tắc ngữ pháp” này cách phần cú pháp đó ánh xạ tới nút tương ứng trong cây phân tích cú pháp. Đó là một công việc cực kỳ lặp đi lặp lại; mỗi quy tắc đều tương tự như tất cả các quy tắc xung quanh nó nhưng cũng, theo định nghĩa, khác biệt.

Và không chỉ là các quy tắc mà còn là việc nghĩ ra và viết các bài kiểm tra để đảm bảo nó chính xác, gỡ lỗi nếu có gì đó sai, phân loại và sửa các lỗi không thể tránh khỏi mà mọi người báo cáo khi tôi làm sai điều gì đó…

Trong nhiều năm, ý tưởng đã dừng lại ở đây. Quá khó cho một dự án phụ12, quá tẻ nhạt để duy trì động lực, quá rủi ro để đầu tư hàng tháng vào một thứ có thể không hoạt động.

Nó đã xảy ra như thế nào

Tôi đã sử dụng các AI coding agents từ đầu năm 2025 (Aider, Roo Code, sau đó là Claude Code từ tháng 7) và chúng chắc chắn hữu ích nhưng chưa bao giờ là thứ mà tôi cảm thấy mình có thể tin tưởng cho một dự án nghiêm túc. Nhưng vào cuối năm 2025, các mô hình dường như đã có một bước tiến đáng kể về chất lượng13. Đồng thời, tôi liên tục gặp các vấn đề trong Perfetto mà lẽ ra có thể giải quyết dễ dàng bằng cách có một trình phân tích cú pháp đáng tin cậy. Mỗi giải pháp tạm thời đều để lại suy nghĩ trong đầu tôi: có lẽ cuối cùng đã đến lúc xây dựng nó thật sự.

Tôi đã có thời gian để suy nghĩ và chiêm nghiệm trong dịp Giáng sinh và quyết định thử nghiệm phiên bản tối đa nhất của AI: liệu tôi có thể làm toàn bộ việc này chỉ bằng Claude Code trên gói Max (£200/tháng) không?

Trong gần hết tháng 1, tôi đã lặp đi lặp lại, đóng vai trò quản lý bán kỹ thuật và ủy quyền gần như toàn bộ thiết kế và tất cả việc triển khai cho Claude. Về mặt chức năng, tôi đã đạt được một kết quả hợp lý: một trình phân tích cú pháp bằng C được trích xuất từ nguồn SQLite sử dụng một loạt tập lệnh Python, một công cụ định dạng được xây dựng trên đó, hỗ trợ cả ngôn ngữ SQLite và các tiện ích mở rộng PerfettoSQL, tất cả đều được hiển thị trong một playground web.

Nhưng khi tôi xem xét kỹ lưỡng cơ sở mã vào cuối tháng 1, nhược điểm là rõ ràng: cơ sở mã là một mớ hỗn độn14. Tôi không hiểu phần lớn quy trình trích xuất nguồn Python, các hàm bị phân tán trong các tệp ngẫu nhiên mà không có cấu trúc rõ ràng và một vài tệp đã phát triển lên đến vài nghìn dòng. Nó cực kỳ mong manh; nó giải quyết vấn đề trước mắt nhưng nó sẽ không bao giờ đáp ứng được tầm nhìn lớn hơn của tôi, chứ đừng nói đến việc tích hợp nó vào các công cụ Perfetto. Điểm cứu vớt là nó đã chứng minh tính khả thi của cách tiếp cận và tạo ra hơn 500 bài kiểm tra, nhiều bài trong số đó tôi cảm thấy có thể tái sử dụng.

Tôi quyết định bỏ tất cả và bắt đầu lại từ đầu đồng thời chuyển phần lớn cơ sở mã sang Rust15. Tôi nhận thấy rằng C sẽ làm cho việc xây dựng các thành phần cấp cao hơn như trình xác thực và triển khai máy chủ ngôn ngữ trở nên khó khăn. Và như một phần thưởng, nó cũng cho phép tôi sử dụng cùng một ngôn ngữ cho cả việc trích xuất và thời gian chạy thay vì chia nó giữa C và Python.

Quan trọng hơn, tôi đã thay đổi hoàn toàn vai trò của mình trong dự án. Tôi chịu trách nhiệm cho tất cả các quyết định16 và sử dụng nó như "tự động hoàn thành tăng cường" trong một quy trình chặt chẽ hơn nhiều: thiết kế có chủ kiến ngay từ đầu, xem xét kỹ lưỡng mọi thay đổi, sửa lỗi một cách nhiệt tình ngay khi phát hiện ra và đầu tư vào khung sườn (như linting, xác thực và kiểm tra không tầm thường17) để kiểm tra đầu ra AI một cách tự động.

Các tính năng cốt lõi đã được hoàn thành trong tháng 2 và chặng cuối (xác thực kiểm tra upstream, tiện ích mở rộng trình chỉnh sửa, đóng gói, tài liệu) đã dẫn đến việc ra mắt phiên bản 0.1 vào giữa tháng 3.

Nhưng theo ý kiến của tôi, dòng thời gian này là phần ít thú vị nhất của câu chuyện này. Điều tôi thực sự muốn nói là những gì đã không xảy ra nếu không có AI và cả những gì nó đã lấy đi từ tôi khi tôi sử dụng nó.

AI là lý do dự án này tồn tại, và là lý do tại sao nó hoàn chỉnh như vậy

Vượt qua quán tính

Tôi đã viết trước đây về một trong những điểm yếu lớn nhất của tôi với tư cách là một kỹ sư phần mềm là xu hướng trì hoãn khi đối mặt với một dự án mới lớn. Mặc dù lúc đó tôi không nhận ra, nhưng điều này hoàn toàn đúng với việc xây dựng syntaqlite.

AI về cơ bản đã cho phép tôi gạt bỏ tất cả những nghi ngờ của mình trong các cuộc gọi kỹ thuật, sự không chắc chắn về việc xây dựng đúng thứ và sự miễn cưỡng bắt đầu bằng cách đưa cho tôi những vấn đề rất cụ thể để làm việc. Thay vì "Tôi cần hiểu cách phân tích cú pháp của SQLite hoạt động", nó là "Tôi cần AI gợi ý một cách tiếp cận cho tôi để tôi có thể xé bỏ nó và xây dựng một thứ gì đó tốt hơn"18. Tôi làm việc hiệu quả hơn nhiều với các nguyên mẫu cụ thể để thử nghiệm và mã để xem hơn là suy nghĩ vô tận về thiết kế trong đầu, và AI cho phép tôi đạt đến điểm đó với tốc độ mà tôi không thể mơ tới trước đây. Một khi tôi đã bước bước đầu tiên, mọi bước sau đó đều dễ dàng hơn rất nhiều.

Chuyển mã nhanh hơn

AI tỏ ra giỏi hơn tôi trong việc viết mã, giả sử mã đó là rõ ràng. Nếu tôi có thể chia nhỏ một vấn đề thành "viết một hàm với hành vi và tham số này" hoặc "viết một lớp khớp với giao diện này", AI sẽ xây dựng nó nhanh hơn tôi và, quan trọng nhất, theo một phong cách có thể trực quan hơn đối với người đọc trong tương lai. Nó ghi lại những điều tôi sẽ bỏ qua, sắp xếp mã nhất quán với phần còn lại của dự án và tuân thủ cái mà bạn có thể gọi là "tiếng địa phương tiêu chuẩn" của bất kỳ ngôn ngữ nào bạn đang làm việc19.

Sự tiêu chuẩn đó là một con dao hai lưỡi. Đối với phần lớn mã trong bất kỳ dự án nào, tiêu chuẩn chính xác là những gì bạn muốn: có thể dự đoán, dễ đọc, không gây bất ngờ. Nhưng mọi dự án đều có những phần là biên giới của nó, những phần mà giá trị đến từ việc làm điều gì đó không hiển nhiên. Đối với syntaqlite, đó là quy trình trích xuất và kiến trúc trình phân tích cú pháp. Bản năng chuẩn hóa của AI đã gây hại ở đó, và đó là những phần tôi phải thiết kế chuyên sâu và thường phải tự mình viết.

Nhưng đây là mặt trái: tốc độ làm cho AI tuyệt vời với mã rõ ràng cũng làm cho nó tuyệt vời trong việc tái cấu trúc. Nếu bạn sử dụng AI để tạo mã ở quy mô công nghiệp, bạn phải tái cấu trúc liên tục và không ngừng20. Nếu không, mọi thứ sẽ nhanh chóng trở nên mất kiểm soát. Đây là bài học trung tâm của tháng vibe-coding: tôi đã không tái cấu trúc đủ, cơ sở mã trở thành thứ mà tôi không thể suy luận được, và tôi phải bỏ tất cả. Trong lần viết lại, tái cấu trúc đã trở thành cốt lõi trong quy trình làm việc của tôi. Sau mỗi lô mã lớn được tạo ra, tôi sẽ lùi lại và hỏi "có xấu không?" Đôi khi AI có thể dọn dẹp nó. Những lần khác có một trừu tượng hóa quy mô lớn mà AI không thể nhìn thấy nhưng tôi có thể; tôi sẽ cung cấp cho nó hướng đi và để nó thực thi21. Nếu bạn có gu thẩm mỹ, chi phí của một cách tiếp cận sai lầm sẽ giảm đáng kể vì bạn có thể cấu trúc lại nhanh chóng22.

Trợ giảng

Trong tất cả các cách tôi sử dụng AI, nghiên cứu có tỷ lệ giá trị mang lại trên thời gian bỏ ra cao nhất.

Tôi đã từng làm việc với các trình thông dịch và trình phân tích cú pháp trước đây nhưng tôi chưa bao giờ nghe nói về Wadler-Lindig pretty printing23. Khi tôi cần xây dựng trình định dạng, AI đã cung cấp cho tôi một bài học cụ thể và có thể hành động được từ một góc nhìn mà tôi có thể hiểu và chỉ cho tôi các bài báo để tìm hiểu thêm. Tôi có thể tự tìm ra điều này cuối cùng, nhưng AI đã nén những gì có thể là một hoặc hai ngày đọc thành một cuộc trò chuyện tập trung nơi tôi có thể hỏi "nhưng tại sao cái này lại hoạt động?" cho đến khi tôi thực sự hiểu.

Điều này đã mở rộng ra các lĩnh vực hoàn chỉnh mà tôi chưa bao giờ làm việc. Tôi có chuyên môn sâu về hiệu suất C++ và Android nhưng hầu như chưa chạm vào công cụ Rust hoặc API mở rộng trình chỉnh sửa. Với AI, đó không phải là vấn đề: các nguyên tắc cơ bản giống nhau, thuật ngữ tương tự và AI bắc cầu cho khoảng cách đó24. Tiện ích mở rộng VS Code có thể đã mất của tôi một hoặc hai ngày để học API trước khi tôi có thể bắt đầu. Với AI, tôi đã có một tiện ích mở rộng hoạt động trong vòng một giờ.

Việc này cũng vô cùng hữu ích để tôi làm quen lại với các phần của dự án mà tôi đã không xem trong vài ngày25. Tôi có thể kiểm soát mức độ chi tiết: “cho tôi biết về thành phần này” để làm mới ở mức bề mặt, “cho tôi một bài kiểm tra chi tiết theo tuyến tính” để đi sâu hơn, “kiểm tra các cách sử dụng không an toàn trong kho lưu trữ này” để săn lùng các vấn đề. Khi bạn phải chuyển đổi ngữ cảnh nhiều, bạn sẽ nhanh chóng mất đi ngữ cảnh. AI cho phép tôi lấy lại nó theo yêu cầu.

Nhiều hơn tôi có thể xây dựng một mình

Ngoài việc làm cho dự án tồn tại, AI còn là lý do khiến nó được hoàn thành đầy đủ như vậy. Mọi dự án mã nguồn mở đều có một danh sách dài các tính năng quan trọng nhưng không mang tính quyết định: những thứ bạn biết về mặt lý thuyết cách thực hiện nhưng liên tục ưu tiên thấp hơn vì công việc cốt lõi cấp bách hơn. Đối với syntaqlite, danh sách đó rất dài: tiện ích mở rộng trình soạn thảo, ràng buộc Python, playground WASM, trang web tài liệu, đóng gói cho nhiều hệ sinh thái26. AI đã làm cho những việc này trở nên đủ rẻ để bỏ qua chúng cảm giác như một sự đánh đổi sai lầm.

Nó cũng giải phóng năng lượng tinh thần cho UX27. Thay vì dành toàn bộ thời gian vào việc triển khai, tôi có thể suy nghĩ về trải nghiệm đầu tiên của người dùng nên như thế nào: những thông báo lỗi nào thực sự giúp họ sửa SQL của mình, định dạng đầu ra nên trông như thế nào theo mặc định, các cờ CLI có trực quan không. Đây là những yếu tố phân biệt một công cụ mà mọi người chỉ dùng thử một lần với một công cụ mà họ tiếp tục sử dụng, và AI đã cho tôi đủ thời gian để quan tâm đến chúng. Nếu không có AI, tôi đã xây dựng một thứ gì đó nhỏ hơn nhiều, có lẽ không có tiện ích mở rộng trình soạn thảo hoặc trang web tài liệu. AI không chỉ làm cho cùng một dự án nhanh hơn. Nó đã thay đổi bản chất của dự án.

AI đã có những chi phí gì

Sự nghiện ngập

Có một sự tương đồng khó chịu giữa việc sử dụng các công cụ lập trình AI và chơi máy đánh bạc28. Bạn gửi một câu lệnh, chờ đợi, và hoặc nhận được thứ gì đó tuyệt vời hoặc thứ gì đó vô dụng. Tôi thấy mình thức khuya chỉ muốn làm “thêm một câu lệnh nữa”, liên tục thử AI chỉ để xem điều gì sẽ xảy ra ngay cả khi tôi biết có lẽ nó sẽ không hiệu quả. Sự ảo tưởng về chi phí chìm cũng xuất hiện: tôi sẽ tiếp tục làm ngay cả với những tác vụ rõ ràng không phù hợp, tự nhủ “có lẽ lần này tôi sẽ diễn đạt khác đi”.

Vòng lặp phản hồi sự mệt mỏi làm cho tình hình tồi tệ hơn29. Khi tôi có năng lượng, tôi có thể viết các câu lệnh chính xác, có phạm vi rõ ràng và thực sự hiệu quả. Nhưng khi tôi mệt mỏi, các câu lệnh của tôi trở nên mơ hồ, kết quả tồi tệ hơn, và tôi lại thử lại, càng mệt mỏi hơn trong quá trình đó. Trong những trường hợp này, AI có lẽ còn chậm hơn việc tự triển khai mọi thứ, nhưng thật khó để thoát ra khỏi vòng lặp đó30.

Mất kết nối

Nhiều lần trong quá trình dự án, tôi đã mất đi mô hình tinh thần về cơ sở mã31. Không phải là kiến trúc tổng thể hay cách mọi thứ khớp với nhau. Mà là chi tiết hàng ngày về những gì nằm ở đâu, hàm nào gọi hàm nào, những quyết định nhỏ tích lũy thành một hệ thống hoạt động. Khi điều đó xảy ra, những vấn đề bất ngờ xuất hiện và tôi hoàn toàn bối rối không hiểu điều gì đang sai. Tôi ghét cảm giác đó.

Vấn đề sâu sắc hơn là việc mất kết nối đã tạo ra sự ngắt kết nối giao tiếp32. Khi bạn không còn nắm bắt được luồng suy nghĩ về những gì đang diễn ra, việc giao tiếp có ý nghĩa với tác nhân trở nên bất khả thi. Mọi trao đổi đều trở nên dài hơn và dài dòng hơn. Thay vì “thay đổi FooClass để làm X”, bạn cuối cùng lại nói “thay đổi cái gì đó làm Bar để làm X”. Sau đó, tác nhân phải tìm hiểu Bar là gì, cách nó ánh xạ tới FooClass, và đôi khi nó làm sai33. Đó chính xác là lời phàn nàn mà các kỹ sư luôn có về các nhà quản lý không hiểu mã, yêu cầu những điều kỳ lạ hoặc bất khả thi. Chỉ có điều bây giờ bạn đã trở thành nhà quản lý đó.

Cách khắc phục là có chủ đích: tôi đã tạo thói quen đọc lại mã ngay sau khi nó được triển khai và tích cực tương tác để xem “tôi sẽ làm thế nào khác đi?”.

Tất nhiên, theo một nghĩa nào đó, tất cả những điều trên cũng đúng với mã tôi đã viết vài tháng trước (do đó có quan điểm rằng mã AI là mã kế thừa), nhưng AI làm cho sự trôi dạt xảy ra nhanh hơn vì bạn không xây dựng cùng một bộ nhớ cơ bắp đến từ việc gõ nó ra ban đầu.

Sự ăn mòn chậm

Có một số vấn đề khác mà tôi chỉ phát hiện ra dần dần trong ba tháng.

Tôi thấy rằng AI khiến tôi trì hoãn các quyết định thiết kế quan trọng34. Bởi vì việc tái cấu trúc rất dễ dàng, tôi luôn có thể nói “tôi sẽ xử lý việc này sau”. Và bởi vì AI có thể tái cấu trúc ở cùng quy mô công nghiệp như nó tạo mã, chi phí của việc trì hoãn có vẻ thấp. Nhưng không phải vậy: trì hoãn các quyết định đã ăn mòn khả năng suy nghĩ rõ ràng của tôi vì cơ sở mã vẫn còn khó hiểu trong thời gian đó. Tháng mã hóa theo cảm hứng là phiên bản cực đoan nhất của điều này. Vâng, tôi hiểu vấn đề, nhưng nếu tôi kỷ luật hơn trong việc đưa ra các quyết định thiết kế khó khăn sớm hơn, tôi có thể hội tụ về kiến trúc phù hợp nhanh hơn nhiều.

Các bài kiểm tra cũng tạo ra một sự thoải mái sai lầm tương tự35. Có hơn 500 bài kiểm tra tạo cảm giác an tâm, và AI giúp việc tạo thêm bài kiểm tra trở nên dễ dàng. Nhưng cả con người lẫn AI đều không đủ sáng tạo để lường trước mọi trường hợp biên mà bạn sẽ gặp phải trong tương lai; có nhiều lần trong giai đoạn mã hóa theo cảm hứng, tôi sẽ nghĩ ra một trường hợp kiểm thử và nhận ra rằng thiết kế của một thành phần nào đó hoàn toàn sai và cần phải được làm lại hoàn toàn. Đây là một yếu tố đóng góp đáng kể vào sự thiếu tin tưởng của tôi và quyết định loại bỏ mọi thứ và bắt đầu lại từ đầu.

Về cơ bản, tôi đã học được rằng “quy tắc thông thường” của phần mềm vẫn áp dụng trong thời đại AI: nếu bạn không có nền tảng cơ bản (kiến trúc rõ ràng, ranh giới được xác định rõ ràng) thì bạn sẽ mãi mãi đuổi theo lỗi khi chúng xuất hiện.

Không có cảm giác thời gian

Một điều tôi liên tục quay trở lại là AI hiểu biết rất ít về sự trôi qua của thời gian36. Nó nhìn thấy một cơ sở mã ở một trạng thái nhất định nhưng không cảm nhận thời gian như con người. Tôi có thể cho bạn biết cảm giác khi sử dụng một API, nó đã phát triển như thế nào trong nhiều tháng hoặc nhiều năm, tại sao một số quyết định nhất định đã được đưa ra và sau đó bị đảo ngược.

Vấn đề tự nhiên từ sự thiếu hiểu biết này là bạn hoặc mắc phải những sai lầm giống như bạn đã mắc phải trong quá khứ và phải học lại bài học hoặc bạn rơi vào những cạm bẫy mới mà lần đầu tiên đã tránh được thành công, làm chậm bạn lại trong dài hạn. Theo ý kiến của tôi, đây là một vấn đề tương tự như lý do tại sao việc mất đi một kỹ sư cấp cao chất lượng cao lại gây tổn thương lớn cho một nhóm: họ mang theo lịch sử và ngữ cảnh mà không tồn tại ở đâu khác và đóng vai trò là người hướng dẫn cho những người xung quanh họ.

Về lý thuyết, bạn có thể cố gắng giữ nguyên ngữ cảnh này bằng cách cập nhật các quy cách và tài liệu. Nhưng có lý do khiến chúng ta không làm điều này trước đây khi có AI: việc ghi lại một cách đầy đủ các quyết định thiết kế ngầm là cực kỳ tốn kém và mất thời gian để viết ra. AI có thể giúp soạn thảo các tài liệu này, nhưng vì không có cách nào để tự động xác minh xem AI đã nắm bắt chính xác những gì quan trọng hay chưa, nên con người vẫn phải kiểm tra thủ công kết quả. Và điều đó vẫn tốn thời gian.

Còn có vấn đề ô nhiễm ngữ cảnh. Bạn không bao giờ biết khi nào một ghi chú thiết kế về API A sẽ vang vọng sang API B. Tính nhất quán là một phần quan trọng làm nên sự hoạt động của cơ sở mã, và vì điều đó, bạn không chỉ cần ngữ cảnh về những gì bạn đang làm ngay bây giờ mà còn cả về những thứ khác đã được thiết kế theo cách tương tự. Việc quyết định điều gì là liên quan đòi hỏi chính xác loại phán đoán mà kiến thức thể chế cung cấp ngay từ đầu.

Tính tương đối

Suy ngẫm về những điều trên, mô hình khi AI giúp ích và khi nào nó gây hại là khá nhất quán.

Khi tôi làm việc trên một thứ mà tôi đã hiểu sâu sắc, AI đã rất xuất sắc. Tôi có thể xem lại kết quả của nó ngay lập tức, phát hiện lỗi trước khi chúng xảy ra và tiến bộ với tốc độ mà tôi không bao giờ có thể một mình đạt được. Việc tạo quy tắc phân tích cú pháp là ví dụ rõ ràng nhất37: tôi biết chính xác mỗi quy tắc nên tạo ra gì, vì vậy tôi có thể xem lại kết quả của AI trong vòng một hoặc hai phút và lặp lại nhanh chóng.

Khi tôi làm việc trên một thứ mà tôi có thể mô tả nhưng chưa hiểu rõ, AI khá tốt nhưng cần cẩn trọng hơn. Việc học Wadler-Lindig cho trình định dạng giống như vậy: tôi có thể diễn đạt những gì mình muốn, đánh giá xem kết quả có đi đúng hướng hay không, và học hỏi từ những gì AI giải thích. Nhưng tôi phải giữ sự tập trung và không thể chỉ chấp nhận những gì nó đưa cho.

Khi tôi làm việc trên một thứ mà tôi thậm chí còn không biết mình muốn gì, AI ở đâu đó giữa vô ích và có hại. Kiến trúc của dự án là trường hợp rõ ràng nhất: tôi đã dành nhiều tuần trong những ngày đầu làm theo AI đi vào ngõ cụt, khám phá các thiết kế có vẻ hiệu quả tại thời điểm đó nhưng lại sụp đổ khi bị soi xét. Nhìn lại, tôi phải tự hỏi liệu việc suy nghĩ thông qua mà không có AI trong vòng lặp có nhanh hơn không.

Nhưng chỉ có chuyên môn là chưa đủ. Ngay cả khi tôi hiểu sâu sắc một vấn đề, AI vẫn gặp khó khăn nếu nhiệm vụ không có câu trả lời có thể kiểm chứng khách quan38. Việc triển khai có một câu trả lời đúng, ít nhất là ở cấp độ cục bộ: mã biên dịch, các bài kiểm tra vượt qua, kết quả đầu ra khớp với những gì bạn yêu cầu. Thiết kế thì không. Chúng ta vẫn tranh cãi về OOP nhiều thập kỷ sau khi nó ra đời.

Cụ thể, tôi nhận thấy rằng việc thiết kế API công khai của syntaqlite là nơi điều này ảnh hưởng nặng nề nhất. Tôi đã dành nhiều ngày vào đầu tháng 3 chỉ để tái cấu trúc API, tự mình sửa những thứ mà bất kỳ kỹ sư có kinh nghiệm nào cũng sẽ tránh một cách bản năng nhưng AI lại làm rối tung lên. Không có bài kiểm tra hay thước đo khách quan nào cho "API này có dễ sử dụng không" và "API này có giúp người dùng giải quyết các vấn đề của họ không" và đó chính xác là lý do tại sao các tác nhân mã lại làm việc tệ hại như vậy.

Điều này đưa tôi trở lại những ngày tôi ám ảnh với vật lý và đặc biệt là thuyết tương đối. Các định luật vật lý trông đơn giản và kiểu Newton trong bất kỳ khu vực cục bộ nhỏ nào, nhưng khi bạn nhìn ra xa, không thời gian sẽ cong theo những cách mà bạn không thể dự đoán chỉ từ bức tranh cục bộ. Mã cũng tương tự: ở cấp độ của một hàm hoặc một lớp, thường có một câu trả lời đúng rõ ràng, và AI rất xuất sắc ở đó. Nhưng kiến trúc là những gì xảy ra khi tất cả các phần cục bộ đó tương tác, và bạn không thể có được hành vi toàn cục tốt bằng cách ghép các thành phần đúng cục bộ với nhau.

Tôi nghĩ rằng việc biết bạn đang ở đâu trên các trục này tại bất kỳ thời điểm nào là kỹ năng cốt lõi để làm việc hiệu quả với AI.

Tổng kết

Tám năm là một khoảng thời gian dài để mang một dự án trong đầu. Việc nhìn thấy các công cụ SQLite này thực sự tồn tại và hoạt động sau chỉ ba tháng làm việc là một chiến thắng lớn, và tôi hoàn toàn nhận thức được rằng chúng sẽ không có ở đây nếu không có AI.

Nhưng quá trình này không phải là câu chuyện thành công sạch sẽ, tuyến tính mà mọi người thường đăng tải. Tôi đã mất cả tháng cho việc lập trình theo cảm tính. Tôi đã rơi vào bẫy quản lý một cơ sở mã mà tôi thực sự không hiểu, và tôi đã phải trả giá bằng việc viết lại hoàn toàn.

Bài học rút ra cho tôi rất đơn giản: AI là một công cụ khuếch đại sức mạnh tuyệt vời cho việc triển khai, nhưng nó là một sự thay thế nguy hiểm cho thiết kế. Nó xuất sắc trong việc cung cấp cho bạn câu trả lời đúng cho một câu hỏi kỹ thuật cụ thể, nhưng nó không có ý thức về lịch sử, sở thích, hoặc cách con người thực sự cảm thấy khi sử dụng API của bạn. Nếu bạn dựa vào nó cho "linh hồn" phần mềm của mình, bạn sẽ chỉ kết thúc bằng việc đụng tường nhanh hơn bao giờ hết.

Điều tôi muốn thấy nhiều hơn từ những người khác chính là những gì tôi đã cố gắng làm ở đây: những báo cáo trung thực, chi tiết về việc xây dựng phần mềm thực tế với các công cụ này; không phải đồ chơi cuối tuần hay các script dùng một lần mà là loại phần mềm phải tồn tại khi tiếp xúc với người dùng, các báo cáo lỗi và chính sự thay đổi suy nghĩ của bạn.

Tác giả: brilee

#discussion