3 ポイント 投稿者 GN⁺ 2024-04-27 | 1件のコメント | WhatsAppで共有
  • APIリソースの命名やモデリングの決定は、API設計で最も難しく重要な部分である。リソースは、ユーザーが製品の動作や機能をどう捉えるかというメンタルモデルを形作る。
  • Increaseチームは、API設計を支えるために「抽象化なし」という原則を使っている。

StripeのAPI設計アプローチ

  • Stripeチームのかなりの人数は以前Stripeで働いており、Stripeの成功したAPI設計の価値観を重視している。
  • Stripeは、複雑なドメインの中核機能を、ユーザーが簡単に理解して使える抽象化として取り出すことに優れている。(例: VisaとMastercardの違いを抽象化したPaymentIntent)
  • Stripeのユーザーの大半は、決済とは無関係の製品を開発する初期段階のスタートアップであり、クレジットカードの細かな仕組みを知る必要がない。彼らはStripeを素早く統合し、製品開発に集中したいと考えている。

IncreaseのユーザーとAPI設計原則

  • 一方でIncreaseのユーザーは決済ネットワークに関する深い知識を持っており、Increaseを選ぶ理由も、ネットワークへの直接接続と統合の深さにある。
  • 彼らはFedACHの窓口がいつ閉まるのか、送金がいつ行われるのかを正確に知りたがっており、ACH送金では異なるSECコードの設定が返却タイミングに影響し得ることも理解している。
  • こうしたネットワークの根本的な複雑さを隠そうとする試みは、ユーザーの生活を単純化するどころか、ただ苛立たせるだけである。
  • 初期ユーザーとの対話を通じて、「抽象化なし」という原則を導き出し、API設計に適用した。

「抽象化なし」原則がAPI設計に与えた影響

  • 実際に使われている用語を使う: APIリソースや属性に独自の名前を作るのではなく、基盤となるネットワークの語彙を使う。(例: ACH送金パラメータにはNacha仕様のフィールド名を使う)
  • 不変性: 実際のイベントをモデルとして使うことで、より多くのAPIリソースを不変にしている。不変リソースのクラスターを、状態機械の「ライフサイクルオブジェクト」としてグループ化するのが効果的である。(例: ach_transferオブジェクトのstatusフィールドと、送金ライフサイクルに応じて生成されるいくつかの不変な子オブジェクト)
  • ユースケース別のリソース分離: リソースインスタンスによってユーザーが取れる操作の集合が大きく異なる場合、複数のリソースに分割する。(例: 送信ACH送金と受信ACH送金は別々のリソースに分ける)

エンジニアリングチームによるアプローチの順守

  • エンジニアリングチームは、このアプローチを守ることを約束している。
  • 複雑なAPIを何年にもわたって設計する際には、常に小さな増分的判断を下し続ける必要があるが、あらかじめ基本原則を守ると決めておけば、そうした判断にかかる認知負荷を減らせる。
  • 例えば、連邦準備制度へ送金する際に必要なInput Message Accountability Dataフィールドについて、抽象化の多いAPIであればこのフィールドにどう「ユーザーフレンドリー」な名前を付けるか悩むことになるが、Increaseではエンジニアがフィールド名をinput_message_accountability_dataにしてそのまま進められる。

GN⁺の意見

  • APIの抽象化レベルは、その製品ドメインに対する開発者の経験レベルや、統合に投入できるエネルギーによって変わり得る。したがってAPIを設計する際には、統合する開発者にとって適切な抽象化レベルを考えることが重要である。
  • 抽象化レベルの高いAPIを構築するなら、新機能を追加する前に慎重に考える必要がある。反対に、抽象化レベルの低いAPIを構築するなら、その方針を守り、抽象化を加えたくなる誘惑に抵抗しなければならない。
  • 基盤となるネットワークやプロトコルの用語をそのまま使うことは、開発者がunderlying systemを理解する助けになる一方で、初めて触れる開発者にとっては参入障壁にもなり得る。したがって、注釈やドキュメントをしっかり整備することが重要だと思われる。
  • API設計でimmutableオブジェクトを活用することは、データの整合性維持やside-effect防止に効果的であり得る。ただし、逆にデータ更新が必要な場合には不便になることもあるため、trade-offを十分に考慮する必要がある。
  • ユースケースごとにリソースを分離することはAPIの複雑さを高める可能性があるが、長期的には予測可能性を高められる。ただし、細分化しすぎると使い勝手が落ちる可能性もあるため、適切な水準を見極めることが重要である.

1件のコメント

 
GN⁺ 2024-04-27
Hacker Newsのコメント
  • 低レベルの抽象化を適用したAPIと高レベルの抽象化を適用したAPIの両方を提供するのがよい

    • 低レベルAPIは細かな制御が可能だが、専門知識が必要
    • 高レベルAPIは一般的なユースケース向けに単純化された操作を提供する
    • 2つのAPIの間に明確な区分を維持すれば、各APIに抽象化や特殊ケースを追加しようとする圧力が減る
    • クライアントが一方のAPIからもう一方のAPIへ移行する方法を学べるよう、資料を提供するのがよい
  • Increaseが別のアプローチを選んだ理由を説明している部分が気に入った

    • 根本的なものを設計するときは文脈が非常に重要だが、人はたいていそれを十分に認識していない
  • Stripeの本当の能力は、顧客を理解し、顧客が望むシンプルさを提供することにある

    • Increaseも顧客が必要とするものをよく把握しており、優れた製品を作るための設計指針を作るうえで同様の集中力を発揮している
  • Domain-Driven Designの「ユビキタス言語(Ubiquitous Language)」という設計パターンに似ている。これは、ドメイン専門家が使う実際の用語と同じ用語を実装でも使うというもの

  • ドメイン専門家が理解できる言語を使うべき

    • ユーザーがNACHAファイルを知っているなら、別の用語を使うと頭の中で対応関係を維持しなければならない
    • Stripeの場合、ユーザーはドメイン専門家ではないため、理解しやすくしつつ不要な詳細を隠す抽象化を作ることに価値がある
  • POSIXのような抽象化がなければ、アプリケーションはサポートするすべてのファイルシステム向けにアダプターを書かなければならない

  • 外部で管理される仕様に基づいて、API構造の一部が1:1で構築されているという

    • こうした仕様が発展または変更された場合はどうなるのか? 新しいAPIになるのか?
  • 支払いAPIでうまくモデル化しにくいものの1つは、支払いスキームが支払いの返金時に支払人と受取人の役割を異なる形で表現することだ

    • たとえば、あるスキームでは支払人と受取人が最初の支払いと同じ位置のままでいられる
    • 一方、別のスキームでは入れ替わる