3 điểm bởi GN⁺ 2024-04-27 | 1 bình luận | Chia sẻ qua WhatsApp
  • Việc đặt tên và mô hình hóa tài nguyên API là phần khó nhất và quan trọng nhất trong thiết kế API. Tài nguyên định hình mô hình tinh thần của người dùng về cách sản phẩm hoạt động và các chức năng của nó.
  • Đội ngũ Increase sử dụng nguyên tắc "không có trừu tượng hóa" để hỗ trợ thiết kế API.

Cách tiếp cận thiết kế API của Stripe

  • Nhiều thành viên trong đội ngũ Stripe trước đây từng làm việc tại Stripe và coi trọng các giá trị thiết kế API đã giúp Stripe thành công.
  • Stripe rất giỏi trong việc rút ra các trừu tượng dễ hiểu và dễ dùng từ các chức năng cốt lõi của những miền phức tạp để người dùng có thể nắm bắt và sử dụng. (Ví dụ: PaymentIntent, một lớp trừu tượng hóa sự khác biệt giữa Visa và Mastercard)
  • Phần lớn người dùng của Stripe là các startup giai đoạn đầu đang phát triển sản phẩm không liên quan đến thanh toán, nên họ không cần biết chi tiết về thẻ tín dụng. Họ muốn tích hợp Stripe nhanh chóng và tập trung vào phát triển sản phẩm.

Người dùng của Increase và nguyên tắc thiết kế API

  • Ngược lại, người dùng của Increase có kiến thức sâu về mạng lưới thanh toán, và lý do họ chọn Increase là vì kết nối trực tiếp với mạng lưới cũng như độ sâu tích hợp.
  • Họ muốn biết chính xác khi nào cửa sổ FedACH đóng lại và thời điểm chuyển khoản diễn ra, đồng thời hiểu rằng việc đặt các mã SEC khác nhau trong giao dịch ACH có thể ảnh hưởng đến thời điểm hoàn trả.
  • Những nỗ lực nhằm che giấu sự phức tạp nền tảng của các mạng lưới này không làm cuộc sống đơn giản hơn mà chỉ khiến người dùng khó chịu.
  • Thông qua các cuộc trò chuyện với những người dùng đầu tiên, nhóm đã rút ra nguyên tắc "không có trừu tượng hóa" và áp dụng nó vào thiết kế API.

Nguyên tắc "không có trừu tượng hóa" đã ảnh hưởng đến thiết kế API như thế nào

  • Sử dụng thuật ngữ thực tế đang được dùng: thay vì tự tạo tên cho tài nguyên và thuộc tính API, nhóm sử dụng từ vựng của mạng lưới nền tảng. (Ví dụ: các tham số chuyển khoản ACH dùng tên trường trong đặc tả Nacha)
  • Tính bất biến: dùng các sự kiện thực tế làm mô hình để nhiều tài nguyên API trở nên bất biến hơn. Việc nhóm các cụm tài nguyên bất biến thành các "đối tượng vòng đời" dạng state machine là một cách làm hiệu quả. (Ví dụ: trường status của đối tượng ach_transfer và một số đối tượng con bất biến được tạo ra theo vòng đời chuyển khoản)
  • Tách tài nguyên theo từng trường hợp sử dụng: khi tập hợp hành động mà người dùng có thể thực hiện khác nhau đáng kể tùy theo từng thể hiện tài nguyên, nhóm chia chúng thành nhiều tài nguyên. (Ví dụ: chuyển khoản ACH đi và chuyển khoản ACH đến được tách thành các tài nguyên riêng biệt)

Cam kết tuân thủ cách tiếp cận của đội ngũ kỹ thuật

  • Đội ngũ kỹ thuật cam kết tuân thủ cách tiếp cận này.
  • Khi thiết kế một API phức tạp trong nhiều năm, bạn luôn phải đưa ra những quyết định nhỏ mang tính gia tăng; việc cam kết trước với các nguyên tắc nền tảng giúp giảm tải nhận thức cho các quyết định đó.
  • Ví dụ, với trường Input Message Accountability Data cần thiết khi chuyển tiền tới Cục Dự trữ Liên bang, trong một API có nhiều trừu tượng hóa, người ta sẽ phải băn khoăn làm sao đặt tên trường này theo cách "thân thiện với người dùng"; nhưng ở Increase, kỹ sư chỉ cần đặt tên trường là input_message_accountability_data rồi tiếp tục.

