Kho mã của bạn chưa bao giờ là toàn bộ câu chuyện

Mã nguồn cho thấy những gì đang tồn tại. Còn lý do nằm rải rác trong đặc tả, sự cố, dữ liệu và các quyết định.

Kho mã của bạn chưa bao giờ là toàn bộ câu chuyện

Mở một repository sau sáu tháng kể từ khi một tính năng được phát hành, bạn vẫn có thể tái dựng được rất nhiều. Bạn có thể lần theo kiến trúc, kiểm tra schema, đọc test và thấy chính xác những dòng nào đã thay đổi.

Điều bạn thường không thể tái dựng lại là cuộc trao đổi đã khiến những dòng mã đó trở nên cần thiết.

Mã nguồn sẽ không cho bạn biết rằng một quy tắc kiểm tra hợp lệ tồn tại vì có một khách hàng gửi các bản export bị lỗi định dạng. Nó sẽ không giải thích rằng một chính sách retry kỳ lạ đang ngăn các giao dịch bị trùng lặp trong một hệ thống downstream. Nó sẽ không cho thấy rằng giao diện gọn gàng hơn đã bị bác bỏ sau một bài kiểm tra khả năng truy cập, hay rằng ranh giới dịch vụ phản ánh một ràng buộc hợp đồng chứ không phải một ưu tiên kỹ thuật.

Git rất xuất sắc trong việc lưu giữ lịch sử mã nguồn. Nó chỉ lưu giữ được chủ đích khi cả nhóm chủ động ghi lại chủ đích đó và giữ nó gắn với phần triển khai.

Khoảng trống đó từ lâu đã là một phần của kỹ nghệ phần mềm. Các công cụ lập trình AI khiến nó lộ rõ hơn. Một hệ thống có thể đọc mọi tệp trong repository, lần theo mọi symbol và tạo ra một bản vá thuyết phục về mặt kỹ thuật nhưng vẫn giải quyết sai vấn đề.

Vấn đề không phải là mã nguồn gây hiểu lầm. Mã nguồn chỉ đang trả lời một câu hỏi hẹp hơn.

Năm lớp sự thật trong kỹ thuật

Hầu hết những thay đổi phần mềm thực sự có ý nghĩa đều phụ thuộc vào năm lớp bằng chứng khác nhau.

  1. Chủ đích — Người dùng, khách hàng hoặc doanh nghiệp đang yêu cầu kết quả gì? Điều này có thể nằm trong đặc tả, ticket, cuộc trao đổi với bộ phận hỗ trợ hoặc ghi chú cuộc họp.
  2. Ràng buộc — Điều gì tuyệt đối không được hỏng? Các cam kết tương thích, ranh giới bảo mật, quy định, hợp đồng, ngân sách và thời hạn thường nằm ngoài repository.
  3. Triển khai — Hệ thống đang hoạt động như thế nào ở thời điểm hiện tại? Mã nguồn, test, schema, dependency và cấu hình triển khai tạo nên lớp này.
  4. Bằng chứng khi chạy thực tế — Điều gì đang xảy ra trong hệ thống thực? Log, trace, metric, dữ liệu production và báo cáo sự cố có thể mâu thuẫn với những giả định trông có vẻ hợp lý trong mã nguồn.
  5. Lịch sử quyết định — Vì sao cách tiếp cận hiện tại lại được chọn? Pull request, thảo luận thiết kế, các phương án đã bị bác bỏ và những sự cố trước đó chứa câu trả lời.

Repository mạnh nhất ở lớp thứ ba. Nó có chứa một phần của các lớp còn lại, nhưng hiếm khi đủ để đại diện cho chúng một cách trọn vẹn.

Điều này quan trọng vì các thất bại phần mềm thường xuất hiện ở ranh giới giữa các lớp. Phần triển khai khớp với một đặc tả đã lỗi thời. Bản sửa đáp ứng ticket nhưng lại vi phạm một ràng buộc vận hành. Test vượt qua vì chúng mã hóa những giả định của ngày hôm qua. Mã nguồn nhất quán về mặt nội bộ trong khi dữ liệu production lại đi theo một mẫu mà không ai từng ghi lại.

Một bản vá đúng ở phạm vi cục bộ vẫn có thể là thay đổi sai.

Những điều mà riêng kho mã nguồn không thể tự trả lời

Hãy hình dung một người dùng chỉnh sửa một tài liệu rồi tìm kiếm câu đã được cập nhật, nhưng kết quả vẫn hiển thị phiên bản cũ. “Hãy để tìm kiếm cập nhật ngay lập tức” nghe có vẻ là một yêu cầu rất rõ ràng. Kho mã nguồn cho thấy một số điểm có thể bắt đầu điều tra, nhưng tự nó không thể xác định đâu là cách sửa đúng.

