Bỏ qua tới nội dung
Kiên

Cái admin panel không ai đem đi demo

· 5 phút đọc

Dashboard ăn chính API của mình là bản review API nhanh nhất có thể có, và cái dạy được nằm ở chi tiết: một bảng mà mỗi dòng danh tính mang mấy chục cột supplier ID, ba lý do khác nhau khiến màn hình trống, một mã lỗi phải biến thành câu chữ người ta hành động được, và một màn hình tiền phải nói rõ số nào đang hiển thị và số nào bị trừ. Kèm phần nửa không ai lên kế hoạch — internal tool là một hệ thống production, người dùng ngồi ngay cạnh mình.

  • internal tool
  • API design
  • frontend
  • vận hành
Mục lục
  1. Một cái bảng phải hiện bốn mươi sáu cột
  2. Ba kiểu rỗng
  3. Một mã lỗi không phải là một câu
  4. Số nào đang hiện, số nào bị trừ
  5. Internal tool là một hệ thống production
  6. Vòng phản hồi không mua được
  7. Nợ đọng lại ở đâu

Internal tool được làm trong mấy khe thời gian. Không ai xếp lịch cho nó, không ai đem nó đi demo, và người dựng nó thường cũng chính là người viết cái API mà nó ăn vào. Cái vế cuối mới là chỗ thú vị: dựng cái dashboard là bản review nhanh nhất mà API của chính mình từng nhận được, và bản review đó đến bằng chi tiết chứ không bằng ý kiến.

"Tự ăn API của mình đi" là lời khuyên nghe như đã đủ, mà chưa đủ. Nên đây là phần chi tiết: bốn cái màn hình, mỗi cái dạy mình một thứ mà ngồi ở backend không thấy được.

Một cái bảng phải hiện bốn mươi sáu cột

Dữ liệu danh tính khách sạn là một bảng rất rộng: khoảng 1,9 triệu dòng, chừng bốn mươi sáu cột supplier ID, vì cùng một toà nhà mang một định danh khác nhau ở mỗi supplier. Người vận hành cần nhìn một dòng trong đó. Vẽ nó ra là mấy câu hỏi thiết kế API ập tới cùng lúc.

Không thể trả về hết cột, nên endpoint cần chọn cột — mà một khi có chọn cột thì client đang tự chọn một phần hình dạng response, nghĩa là response phải đủ tự mô tả để cái bảng render được bất cứ thứ gì nó nhận. Cũng không thể trả về hết dòng, nên phải phân trang — mà phân trang theo offset trên một bảng rộng như thế, lọc theo một cột không index mà ai đó vừa thêm vào thanh filter cho tiện, là câu query mà database cảm nhận được. Lúc viết endpoint, không câu hỏi nào trong hai câu đó có sức nặng. Cả hai có sức nặng ngay khi đầu bên kia có một cái bảng, vì cái bảng ép ra phiên bản cụ thể của câu hỏi: chính xác thì cái gì trả về, và trả về bao nhiêu.

Ba kiểu rỗng

Trạng thái rỗng là một quyết định sản phẩm, và là quyết định hay bị đưa ra một cách vô tình nhất. Có ít nhất ba lý do khiến màn hình của người vận hành không có dòng nào:

Không khớp gì cả — query có chạy, dữ liệu vẫn ổn, khách sạn này thật sự không có mapping ở supplier đó. Filter sai — người vận hành gõ một supplier code không tồn tại, hoặc chọn khoảng ngày loại hết mọi thứ. Hoặc một supplier timeout: search chạy bất đồng bộ, worker ghi vào một cache dùng chung rồi đánh dấu đã xong, tầng HTTP trả về những gì đã kịp về trong deadline 30 giây. Supplier trả lời ở giây thứ ba mươi mốt thì đơn giản là không có mặt trong kết quả.

Đó là ba màn hình khác nhau. "Không tìm thấy kết quả", "kiểm tra lại filter", và "một supplier không trả lời kịp — kết quả này chưa đủ". Hiện nhầm cái nào là không chỉ vô ích; là đẩy người đọc sang nhầm đội. Một người vận hành đọc "không có kết quả" cho một ca thật ra là timeout sẽ mở ticket về dữ liệu, và một engineer dữ liệu mất cả buổi sáng để chứng minh mapping vẫn nằm đó từ đầu — mà cái màn hình chỉ gây ra được chuyện đó vì API trả về một mảng rỗng không kèm theo ý kiến nào.

Một mã lỗi không phải là một câu

Backend trả về code. Màn hình phải trả về câu chữ. Giữa hai thứ đó là một phép dịch mà mặc định không ai sở hữu, và nếu frontend làm ngay tại chỗ trong một cái switch, thì cùng một lỗi cuối cùng đọc ra ba kiểu ở ba nơi.

