Định nghĩa hợp đồng dữ liệu vượt ngoài kiểu cột
Kiểm tra đơn vị, phạm vi, độ đầy đủ của lô và danh tính lần chạy trước khi tính thời gian tác vụ, đồng thời giữ đúng nghĩa kết quả rỗng.

Kiểu của cột cho biết biểu diễn được những giá trị nào. Hợp đồng dữ liệu còn nói giá trị có nghĩa gì, quan sát nào thuộc tập dữ liệu, khi nào tập đã đầy đủ và bên sử dụng phải xử lý ra sao nếu lời hứa không đạt. Hai bản xuất có thể có các cột giống hệt nhưng phục vụ những báo cáo khác nhau, không tương thích.
Nếu bạn là lập trình viên hoặc người phân tích chuẩn bị báo cáo định kỳ, hãy bắt đầu từ quyết định mà báo cáo phục vụ. Ví dụ này tính thời gian thực thi trung bình của các lần chạy tác vụ kết thúc thành công trong một ngày UTC. Người đọc cần biết Python cơ bản, dòng dữ liệu, định danh và trung bình. Lỗi đáng chú ý không phải con số sai cú pháp, mà là trung bình có vẻ hợp lý được tính từ sai tập đối tượng hoặc đơn vị.
Định nghĩa quan sát trước khi liệt kê cột
Một dòng đại diện cho một lần thực thi đã kết thúc thành công. Bên tạo dữ liệu gán run_id ổn định, kể cả khi tác vụ lớn hơn được thử lại. Lần thử lại có danh tính thực thi khác. Ngày là ngày kết thúc theo UTC; duration_ms là thời gian thực thi đã trôi qua, loại thời gian xếp hàng trước lúc khởi chạy. Các định nghĩa ấy phân biệt chỉ số với thời gian hoàn tất yêu cầu người dùng hoặc thời gian chờ worker.
Bên tạo dữ liệu phải lọc lấy các lần thực thi thành công trước khi xuất. Các dòng này không có trường trạng thái thành công, nên một lần chạy thất bại được xuất đúng hình dạng vẫn vượt qua bước kiểm tra phía bên sử dụng bên dưới. Hãy đối chiếu bộ lọc của bên tạo với trạng thái nguồn hoặc các lần chạy thành công và thất bại được kiểm soát; kiểm tra dòng phía bên sử dụng không xác nhận được việc chọn đúng tập đối tượng ấy.
Schema từng dòng có thể yêu cầu mã không rỗng, ngày và thời lượng nguyên không âm. Tài liệu đối tượng JSON Schema giải thích properties, trường bắt buộc và kiểm soát thuộc tính bổ sung. Những quy tắc đó mô tả được hình dạng dòng được nhận. Kiểm tra riêng từng dòng chưa xác lập mọi phân vùng nguồn mong đợi đã tới hoặc mỗi lần thực thi chỉ xuất hiện một lần trong cả lô.
Open Data Contract Standard tổ chức nội dung vượt ra ngoài schema: có chất lượng dữ liệu, nhóm phụ trách, hỗ trợ và thỏa thuận mức dịch vụ. Tiêu chuẩn giúp ghi những thỏa thuận này nhất quán. Đối tượng nhỏ và bước chặn dưới đây là định dạng minh họa tự xây, không triển khai tiêu chuẩn ấy và không tuyên bố tuân thủ schema của nó.
Khai báo kỳ vọng đầy đủ độc lập cho lô
Giả sử phạm vi báo cáo ngày 1 tháng 10 năm 2026 yêu cầu hai phân vùng tạo dữ liệu, worker-a và worker-b. Tập mong đợi đến từ hợp đồng báo cáo. Không được suy nó từ những phân vùng tình cờ tải lên thành công. Lô giả lập có một lần thực thi đã hoàn tất từ mỗi worker:
from fractions import Fraction
batch = {
"contract": "run-duration/v1",
"day": "2026-10-01",
"unit": "ms",
"partitions": {
"worker-a": {"complete": True, "rows": [
{"run_id": "r1", "day": "2026-10-01", "duration_ms": 1200}
]},
"worker-b": {"complete": True, "rows": [
{"run_id": "r2", "day": "2026-10-01", "duration_ms": 800}
]},
},
}
Phân vùng đầy đủ với danh sách dòng rỗng nghĩa là bên tạo dữ liệu báo không có lần thực thi đủ điều kiện. Phân vùng bị thiếu nghĩa là chưa có kết quả của nó. Phân vùng có mặt nhưng đánh dấu chưa đầy đủ nghĩa là vẫn có thể còn dòng tới sau. Không nên biến cả ba trạng thái thành cùng danh sách rỗng lúc nhập, vì báo cáo cần kết luận khác nhau từ chúng.
Biến điều kiện công bố thành mã có thể chạy
Hàm sau kiểm tra envelope đã giải mã, với các mapping bên ngoài và danh sách dòng của phân vùng đã qua kiểm tra cấu trúc. Nó không phải bộ phân tích JSON tổng quát. Bên gọi cung cấp ngày báo cáo chuẩn cùng tập phân vùng bắt buộc đáng tin. Hàm kiểm tra hợp đồng được khai báo, đơn vị, độ phủ, hình dạng dòng và danh tính giữa các phân vùng trước khi tính trung bình.
def summarize(batch, expected_day, required_partitions):
if batch["contract"] != "run-duration/v1":
raise ValueError("unsupported contract")
if batch["unit"] != "ms":
raise ValueError("unexpected duration unit")
if batch["day"] != expected_day:
raise ValueError("wrong reporting day")
parts = batch["partitions"]
if set(parts) != set(required_partitions):
raise ValueError("unexpected partition set")
seen, durations = set(), []
for name in sorted(required_partitions):
part = parts[name]
if part["complete"] is not True:
raise ValueError("incomplete partition")
for row in part["rows"]:
if type(row) is not dict or set(row) != {"run_id", "day", "duration_ms"}:
raise ValueError("unexpected row shape")
if type(row["run_id"]) is not str or not row["run_id"]:
raise ValueError("invalid execution identity")
value = row["duration_ms"]
if type(value) is not int or value < 0:
raise ValueError("invalid duration")
if row["day"] != expected_day:
raise ValueError("execution outside reporting day")
if row["run_id"] in seen:
raise ValueError("duplicate execution identity")
seen.add(row["run_id"])
durations.append(value)
count = len(durations)
mean = Fraction(sum(durations), count) if count else None
return {"executions": count, "mean_ms": mean}
print(summarize(batch, "2026-10-01", {"worker-a", "worker-b"}))
Kết quả là hai lần thực thi và trung bình chính xác 1.000 mili giây. Kiểm tra từ chối thời lượng Boolean dù Python coi bool là kiểu con của int. Nó cũng từ chối trường dòng ngoài dự kiến theo hợp đồng dòng đóng có chủ ý này. Không hành vi nào là yêu cầu chung cho mọi tập dữ liệu; cả hai là lựa chọn rõ để bên sử dụng có thể kiểm tra.
Trên bản sao mới, xóa worker-b. Dòng còn lại hợp lệ riêng lẻ nhưng kiểm tra tập phân vùng từ chối cả lô. Thay vào đó đánh dấu worker-b chưa hoàn tất, kiểm tra đầy đủ sẽ từ chối. Dùng lại r1 làm danh tính thực thi của B, kiểm tra duy nhất giữa phân vùng sẽ từ chối. Các lỗi cần cách sửa khác nhau: lấy phân vùng còn thiếu, chờ nó hoàn tất hoặc giải quyết danh tính nguồn bị trùng.
Giữ kết quả rỗng hợp lệ
Bây giờ giữ cả hai phân vùng đầy đủ nhưng thay các dòng của B bằng danh sách rỗng. Kết quả có một lần thực thi với trung bình 1.200 mili giây. Nó khác với thiếu worker một cách hợp lệ, vì bên tạo dữ liệu đã đưa ra tuyên bố rõ rằng B không có lần thực thi đủ điều kiện theo hợp đồng.
Nếu cả hai phân vùng đầy đủ và rỗng, kết quả là không lần thực thi và mean None. Trung bình của không quan sát không được xác định; công bố không mili giây sẽ khẳng định một kết quả hiệu năng đã được quan sát nhưng thực tế chưa có. Lưu số lần chạy bên cạnh trung bình để bên sử dụng phân biệt với những lần thực thi thật có thời lượng bằng không.
Bước chặn giả định tuyên bố đầy đủ là đúng. Nó không chứng minh worker đã tải mọi lần chạy thành công chỉ bằng cách đọc complete=True. Bên tạo dữ liệu cần đối soát con trỏ nguồn, chốt cửa sổ trích xuất hoặc có cơ chế hoàn tất khác được ghi rõ. Bên sử dụng kiểm tra được tuyên bố cùng phạm vi mong đợi đã cung cấp; bằng chứng nguồn độc lập phải hỗ trợ bản thân tuyên bố ấy.
Coi thay đổi ý nghĩa là thay đổi hợp đồng
Đổi unit thành giây sẽ bị từ chối dù mọi thời lượng vẫn là số nguyên. Giữ nhãn ms nhưng gửi số giây sẽ vượt qua kiểm tra này, nên siêu dữ liệu đơn vị cần thiết nhưng chưa đủ. Dùng trường hợp tích hợp có đầu vào đã biết và kiểm tra cách đo phía nguồn để xác nhận chuyển đổi. Nhãn hợp đồng không phải phép đo vật lý.
Tương tự, cộng thời gian xếp hàng làm đổi ý nghĩa chỉ số mà không đổi kiểu hay tên trường. Hãy công bố hợp đồng sửa đổi cùng quyết định chuyển đổi của bên sử dụng, thay vì âm thầm đổi báo cáo cũ. Bước chặn v1 từ chối mã hợp đồng khác; nó không tự thương lượng phiên bản hoặc xác lập tương thích cho mọi bên sử dụng còn lại.
Bên tạo dữ liệu bổ sung mã truy vết tùy chọn cũng sẽ không qua hình dạng dòng đóng này. Bên sử dụng chủ ý cho phép trường mở có thể nhận bổ sung ấy theo quy tắc khác. Ghi rõ có dung nạp trường mới không và kiểm tra hành vi bên sử dụng thực tế. Nói “tương thích schema” mà không nêu bên sử dụng cùng quy tắc của họ quá mơ hồ để quyết định thay đổi có phù hợp không.
Gắn lỗi kiểm tra với cách xử lý vận hành
Quyết định điều gì xảy ra khi bước chặn thất bại. Báo cáo minh họa này không công bố trung bình thay thế từ lô bị từ chối. Sản phẩm có thể giữ báo cáo thành công gần nhất trên giao diện, nhưng cần giữ ngày và trạng thái độ mới của báo cáo đó. Dùng lại số hôm qua dưới nhãn hôm nay sẽ biến lô chưa đầy đủ được báo trung thực thành kết quả hiện tại sai.
Gán người phụ trách ở cả bên tạo và bên sử dụng, kỳ vọng giao dữ liệu cùng đường xử lý lô bị từ chối. Mã này không cưỡng chế hạn giao theo đồng hồ hoặc gửi thông báo cho người phụ trách. Đó là những phần vận hành bổ sung của hợp đồng, cần kiểm tra quan sát được riêng. Lưu phiên bản đầu vào đã chọn và kết quả xác minh để đối chiếu lần thử lại với lần thất bại.
Để thực hành, tạo lại dữ liệu gốc riêng cho từng thay đổi: thiếu B, B chưa đầy đủ, run_id trùng, sai đơn vị và một dòng thuộc ngày 30 tháng 9. Sau đó kiểm tra B đầy đủ nhưng rỗng, rồi cả A và B đầy đủ nhưng rỗng. Dự đoán báo cáo sẽ bị từ chối, có một lần thực thi hay có trung bình không xác định trước khi chạy hàm. Hợp đồng hữu ích giúp cả bên tạo và bên sử dụng dự đoán những khác biệt đó, đồng thời giữ các giả định còn lại nhìn thấy được.