Câu hỏi Nguồn có khả năng chứa câu trả lời
Phiên bản nào của tài liệu là nguồn xác thực? Tài liệu gốc và lịch sử sửa đổi
Đoạn văn bản cũ còn tồn tại ở đâu? Nhật ký đồng bộ, đầu ra trích xuất, chỉ mục tìm kiếm hoặc bộ nhớ đệm
“Ngay lập tức” có nghĩa là gì đối với sản phẩm này? Cam kết sản phẩm hoặc mục tiêu dịch vụ
Quyền truy cập của tài liệu có thay đổi cùng với nội dung không? Quyền trên nguồn và lịch sử kiểm toán
Kết quả lỗi thời này chỉ giới hạn ở một người dùng, một nguồn hay một khu vực không? Dấu vết yêu cầu và số liệu production

Mã tìm kiếm có thể giải thích cách kết quả được trả về. Nhưng nó không thể cho bạn biết liệu lỗi thực sự là do độ trễ đồng bộ, trích xuất lỗi thời, vô hiệu hóa bộ nhớ đệm, lan truyền quyền truy cập, hay một kỳ vọng mà sản phẩm chưa từng định nghĩa.

Sự phân biệt này càng trở nên quan trọng hơn trong các hệ thống đã trưởng thành. Một trường dữ liệu trông có vẻ lỗi thời vẫn có thể đang phục vụ một client cũ. Một dịch vụ trông như bị trùng lặp có thể đang tách dữ liệu với các yêu cầu quyền truy cập khác nhau. Một bước kiểm tra có vẻ quá mức có thể là dấu vết duy nhất ở cấp độ mã của một sự cố production mà đội ngũ hiện tại chưa từng chứng kiến.

Loại bỏ sự phức tạp là điều có giá trị. Loại bỏ lịch sử được ngụy trang thành sự phức tạp thì rất tốn kém.

Nhiều ngữ cảnh hơn vẫn có thể dẫn đến câu trả lời sai

Giải pháp hiển nhiên là cung cấp cho AI nhiều tài liệu hơn: toàn bộ kho mã nguồn, mọi ticket, mọi tài liệu, mọi tin nhắn và mọi nhật ký.

Điều đó tạo ra quyền truy cập, chứ không tạo ra sự hiểu biết.

Các nguồn có thể đã lỗi thời, mâu thuẫn, mang tính suy đoán, hoặc được viết cho những đối tượng khác nhau. Một buổi brainstorm không nên được coi trọng hơn một đặc tả đã được phê duyệt. Một yêu cầu từ sáu tháng trước không nên âm thầm ghi đè quyết định sản phẩm của ngày hôm qua. Một nhật ký production phải được gắn với bản phát hành, môi trường và luồng mã đã tạo ra nó. Một yêu cầu của khách hàng không nên bị xem như yêu cầu phổ quát nếu chưa kiểm tra phạm vi áp dụng.

Vì vậy, một hệ thống ngữ cảnh nghiêm túc cần nhiều hơn là truy xuất. Nó cần một cách để suy luận về:

  • Thẩm quyền: Nguồn nào được phép xác định yêu cầu?
  • Tính cập nhật: Thông tin nào là hiện hành, và thông tin nào đã bị thay thế?
  • Nguồn gốc: Mỗi khẳng định, ràng buộc hoặc kết luận đến từ đâu?
  • Mối quan hệ: Vấn đề, bản phát hành, khách hàng, tập dữ liệu và luồng mã nào thuộc về nhau?
  • Quyền truy cập: Những nguồn nào có thể được dùng cho tác vụ này và được hiển thị cho người này?

Ngữ cảnh không phải là một đống token. Nó là một đồ thị có thời gian, thẩm quyền và ranh giới.

Nhiều ngữ cảnh hơn phải tạo ra nhiều bằng chứng hơn, chứ không phải nhiều tự tin hơn mà không có bằng chứng.

Đơn vị công việc thực sự là thay đổi

Trình soạn thảo và các công cụ lập trình được tổ chức xoay quanh tệp vì tệp là thứ chúng ta chỉnh sửa. Các nhóm kỹ thuật được tổ chức xoay quanh thay đổi.

Một thay đổi bắt đầu từ một lý do. Nó trở thành một yêu cầu, chạm đến mã và dữ liệu, đi qua khâu review, đến production và tạo ra bằng chứng mới. Nếu các giai đoạn đó vẫn tách rời nhau, thì mọi tác vụ trong tương lai đều sẽ lại bắt đầu bằng thêm một vòng khảo cổ.

Một hệ thống AI làm việc với phần mềm thực tế nên đi theo vòng đời đó.

Trước khi triển khai, nó nên xác định yêu cầu, các ràng buộc liên quan và mọi nguồn mâu thuẫn. Nó nên biết liệu mình đang sửa một lỗi, thay đổi hành vi được kỳ vọng hay đưa vào một cam kết mới.

Trong khi triển khai, nó nên gắn mỗi lựa chọn có ý nghĩa với bằng chứng. Vì sao là module này? Vì sao là chiến lược migration này? Vì sao giữ lại nhánh này? Phần giải thích đó phải tồn tại được lâu hơn cuộc trò chuyện đã tạo ra đoạn mã.