Bài kiểm mình dùng là: câu đó có nói cho người đọc biết làm gì tiếp theo không. "Giá không còn khả dụng" là một sự kiện. "Giá này đã hết hạn — search lại để lấy giá hiện tại" là một chỉ dẫn. Khoảng cách giữa hai câu không phải chuyện gọt chữ; nó là chuyện người đọc có phải đi hỏi một con người hay không. Trên sản phẩm đa ngôn ngữ, câu đó tồn tại hai lần, nên một mã lỗi đọc kiểu này ở chỗ này và kiểu khác ở chỗ khác là loại bug tìm ra bằng cách đọc, không phải bằng cách test.

Số nào đang hiện, số nào bị trừ

Bất kỳ màn hình nội bộ nào hiện tiền đều phải trả lời một câu mà cái mockup không bao giờ hỏi: đây là con số mình hiện cho khách, hay con số thật sự chạy? Trên một nền tảng có cấu hình markup riêng cho từng tenant, hai con số đó khác nhau theo thiết kế. Có giá của supplier, và có thứ mà cấu hình của tenant làm ra từ giá đó, và người vận hành đang nhìn một booking cần biết con số nào đang nằm trên màn hình — vì hành động kế tiếp thường là hoàn tiền, chỉnh sửa, hoặc giải thích với đối tác, và cả ba đều sai nếu con số kia mới là con số đúng.

Luật mình chốt lại là: một trường tiền trên màn hình nội bộ phải mang vai trò của nó ngay trong nhãn, không phải trong tooltip và càng không phải trong trí nhớ truyền miệng. Nó tốn thêm một chữ trong nhãn. Phương án còn lại tốn của ai đó một lần đối soát.

Internal tool là một hệ thống production

Cái nửa ít được lên kế hoạch nhất: những người dùng internal tool đang dùng nó để chạy công việc kinh doanh, nên nó là một hệ thống production bất kể người dùng là ai. Nó cần auth thật — "ai trong mạng nội bộ cũng tin được" thôi không còn là một lập luận kể từ lúc có một màn hình bấm được nút hoàn tiền. Nó cần audit trail, vì câu "ai sửa dòng này" chắc chắn sẽ được hỏi, và câu trả lời thành thật không được phép là một cái nhún vai. Và nó cần đúng cái kỷ luật deploy như mọi thứ hướng ra khách: mỗi lần push một version, rollback có câu trả lời chính xác cho "về lại cái nào", cùng một bước xác nhận rõ ràng trước khi lên production. Một internal tool có đường ghi là một hệ thống production với ít người dùng hơn và mức sát thương y hệt.

Vòng phản hồi không mua được

Bù lại là một vòng phản hồi mà các đội làm sản phẩm hướng khách phải bỏ tiền ra mới có gần được. Người gặp bug đi bộ sang mô tả nó, ngay trong ngày, với dữ liệu thật còn nguyên trên màn hình của họ. Họ cũng sẽ nói luôn cho mình biết họ né màn hình nào và họ làm thay bằng cái file spreadsheet nào — đó là loại nghiên cứu sản phẩm hữu ích nhất, và nó miễn phí.

Nợ đọng lại ở đâu

Đoạn kết thành thật là: internal tool là chỗ nợ thiết kế tích lại nhanh nhất, và lý do mang tính cấu trúc chứ không phải văn hoá. Nợ chỉ được trả khi có thứ gì đó ép người ta phải nhìn vào — một buổi demo, một lời phàn nàn của khách, một trang public mà người ngoài sẽ thấy. Internal tool không có cái nào trong số đó. Người dùng của nó thích nghi thay vì phàn nàn, vì họ đã học được cách lách, và cách lách thì nhanh hơn mở ticket.

Nên mấy màn hình sai vẫn sống. Cái trạng thái rỗng không nói gì vẫn sống. Cái trường tiền không nhãn vẫn sống. Mình không có phép đo nào về việc chuyện đó tốn của những người dùng nó hằng ngày bao nhiêu — mình chưa bao giờ đo — nhưng cả bốn màn hình ở trên đều được tìm ra bằng cách dùng cái tool, chứ không phải bằng cách ngồi review cái API nuôi nó.

Bài liên quan

· 5 phút đọc

"Tức là gọi API của người khác hả" — câu tóm tắt mình nghe nhiều nhất về công việc của mình, và nó sai theo một cách đáng để mổ xẻ. Khoảng 150 supplier code trên chừng 90 tích hợp, hai pattern offer được ghi thành tài liệu, hai mô hình thực thi sau cùng một contract, và những supplier trả 200 kèm lỗi bên trong — một vòng quanh việc này thật sự gồm những gì, và vì sao nó là kiến trúc.

  • tích hợp
  • kiến trúc
  • API design
  • hệ phân tán

· 5 phút đọc

Ngày đầu với một supplier mới, mình không viết dòng code nào. Có một danh sách câu hỏi cố định — auth và cách xoay credential, search một nhịp hay hai nhịp, offer có định danh gì và sống được bao lâu, book có idempotent không và nếu không thì tra bằng gì, lỗi nằm ở đâu, chính sách có cấu trúc không, mô hình rate ngụ ý pattern nào — và các câu trả lời quyết định hình dạng của module. Con số ước lượng đi ra từ lượt đọc đó, không đi ra từ số endpoint.

  • tích hợp
  • API design
  • phương pháp
  • ước lượng