Ý kiến của GN⁺

  • Mức độ trừu tượng hóa của API có thể khác nhau tùy theo mức độ kinh nghiệm của lập trình viên với miền sản phẩm đó và lượng công sức họ sẵn sàng bỏ ra cho việc tích hợp. Vì vậy, khi thiết kế API, điều quan trọng là phải cân nhắc mức độ trừu tượng hóa phù hợp với các lập trình viên sẽ tích hợp nó.
  • Nếu xây dựng một API có mức độ trừu tượng hóa cao, bạn cần suy nghĩ cẩn thận trước khi thêm tính năng mới. Ngược lại, nếu xây dựng một API có mức độ trừu tượng hóa thấp, bạn cần kiên định với hướng đó và chống lại cám dỗ muốn thêm các lớp trừu tượng.
  • Việc giữ nguyên thuật ngữ của mạng lưới hoặc giao thức nền tảng có thể giúp các lập trình viên hiểu rõ hệ thống underlying, nhưng ngược lại cũng có thể trở thành rào cản gia nhập với những người mới tiếp cận. Vì vậy, có lẽ điều quan trọng là phải chuẩn bị chú thích hoặc tài liệu hóa đầy đủ.
  • Việc sử dụng đối tượng immutable khi thiết kế API có thể hiệu quả trong việc duy trì tính nhất quán dữ liệu và ngăn side-effect. Tuy nhiên, ngược lại, nó cũng có thể gây bất tiện khi cần cập nhật dữ liệu, nên cần cân nhắc kỹ trade-off.
  • Việc tách tài nguyên theo từng trường hợp sử dụng có thể làm tăng độ phức tạp của API, nhưng về dài hạn có thể nâng cao tính dự đoán. Tuy nhiên, nếu chia quá vụn thì tính khả dụng có thể giảm, vì vậy điều quan trọng là tìm được mức độ phù hợp.

1 bình luận

 
GN⁺ 2024-04-27
Ý kiến trên Hacker News
  • Nên cung cấp cả API với mức trừu tượng thấp và API với mức trừu tượng cao

    • API cấp thấp cho phép kiểm soát chi tiết nhưng đòi hỏi kiến thức chuyên môn
    • API cấp cao cung cấp các thao tác được đơn giản hóa, phù hợp với những trường hợp sử dụng phổ biến
    • Nếu giữ ranh giới rõ ràng giữa hai API, sẽ giảm áp lực phải thêm các lớp trừu tượng hay trường hợp đặc biệt vào từng API
    • Nên cung cấp tài liệu để client có thể học cách chuyển từ API này sang API kia
  • Tôi thích phần giải thích vì sao Increase chọn một cách tiếp cận khác

    • Khi thiết kế những thứ mang tính nền tảng, bối cảnh rất quan trọng, nhưng mọi người thường không nhận thức đầy đủ điều đó
  • Năng lực thực sự của Stripe là hiểu khách hàng và mang đến sự đơn giản mà họ mong muốn

    • Increase cũng nắm rất rõ điều khách hàng cần và thể hiện mức độ tập trung tương tự trong việc tạo ra các nguyên tắc thiết kế để làm ra sản phẩm xuất sắc
  • Điều này giống với mẫu thiết kế "Ubiquitous Language" của Domain-Driven Design, nơi cách triển khai sử dụng chính các thuật ngữ thực tế mà chuyên gia miền nghiệp vụ dùng

  • Cần sử dụng ngôn ngữ mà chuyên gia miền nghiệp vụ có thể hiểu

    • Nếu người dùng biết về tệp NACHA, thì dùng thuật ngữ khác sẽ buộc họ phải tự duy trì việc ánh xạ trong đầu
    • Với Stripe, người dùng không phải là chuyên gia miền nghiệp vụ, nên việc tạo ra các lớp trừu tượng vừa dễ hiểu vừa che giấu những chi tiết không cần thiết là điều có giá trị
  • Nếu không có những lớp trừu tượng như POSIX, ứng dụng sẽ phải viết adapter cho mọi hệ thống tệp được hỗ trợ

  • Có nói rằng một phần cấu trúc API được xây dựng theo kiểu 1:1 dựa trên các đặc tả do bên ngoài kiểm soát

    • Nếu các đặc tả này phát triển hoặc thay đổi thì sẽ ra sao? Đó có phải là một API mới không?
  • Một điều khó mô hình hóa gọn gàng trong API thanh toán là các hệ thống thanh toán biểu diễn vai trò của người trả và người nhận khác nhau khi hoàn tiền

    • Ví dụ, trong một số hệ thống nhất định, người trả và người nhận có thể vẫn giữ nguyên vị trí như ở khoản thanh toán ban đầu
    • Trong khi ở các hệ thống khác, hai vai trò này sẽ bị đảo lại