Sau khi triển khai, hệ thống nên đính kèm kết quả xác minh, các quyết định khi rà soát và những ràng buộc mới được phát hiện vào thay đổi đó. Nếu không, người tiếp theo—hoặc phiên AI tiếp theo—sẽ phải khám phá lại chúng từ đầu.

Đó là khác biệt giữa một công cụ có thể chỉnh sửa repository và một hệ thống có thể tham gia vào công việc kỹ thuật.

AI nên giảm nhu cầu tái dựng bối cảnh, chứ không thay thế phán đoán

Bối cảnh tốt hơn đôi khi được xem là con đường dẫn tới phát triển phần mềm tự chủ. Nhưng giá trị trước mắt thì ít kịch tính hơn và hữu ích hơn: giảm chi phí tái dựng thực tế trước khi thực hiện một thay đổi.

AI có thể đưa yêu cầu ban đầu đặt cạnh phần mã liên quan. Nó có thể làm lộ ra sự cố giải thích cho một biện pháp bảo vệ bất thường. Nó có thể kết nối một chỉ số đang thất bại với bản phát hành đã làm thay đổi nó. Nó có thể cho thấy hai nguồn có thẩm quyền đang mâu thuẫn với nhau trước khi việc triển khai bắt đầu.

Những khả năng đó không loại bỏ phán đoán kỹ thuật. Chúng giúp phán đoán được đưa ra trên cơ sở đầy đủ thông tin hơn.

Con người vẫn phải quyết định đánh đổi nào là chấp nhận được, liệu một yêu cầu đã đầy đủ hay chưa, và một bản phát hành có thể mang theo mức rủi ro đến đâu. Hệ thống nên làm cho bằng chứng trở nên rõ ràng và lập luận có thể được kiểm tra. Nó không nên che giấu sự bất định đằng sau một bản vá được trau chuốt.

Tiêu chuẩn không phải là “nó có tạo ra được mã không?”

Tiêu chuẩn là “nó có thể giải thích vì sao đây là thay đổi đúng đắn vào lúc này không?”

Từ hiểu repository đến hiểu công việc

Các trợ lý lập trình ban đầu trở nên hữu ích nhờ hiểu được tệp ngay trước mắt nhà phát triển. Khả năng nhận biết repository là bước tiến lớn tiếp theo: tìm mã liên quan, lần theo các symbol và áp dụng thay đổi trên toàn bộ dự án.

Bước tiếp theo là nhận biết được công việc xoay quanh repository.

Điều đó có nghĩa là kết nối mã với đặc tả đã yêu cầu nó, cuộc trao đổi đã làm rõ nó, bằng chứng từ môi trường production đã thách thức nó, và quyết định cần được ghi nhớ về sau. Nó cũng có nghĩa là loại trừ những bối cảnh không liên quan, đã lỗi thời hoặc nằm ngoài quyền truy cập của người dùng.

Trong khi xây dựng Dvina, đây là một trong những ý tưởng mà chúng tôi liên tục quay lại. Công việc không diễn ra bên trong một tệp, một ứng dụng hay một cuộc trò chuyện đơn lẻ. Ý nghĩa nằm trong các kết nối giữa chúng và trong cách những kết nối đó thay đổi theo thời gian.

Repository vẫn là yếu tố cốt lõi. Nó là nguồn chân lý có thể thực thi cho hành vi của hệ thống. Chỉ là nó không phải nguồn chân lý đầy đủ cho ý định sản phẩm, thực tế vận hành hay ký ức của tổ chức.

Toàn bộ câu chuyện sẽ thay đổi thứ được xây dựng

Khi chỉ có mã, câu hỏi tự nhiên là:

Thay đổi nào phù hợp với hệ thống này?

Khi có bối cảnh rộng hơn, câu hỏi trở thành:

Thay đổi nào phù hợp với hệ thống này, yêu cầu này, lịch sử này và thời điểm này?

Câu hỏi thứ hai đó giúp nhận ra các ràng buộc trước khi chúng biến thành lỗi hồi quy. Nó cho người review thấy được lập luận đằng sau cách triển khai. Nó giúp các thành viên mới trong nhóm hiểu vì sao hệ thống lại trông như hiện tại. Nó trao cho AI một vai trò có cơ sở: không phải một nhà tiên tri trong trình soạn thảo, mà là một tác nhân có thể tập hợp bằng chứng xuyên suốt công việc.

Repo của bạn chưa bao giờ là toàn bộ câu chuyện.

Cơ hội ở đây là xây dựng những hệ thống có thể đọc được phần còn lại của câu chuyện đó—và cho thấy cách chúng đi đến kết luận.

Tham gia Dvina

Đăng ký miễn phí và đưa mọi công cụ của bạn vào một không gian làm việc đơn giản.

Khám phá thêm

Chúng tôi chỉ thu thập dữ liệu phân tích thiết yếu để đảm bảo dịch vụ vận hành trơn tru.