docs: rewrite reference and clarify interface abstraction

This commit is contained in:
2026-10-15 17:53:48 +09:00
parent 6e9e675c70
commit f6905074b1
20 changed files with 981 additions and 826 deletions
+49 -43
View File
@@ -2,35 +2,35 @@
## Status
この文書は、Rust / TypeScript Host APIを設計する前に、動的なWorldspaceを運用するための責務、処理モデル、要件を整理するdraftである。
動的なWorldspaceを運用するには、Hostが何を解決し、どの範囲のObjectを投影し、どうOperationを実行するかを整理する必要がある。このdraftは、Rust / TypeScript Host APIの設計に先立って、その責務、処理モデル、要件をまとめたものである。
具体的なtrait、class、function、decorator、macro、builderのsyntaxは定義しない。この文書で使用する`Projection Provider`、`Projection Resolution`、`Projected Object`等の名称もworking terminologyであり、canonicalなProtocol typeではない。
具体的なtrait、class、function、decorator、macro、builderのsyntaxは、ここでは定義しない。`Projection Provider`、`Projection Resolution`、`Projected Object`等もHost内部の設計を検討するためのworking terminologyであり、canonicalなProtocol typeではない。
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)を参照する。言語別のconceptual API modelは[Rust API Model](rust-api-model.md)と[TypeScript API Model](typescript-api-model.md)で扱う。
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)に従う。言語別のconceptual API modelは[Rust API Model](rust-api-model.md)と[TypeScript API Model](typescript-api-model.md)で扱う。
## 目的
WIP Hostの中心的な実装対象は、事前に列挙された静的endpointだけではない。Filesystem、database row、repository内容、検索結果、外部service上のentityなど、実行時に存在と状態が決まる空間をWorldspaceへ投影できなければならない。
WIP Hostは、事前に列挙した静的endpointだけでなく、実行時に存在と状態が決まる空間をWorldspaceへ投影できなければならない。Filesystem、database row、repository内容、検索結果、外部service上のentityなどが、その実装対象になる。
HostがWorldspace内のすべてのObjectを常駐instanceとして保持することは要求しない。Backend dataをrequest時に解決し、必要な範囲だけObjectとして投影できることを基本とする。
そのために、すべてのObjectを常駐instanceとして保持する必要はない。Backend dataをrequest時に解決し、必要な範囲だけObjectとして投影できることを基本とする。
固定pathへ登録されたObjectやservice endpointは、同じ動的projection modelにおいてrouting / resolution structureが固定された特殊ケースとして扱えるべきである。現在の主体やbackend stateに応じて、そこで返すObject representationやvalidatorが変化することは妨げない。静的登録だけを基本形とし、動的空間を大量のObject登録によって模倣する設計にはしない。
固定pathに登録するObjectやservice endpointも、同じ動的projection modelで表現できるべきである。この場合はrouting / resolution structureが固定されているが、返すObject representationやvalidatorは、現在の主体やbackend stateに応じて変化してよい。静的登録を基本形にして大量のObject登録で動的空間を模倣するのではなく、動的な解決の特殊ケースとして静的登録を扱う。
## 基本的な分離
Host実装APIでは、少なくとも次の責務を区別する必要がある。この区別を一対一のpublic type、trait、objectへ分割することまでは決定しない。
Host実装APIでは、少なくとも次の責務を区別する必要がある。ただし、責務ごとに一つのpublic type、trait、objectを設けるかどうかは未決定である。
### Interface Declaration
Operation名、parameter、return type、documentation等を宣言し、Interface Descriptor、Value codec、boundary validationを生成する。
Interface Declarationは、Operation名、parameter、return type、documentation等の宣言である。その宣言からInterface Descriptor、Value codec、boundary validationを生成する。
Interface Declarationは、多数のObjectが共有できる比較的静的なcapability schemaである。Objectの列挙やbackend dataのlifecycleは担当しない。
多数のObjectが共有できる、比較的静的なcapability schemaとして扱う。Objectの列挙とbackend dataのlifecycleは、Interface Declarationの責務には含めない。
### Worldspace Projection
Clientから受け取ったpathを、現在の主体とbackend stateに基づいて解決し、Protocol上のObject projectionを生成する。一つのProjected Objectは、Host固有のentityを持たないvirtual nodeでも、一つのbackend entityに対応するものでも、複数のbackend entityを集約したものでもよい。
Worldspace Projectionは、Clientから受け取ったpathを現在の主体とbackend stateに基づいて解決し、Protocol上のObject projectionを生成する処理である。投影するObjectは、Host固有のentityを持たないvirtual nodeでも、一つのbackend entityに対応するものでも、複数のbackend entityを集約したものでもよい。
Projectionは、少なくとも次を決定する。
Projectionで決定する内容には、少なくとも次が含まれる。
- そのpathのObjectを現在の主体へ公開するか。
- 公開する`name`、optionalな`description`、`ref`、`validator`。
@@ -40,26 +40,28 @@ Projectionは、少なくとも次を決定する。
### Host Runtime
Protocol requestを受け取り、ProjectionとInterface registryを協調させる。Operation callでは、現在のProjected Objectが公開するInterface集合からClientが指定した一つのDescriptorを固定し、そこに宣言されたOperationをObjectのHost内implementationへ適用する。
Host RuntimeはProtocol requestを受け取り、ProjectionとInterface registryを協調させる。Operation callでは、現在のProjected Objectが公開するInterface集合からClient指定のDescriptorを一つ固定し、そのDescriptorに宣言されたOperationをObjectのHost内implementationへ適用する。
Host RuntimeはProtocol validation、Interface Descriptorの公開、Value validation、error mapping、resource limit等を担う。Backend固有のprojection resolutionやdomain operation implementationそのものはProvider等のHost componentへ委譲できる。Object implementationとOperation実装を接続する具体的なAPIは各言語のSDK側で決定し、Protocol conceptとして追加しない。
また、Protocol validation、Interface Descriptorの公開、Value validation、error mapping、resource limit等も担う。一方、backend固有のprojection resolutionやdomain operation implementationそのものは、Provider等のHost componentへ委譲できる。
Object implementationとOperation実装を接続する具体的なAPIは、各言語のSDK側で決める。これはHost内の実装を接続するためのAPIであり、新たなProtocol conceptとしては追加しない。
## Working terminology
このdraftでは、Host内部の議論のために次の語を使う。
Host内部の投影処理を検討するため、次の語を使う。
- **Backend Entity** — File、database row、issue、repository、remote entity等、projectionの入力になり得るHost固有の実体。一つのProjected Objectと一対一に対応するとは限らない。
- **Projection Resolution** — 現在の主体とpathについて、公開するObject representationと、後続処理に必要なHost-private情報を得るrequest-timeの解決結果。
- **Projection Provider** — Pathと主体からProjection Resolutionを生成し、indexable childrenの発見を支援するHost component。
- **Projected Object** — その時点でClientへ返すProtocol `Object`。Backend Entityを持たないvirtual Object、一つのentityのprojection、複数entityのaggregateのいずれでもよく、Host内の常駐instanceを意味しない。
HostがOperationを実装するために使用するRust struct、TypeScript object、backend handle、transaction context等はHost-privateであり、共通するHost abstractionを必須にしない。これらをProtocolの`Target { path, validator }`、canonical path、Objectの`ref`として公開または流用しない。
Operationの実装に使うRust struct、TypeScript object、backend handle、transaction context等はHost-privateである。これらに共通するHost abstractionは必須としない。また、Protocolの`Target { path, validator }`、canonical path、Objectの`ref`として公開したり、それらへ流用したりしない。
## 運用モデル
### `observe`
`observe(path, depth)`では、Hostは概念的に次を行う。
`observe(path, depth)`では、要求された範囲のObjectを現在の状態から投影する。Hostが概念的に行う処理は次のとおりである。
1. Requestの主体とpathをProjection Providerへ渡す。
2. Providerが現在のbackend stateから、そのpathで公開するProjected ObjectのProjection Resolutionを生成する。
@@ -69,23 +71,25 @@ HostがOperationを実装するために使用するRust struct、TypeScript obj
6. Nodeがrequested depthに達した場合はchildrenを観測せず、responseの`children` fieldを省略する。
7. Requested depthまで完全な`ObjectObservation`を返す。
ProviderはWorldspace全体をmaterializeせず、現在処理しているparentのdirect childrenを遅延して発見できる必要がある。Childrenをstream、iterator、cursor等のHost内部表現で生成してよいが、一つのparentについて成功するには公開されたindexable childrenをすべて調べ終えなければならない。
Providerには、Worldspace全体をmaterializeせず、処理中のparentのdirect childrenを遅延して発見できることが必要になる。Host内部ではstream、iterator、cursor等でchildrenを生成してよい。ただし、一つのparentの観測を成功とするには、その主体へ公開するindexable childrenをすべて調べ終える必要がある。
Backend failure、cancellation、またはresource budget超過をclean exhaustionとして扱わない。Requested depthまでの完全なresponseを構築できない場合、Host Runtimeは部分的なsuccess responseを返さず、対応するfailureを返す。
Backend failure、cancellation、resource budget超過は、列挙が正常に完了したclean exhaustionとは区別する。Requested depthまで完全なresponseを構築できなければ、Host Runtimeは部分的なsuccess responseではなく、対応するfailureを返す。
各childについて現在のObject projectionを構築し、そのcanonical pathを後の`observe`または`call_operation`で現在のProjected Objectとして再解決できなければならない。以前観測したbackend entityやHost内部instanceを再現することは要求しない。
列挙した各childについては、現在のObject projectionを構築し、そのcanonical pathを後の`observe`や`call_operation`で再解決できなければならない。再解決の対象は、その時点のProjected Objectである。以前観測したbackend entityやHost内部instanceの再現は要求しない。
この処理のために、Hostが以前の`observe`で生成したObject instanceを保持している必要はない。内部cacheを利用してもよいが、cacheの有無によってProtocol semanticsを変えてはならない。
したがって、Hostが以前の`observe`で作ったObject instanceを保持する必要もない。内部cacheは利用してよいが、その有無でProtocol semanticsを変えてはならない。
### `fetch_interface`
ProjectionがObjectへ割り当てた各Interface参照は、同じ主体から取得可能なDescriptorへ解決されなければならない。
ProjectionがObjectへ割り当てた各Interface参照は、その主体から取得可能なDescriptorへ解決されなければならない。複数のObjectで同じ参照を共有でき、一つのObjectに複数のInterfaceを組み合わせることもできる。
複数のObjectは同じInterface参照を共有でき、一つのObjectも複数のInterfaceを組み合わせられる。Validatorを返すInterface参照ではDescriptorを変更でき、同じ参照とvalidatorの組が一つのDescriptor observationを表す。Validatorを返さない参照のDescriptorは、その参照が有効な間immutableである。Interface参照のscopeは[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。登録API、生成時期、deduplication、cacheの具体実装は別途決定する。
Descriptorの変更可否は、Interface参照がvalidatorを返すかどうかで分かれる。Validatorを返す参照ではDescriptorを変更でき、同じ参照とvalidatorの組が一つのDescriptor observationを表す。Validatorを返さない参照では、その参照が有効な間、Descriptorはimmutableである。
Interface参照のscopeは[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。登録API、生成時期、deduplication、cacheの具体実装は別途決める。
### `call_operation`
`call_operation`では、HostはProviderまたはbackend固有のexecution boundaryへ入り、その同じboundary内で概念的に次を行う。
`call_operation`では、現在のObjectを解決する処理と、そのObjectへの実行を同じexecution boundary内で行う。HostはProviderまたはbackend固有のboundaryに入り、概念的に次を行う。
1. 現在の主体と`target.path`からProjection Resolutionを生成し、同じbackend対象を保持するstable handleまたはtransaction contextを取得する。
2. そのpathのProjected Objectを現在も公開するか確認する。
@@ -97,15 +101,15 @@ ProjectionがObjectへ割り当てた各Interface参照は、同じ主体から
8. 固定したObject implementation、Interface Descriptor、Operation implementationを、step 1で固定した同じbackend対象へ適用する。
9. Resultを同じOperation Declarationで検証し、nestedしたすべての`Entry`へ現在の主体のvisibility checkを適用してから、実行後Object validatorとともに返す。
Step 3から8までの間にObject、Interface、Descriptor、Operation implementation、backend対象の対応が変化し得る実装は、この手順を満たさない。Projectionは、Host RuntimeとProviderがこのatomicityを実現するために必要なstable handle、transaction、conditional operation、lock等を使用できるようにしなければならない。
Step 3から8までの間に、Object、Interface、Descriptor、Operation implementation、backend対象の対応が変わり得る実装では、この手順を満たせない。Host RuntimeとProviderがatomicityを実現できるよう、Projectionは必要なstable handle、transaction、conditional operation、lock等を使用できる必要がある。
過去の`observe`で作成したHost内部Object instanceの存在を前提にしてはならない。Clientから届くprotocol-level Targetはpathとoptionalなvalidatorであり、Hostはcall時の現在状態からObject implementationを解決する。Validatorを省略したcallを現在のOperationが許可する場合は、過去に観測したObjectではなく、実行時にpathが指す現在のObjectへ無条件に実行する。
解決には、過去の`observe`で作ったHost内部Object instanceを前提としない。Clientから届くprotocol-level Targetはpathとoptionalなvalidatorであり、Hostはcall時の現在状態からObject implementationを解決する。現在のOperationがvalidatorの省略を許可する場合、callは過去に観測したObjectではなく、実行時にpathが指す現在のObjectへ無条件に実行する。
Validatorを指定した場合は、Clientが観測したObject identityおよび保護対象状態と実行対象を照合する。Path、`ref`、以前のProjection Resolution、cacheされたHost内部instanceのいずれも、単独ではProtocol上の永続的なObject identityとして扱わない。
一方、validatorが指定されたcallでは、Clientが観測したObject identityと保護対象状態を実行対象へ照合する。Path、`ref`、以前のProjection Resolution、cacheされたHost内部instanceは、いずれも単独ではProtocol上の永続的なObject identityとして扱わない。
## Filesystem projectionの評価例
Filesystemを`/files`以下へ投影する場合、Hostが全file / directoryに対応するObject instanceを作成する必要はない。
Filesystemを`/files`以下へ投影する場合も、全file / directory分のObject instanceを作成する必要はない。Request時の解決と投影を、次のように行える。
- `observe("/files/a.txt", depth = 0)`では、pathをfilesystem entryへ解決し、stat等からObject projectionを構築する。
- `observe("/files", depth = 1)`では、directory listingから直接のindexable childrenをすべて列挙する。
@@ -113,7 +117,7 @@ Filesystemを`/files`以下へ投影する場合、Hostが全file / directoryに
- 主体の権限に応じてObjectを非公開にしたり、read-only、writable等のcapability Interfaceを集合へ追加または除外できる。
- File Operationでは、call時にpathを現在のfilesystem entryへ解決し、Rust struct、TypeScript object、file descriptor等を使ってOperationを実装できる。
この例で、Objectはfileそのものでも、file内容を複製したrecordでもない。FileをWorldspace上で発見および操作するためのprotocol-level projectionである。
この場合のObjectは、fileをWorldspace上で発見・操作するためのprotocol-level projectionである。Fileそのものを渡すわけでも、file内容を複製したrecordを渡すわけでもない。
## 要件
@@ -167,13 +171,13 @@ Filesystemを`/files`以下へ投影する場合、Hostが全file / directoryに
- Operation call時には、その時点でpathが指す現在のProjected ObjectとInterface集合を再解決し、Clientが指定した参照のmembershipとvalidatorを確認する。
- 非公開Object、非公開Operation、公開済みだが実行拒否されたOperationをProtocolで定めたerrorへ一貫して対応付ける。
Backendが並行して変化する場合、複数request間で同じsnapshotを保証することまでは要求しない。観測したObject identityおよび状態と条件付き実行の対応はvalidatorで保護する。Validatorを省略したcallをOperationが許可する場合は実行時の現在Objectへ無条件に実行し、Operationがvalidatorを要求する場合は`ValidatorRequired`として実行しない。
Backendが並行して変化する場合、複数request間で同じsnapshotを保証することまでは要求しない。観測したObject identityと状態を条件付き実行の対象へ対応付けるため、validatorを使う。Operationがvalidatorの省略を許可すれば、callは実行時の現在Objectへ無条件に実行する。Validatorを要求するOperationでは、省略されたcallを`ValidatorRequired`として拒否し、実行しない。
### Operation解決と実行対象のatomicity
Operation callでは、visibility、Object identityとvalidator、Interface membershipとvalidator、Interface Descriptor、Operation implementation、backend対象を一つのlinearization pointで固定しなければならない。ValidatorなしのObject実行をOperationが許可する場合でも、解決後にpathの指すProjected Objectが変化し、以前のDescriptorに基づくOperation implementationが現在の別Objectへ適用されることを許してはならない。
Operation callでは、visibility、Object identityとvalidator、Interface membershipとvalidator、Interface Descriptor、Operation implementation、backend対象を、一つのlinearization pointで固定しなければならない。Object validatorなしの実行をOperationが許可する場合も、この固定は必要である。解決後にpathの指すProjected Objectが変わり、以前のDescriptorに基づくOperation implementationが現在の別Objectへ適用されることは許さない。
少なくとも次を一つのatomicなexecution boundaryとして扱えなければならない。
少なくとも次の処理を、一つのatomicなexecution boundaryとして扱える必要がある。
- Pathが現在指すObject identityと保護対象状態の確認。
- Object validatorの必須判定と比較。
@@ -183,9 +187,9 @@ Operation callでは、visibility、Object identityとvalidator、Interface memb
- Authorizationの確認。
- 同じbackend対象へのOperation実行。
単にpathを一度解決し、validatorを比較した後に、同じpathを別途開き直してOperationを実行する実装では、比較と実行の間に対象が差し替わる可能性がある。
Pathを一度解決してvalidatorを比較しても、その後に同じpathを別途開き直して実行すると、比較と実行の間に対象が差し替わる可能性がある。
Host APIは、backend transaction、lock、revision付きconditional update、file descriptor、identity再確認等、Providerがbackendに適した方法でatomicityを実現できる境界を提供する必要がある。すべてのbackendに共通する特定のlocking方式は要求しない。
そのためHost APIには、Providerがbackendに適した方法でatomicityを実現できる境界が必要になる。Backend transaction、lock、revision付きconditional update、file descriptor、identity再確認等を利用できるようにするが、すべてのbackendに共通する特定のlocking方式は要求しない。
### Host内部Object stateのlifecycleを限定できること
@@ -229,7 +233,7 @@ Host APIは、backend transaction、lock、revision付きconditional update、fi
### RustとTypeScriptで同じsemanticsを表現できること
言語ごとのAPI syntaxは異なってよいが、少なくとも次を両方で実現できなければならない。
RustとTypeScriptでAPI syntaxが異なっても、次の処理や制約は両方で実現できなければならない。
- Asyncなpath resolutionとchild enumeration。
- Data-drivenなObject projection。
@@ -240,11 +244,11 @@ Host APIは、backend transaction、lock、revision付きconditional update、fi
- Request context、主体、cancellation、resource limitの伝播。
- Protocol errorとbackend / implementation errorの分離。
Rust固有のtrait、generic、associated type、type erasureや、TypeScript固有のobject definition、generic inference、runtime schema libraryの選択は、この要件を満たすためのAPI設計段階で決める。
Rustのtrait、generic、associated type、type erasureや、TypeScriptのobject definition、generic inference、runtime schema libraryの選択は、これらの要件を満たすAPIを設計する段階で決める。
## Host内部cache
Hostは性能最適化として、path resolution、backend metadata、Object projection、Interface Descriptor、Host内部Object state等をcacheしてよい。ただし、cacheはProtocol contractではない。
Host内部のcacheは性能最適化であり、Protocol contractではない。Path resolution、backend metadata、Object projection、Interface Descriptor、Host内部Object state等をcacheしてよいが、次の条件を守る必要がある。
- Cacheがなくても正しく動作しなければならない。
- Visibilityとauthorizationを異なる主体間で誤って共有してはならない。
@@ -254,21 +258,23 @@ Hostは性能最適化として、path resolution、backend metadata、Object pr
## Composition
一つのHostは、Filesystem、database、remote API等の複数Providerを一つのWorldspaceへ合成できることが望ましい。
一つのHostで、Filesystem、database、remote API等の複数Providerを一つのWorldspaceへ合成できることが望ましい。
Composition後も、同じ主体へ公開されたWorldspace全体で`ref`とInterface参照のProtocol semanticsを保たなければならない。Provider-local identityやInterface keyをそのまま公開すると衝突し得るため、Hostはnamespace、変換、中央発行等の方法で次を保証する。
合成する場合も、同じ主体へ公開するWorldspace全体で`ref`とInterface参照のProtocol semanticsを保たなければならない。Provider-local identityやInterface keyをそのまま公開すると衝突し得るため、Hostはnamespace、変換、中央発行等によって次を保証する。
- 異なるObjectへ同じ有効な`ref`を割り当てない。
- 同じ有効なInterface参照とvalidatorの組を異なるDescriptorへ対応付けない。
- Validator比較がProvider routingの変更によって別Objectへ適用されない。
Interface参照は[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)の構造化参照を使用する。Objectの祖先制約と、合成後のscope・path・typed `entry`の変換は[ProtocolのWorldspace composition](../3-protocol.md#worldspace-composition)に従う。Objectの`ref`の具体的な発行方式は引き続き未決定とする。ScopeはそのpathのObjectに紐づき、self-scopeを許可する。RuntimeはDescriptorとscope Objectのoptionalな`ref`を一つのInterface observationとして公開し、callで指定された`scope_ref`をrouting・implementationの固定と一貫して確認する。`ref`のないscopeも許可し、そのidentityの追跡を要求しない。
Interface参照には、[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)の構造化参照を使う。Objectの祖先制約と、合成後のscope・path・typed `entry`の変換は、[ProtocolのWorldspace composition](../3-protocol.md#worldspace-composition)に従う。Objectの`ref`を具体的にどう発行するかは、引き続き未決定である。
ただし、mount API、path routing、Provider間のparent / child関係、同名entry conflict、cross-provider Operation、transaction boundaryは未決定である。ProtocolはHost内部のcomposition方式を公開しないため、Host APIでこれらをどこまで標準化するかを別途検討する。
ScopeはそのpathのObjectに紐づき、self-scopeも許可する。RuntimeはDescriptorとscope Objectのoptionalな`ref`を一つのInterface observationとして公開する。Callで指定された`scope_ref`は、routing・implementationの固定と一貫して確認する。`ref`のないscopeも許可し、そのidentityの追跡は要求しない。
Host内部の合成方法については、mount API、path routing、Provider間のparent / child関係、同名entry conflict、cross-provider Operation、transaction boundaryが未決定である。ProtocolではHost内部のcomposition方式を公開しないため、これらをHost APIでどこまで標準化するかは別途検討する。
## 非目標
このdraftは次を要求しない。
動的projectionの要件には、次を含めない。
- Worldspace全体の事前materialization。
- Objectごとの常駐class instanceまたはactor。
@@ -281,7 +287,7 @@ Interface参照は[2.2. Operation and Interface](../2.2-operation-and-interface.
## API設計前に評価するシナリオ
具体API案は、少なくとも次のシナリオで不自然な大量登録や永続Object instanceを要求しないことを確認する。
具体API案は、少なくとも次のシナリオで評価する。不自然な大量登録や、永続Object instanceの保持を要求しないことを確認する必要がある。
1. 数百万entryを持つFilesystemを、directory listingに応じて遅延投影する。
2. Database tableのrowをObjectとして投影し、row keyからcall時に再解決する。
@@ -318,4 +324,4 @@ Interface参照は[2.2. Operation and Interface](../2.2-operation-and-interface.
- Provider composition時のconflict、ownership、lifecycle、shutdown順序。
- Observability、tracing、auditで非公開Objectやsecretを漏らさないための標準hook。
これらを決定する前に、Rust / TypeScript双方で複数のAPI sketchを作り、上記の評価シナリオと要件に照らして比較する。
これらの決定に先立ち、Rust / TypeScript双方で複数のAPI sketchを作る。各案をここに挙げた評価シナリオと要件に照らして比較し、具体的なAPIを検討する。