~70%
Giảm ~70% lượng token so với cách viết code trực tiếp bằng AI
Đang khởi tạo pipeline Contract Coding...
Contract là nguồn sự thật duy nhất. Code được sinh ra một cách nhất quán và có thể kiểm soát.
Contract Coding không đơn thuần là AI coding. Đây là phương pháp phát triển phần mềm nơi contract đóng vai trò source of truth, mọi thay đổi đều bắt đầu từ contract, sau đó được biên dịch thành code có thể lặp lại và truy vết.
Contract Coding là một phương pháp phát triển phần mềm có AI hỗ trợ, trong đó contract đóng vai trò như một lớp đặc tả có cấu trúc nằm giữa yêu cầu và mã nguồn. Thay vì để AI chỉnh sửa trực tiếp codebase, mọi thay đổi đều đi qua contract — nơi chúng được kiểm soát, biên dịch và tạo ra code theo một pipeline nhất quán.
Cách tiếp cận này giúp việc phát triển với AI trở nên dễ review, dễ truy vết và ổn định hơn — đặc biệt khi hệ thống ngày càng phức tạp, có nhiều module, nhiều quy tắc và nhiều người cùng tham gia.
Tìm hiểu sâu hơn về Contract Coding →Giảm ~70% lượng token so với cách viết code trực tiếp bằng AI
Giảm ~90% số lần prompt - chỉnh sửa - chạy lại
Hoạt động ổn định ngay cả khi hệ thống trở nên phức tạp
Mọi thay đổi đều bám theo contract, dễ review và truy vết
Khác biệt nằm ở nơi tạo ra thay đổi, cách thay đổi đi vào codebase và mức độ kiểm soát khi hệ thống mở rộng.
| Tiêu chí | Vibe Coding | Contract Coding |
|---|---|---|
| Nguồn điều khiển | Prompt + thao tác trực tiếp trên code | Contract là nguồn sự thật duy nhất |
| Cách tạo thay đổi | Prompt -> thay đổi trực tiếp vào codebase | Contract -> IR -> compiler -> code (theo pipeline kiểm soát) |
| Khả năng lặp lại | Phụ thuộc vào prompt, kết quả dễ thay đổi mỗi lần sinh | Đầu ra ổn định khi contract và pipeline không đổi |
| Khả năng truy vết | Khó truy vết về ý định ban đầu | Truy vết rõ ràng qua contract, version và rule liên quan |
Ba vấn đề xuất hiện rất sớm khi prompt và việc chỉnh sửa trực tiếp code trở thành trung tâm của quy trình.
Khi thay đổi bắt đầu từ prompt và chỉnh sửa rải rác trong nhiều file, team dần không còn rõ đâu là quy tắc gốc cần duy trì.
Khi chỉnh sửa trực tiếp vào code, AI dễ vượt qua ranh giới giữa các module, khiến kiến trúc hệ thống dần lệch khỏi thiết kế ban đầu.
Pull Request có thể vẫn chạy, nhưng team khó hiểu vì sao thay đổi xuất hiện, đến từ quyết định nào và ảnh hưởng đến đâu.
Mọi thay đổi bắt đầu từ mô tả rõ ràng về hành vi hệ thống, được chuẩn hóa thành contract, rồi đi qua pipeline biên dịch trước khi đi vào codebase.
AI, developer hoặc team viết mô tả rõ ràng về hành vi hệ thống — bao gồm yêu cầu, quy tắc và ý định cần triển khai.
Midi Coder chuyển mô tả này thành contract có cấu trúc — đóng vai trò lớp điều khiển chính cho hệ thống.
Contract đi qua pipeline biên dịch để tạo ra code nhất quán, có thể lặp lại và kiểm soát được.
Code được đưa vào codebase thông qua pipeline, thay vì để AI chỉnh sửa trực tiếp từng file.
Một contract thực tế thường gồm nhiều file, nhiều layer và nhiều artifact liên quan.
routes: - method: POST path: /api/v1/matches command: CreateMatch description: Create a new match and enter matchmaking queue auth: jwt request_schema: - name: user_id type: string required: true response_schema: - name: match_id type: string required: true tags: - matchmaking - method: POST path: /api/v1/matches/{id}/move command: MakeMove description: Make a move in an active match auth: jwt request_schema: - name: move type: string required: true description: Chess move notation response_schema: - name: game_state type: json required: true description: Updated game state after move tags: - gameplay - method: POST path: /api/v1/matches/{id}/resign command: ResignMatch description: Resign from current match auth: jwt request_schema: - name: user_id type: string required: true response_schema: - name: result type: string required: true tags: - gameplay - method: GET path: /api/v1/matches/{id} query: GetMatch description: Get match details by ID auth: jwt response_schema: - name: match_id type: string required: true - name: player_white type: string required: true - name: player_black type: string required: true - name: status type: string required: true - name: result type: string required: false tags: - matches - method: GET path: /api/v1/users/{user_id}/matches query: GetUserMatches description: Get all matches for a user auth: jwt response_schema: - name: matches type: list<json> required: true tags: - matchescommands: - id: CreateMatch description: Create a new match and add to matchmaking queue input: - name: user_id type: uuid required: true returns: - name: match_id type: uuid effects: - id: db.insert params: table: matches - id: emit.event params: event: MatchCreated writes_to: - matches emits: - MatchCreated transaction: true - id: MakeMove description: Execute a chess move in an active match input: - name: match_id type: uuid required: true - name: move type: string required: true description: Chess move in algebraic notation returns: - name: fen type: string description: New board state in FEN notation guards: - id: exists params: entity: Match - id: state.equals params: entity: Match field: status value: PLAYING effects: - id: db.insert params: table: moves - id: db.update params: table: matches - id: emit.event params: event: MoveMade errors: - InvalidMoveError - NotYourTurnError - MatchNotFoundError - MatchAlreadyFinishedError writes_to: - moves - matches emits: - MoveMade transaction: true - id: ResignMatch description: Resign from an active match input: - name: match_id type: uuid required: true - name: user_id type: uuid required: true returns: - name: result type: string guards: - id: exists params: entity: Match - id: state.equals params: entity: Match field: status value: PLAYING effects: - id: db.update params: table: matches - id: emit.event params: event: MatchFinished writes_to: - matches emits: - MatchFinished transaction: truequeries: - id: GetMatch description: Retrieve match details by match ID input: - name: match_id type: uuid required: true returns: - name: id type: uuid - name: player_white type: uuid - name: player_black type: uuid - name: status type: string - name: result type: string reads_from: - matches category: detail - id: GetUserMatches description: Retrieve list of matches for a specific user input: - name: user_id type: uuid required: true returns: - name: matches type: list<uuid> reads_from: - matches category: listentities: - id: User description: Chess player account fields: - name: id type: uuid required: true - name: username type: string required: true - name: rating type: int required: true description: Elo rating for matchmaking - name: status type: string required: true primary_key: id indexes: - name: idx_username fields: - username unique: true - id: Match description: A chess match between two players fields: - name: id type: uuid required: true - name: player_white type: uuid required: true description: User ID playing white pieces - name: player_black type: uuid required: true description: User ID playing black pieces - name: status type: string required: true description: Match status - WAITING, PLAYING, FINISHED - name: result type: string required: false description: Game result - WHITE_WIN, BLACK_WIN, DRAW primary_key: id indexes: - name: idx_player_white fields: - player_white - name: idx_player_black fields: - player_black - id: Move description: A single move in a chess match fields: - name: match_id type: uuid required: true - name: move_number type: int required: true - name: notation type: string required: true description: Chess move notation - name: timestamp type: datetime required: true indexes: - name: idx_match_id fields: - match_id - id: GameState description: Current state of the chess board fields: - name: match_id type: uuid required: true - name: fen type: string required: true description: FEN notation of board state - name: turn type: string required: true description: Whose turn it is primary_key: match_idContract trở thành nơi thống nhất yêu cầu, quy tắc và cấu trúc — thay vì để tri thức bị phân tán giữa prompt, tài liệu rời và code sửa tay.
Cùng một contract và pipeline luôn tạo ra kết quả giống nhau, giúp giảm sai lệch qua mỗi lần thay đổi hoặc triển khai.
Mỗi thay đổi đều có thể lần ngược về contract, version và quyết định liên quan — không chỉ dừng ở diff của code.
Những phần do contract quản lý không bị chỉnh sửa thủ công, giúp giảm lệch cấu trúc và giữ hệ thống ổn định theo thời gian.
Contract Coding phát huy hiệu quả nhất khi hệ thống có quy tắc rõ ràng, lặp lại nhiều và cần giữ đầu ra nhất quán theo thời gian.
Phù hợp khi team cần tạo nhiều endpoint, DTO, validation, service… theo cùng một pattern và cấu trúc.
Phù hợp với các luồng như phê duyệt, xử lý hồ sơ, hoặc điều phối công việc — nơi mỗi bước và trạng thái đều cần được kiểm soát.
Phù hợp khi codebase có nhiều phần giống nhau về pattern, naming, boundary và cách tổ chức implementation.
Phù hợp khi team muốn contract, tài liệu và code luôn bám theo cùng một nguồn sự thật — không bị lệch theo thời gian.
Không chỉ sinh code, Midi Coder giúp chuẩn hóa ý định, kiểm soát thay đổi và cộng tác ổn định quanh contract.
Giữ quyền kiểm soát model, usage và môi trường chạy ngay từ lớp hạ tầng.
Sử dụng API key riêng để kiểm soát model, usage và chi phí theo chính sách nội bộ.
Mỗi tenant chạy trên hạ tầng riêng, đảm bảo tách biệt, ổn định và dễ quản trị.
Quản trị team, vai trò và ngữ cảnh để đầu ra giữ được tính nhất quán.
Quản lý tổ chức, thành viên, vai trò và quyền truy cập theo team, môi trường hoặc dự án.
Lưu và tái sử dụng ngữ cảnh theo tổ chức hoặc dự án, giúp đầu ra luôn nhất quán.
Kiểm soát thay đổi trước khi đầu ra đi vào repo thật.
So sánh khác biệt giữa các version contract để kiểm soát thay đổi ở mức ý định.
Quản lý thay đổi qua quy trình review, approval và merge trước khi áp vào codebase.
Tự động phát hiện và xử lý các vấn đề phổ biến trước khi code được áp vào hệ thống.
Cho nhiều người cùng review, phản hồi và chốt kết quả trong một flow thống nhất.
Môi trường cộng tác để nhiều người cùng làm việc trên contract, code và quy trình review.
Xem trước kết quả cuối và thu thập phản hồi trực tiếp trước khi triển khai.
Các năng lực đang được mở rộng để đưa Contract Coding đi xa hơn trong quy mô team và product workflow.
Những câu hỏi thường gặp khi bắt đầu với Contract Coding.
Không. Contract Coding thay đổi cách team dùng AI: AI hỗ trợ tạo và cập nhật contract, còn code được sinh qua pipeline có kiểm soát trước khi vào codebase.
Có. Team nhỏ vẫn dùng tốt nếu bài toán có cấu trúc lặp lại và cần giữ thay đổi dễ review. Không cần đợi đến khi hệ thống lớn mới bắt đầu.
Nên bắt đầu từng phần. Chọn khu vực có rule rõ, chuyển thành contract và để pipeline xử lý trước, rồi mở rộng dần sang phần khác.
Không. Homepage và guide là đủ để hiểu flow cơ bản. Tài liệu sâu hơn chỉ cần khi team muốn thiết kế contract và pipeline chi tiết.
Vì mọi thay đổi đều đi qua contract, version và pipeline trước khi vào codebase. Team không chỉ thấy diff cuối, mà còn hiểu được vì sao thay đổi xảy ra.
Không. Bạn có thể áp dụng từng phần, giữ quy trình hiện tại ở nơi chưa phù hợp và mở rộng dần khi team đã quen.
Đưa AI vào phát triển phần mềm với nguồn sự thật rõ ràng, code nhất quán và thay đổi luôn trong kiểm soát.
Cộng đồng nói gì về Midi Coder
Những phản hồi từ team đang sử dụng Contract Coding trong thực tế.
"Giá trị nhất là team có một nguồn chuẩn để review thay đổi, thay vì chỉ nhìn diff code cuối cùng."
Tech Lead, SaaS (50+ services)
"Contract giúp product và engineering nói chuyện với nhau rõ ràng hơn, mà vẫn giữ được flow tự động hóa."
Product Owner, Internal Platform Team
"Khi mọi thay đổi đi qua contract, việc review dễ thảo luận hơn rất nhiều so với prompt rời và code sửa tay."
Engineering Manager, Fintech (Series B)