注意:これは、APIデザインに関する私の本の2つの新しい章のドラフトです。このテキストには、前の章への参照が含まれています。
強力な接続と関連する問題
前のセクションでは、理論的なルールと原則を示し、実際の例でそれらを説明しようとしました。ただし、変更に強いAPIを設計する原則を理解するには、何よりも多くの練習が必要です。「わらを置く」場所の知識は、多くの点で「困難な過ちの息子」です。すべてを予測することはできませんが、必要なレベルの技術的直感を身に付けることはできます。
したがって、このセクションでは、次のように進めます。前のセクションからモデルAPIを取得し、可能なすべてのポイントで安定性を確認します。インターフェイスの「変動分析」を実行します。さらに具体的には、「もしも」という質問で各エンティティにアプローチします。-このロジックの独自の実装を作成する機能をパートナーに提供する必要がある場合はどうなりますか。
注意を払うべき最初の重要なポイント:私たちは製品ロジックの実装のためのオプションについて具体的に話している。エンティティの実装のオプションについてではありません。APIの変更は、主に、元の設計では提供されなかった何か、つまり便利なことを実行できるようにするために行われます。あなたの顧客はそのようにインターフェースを再実装することはありません。
この考慮事項により、インターフェイスを盲目的に変更しないようにする特定の制限が導入されます(結局のところ、そのようなオプションは無数にあり、それらすべてを提供するのはSisypheanの作業です):まず、なぜ特定の理由を理解する必要があります変更が必要であり、ここから、それらがどのように導入されるべきかをすでに理解しています。
2つ目の重要な点は、このバリエーションを可能にするソリューションの多くは、APIの設計にすでに組み込まれているということです。それらのいくつか(たとえば、準備の決定の問題)については前の章で詳しく説明し、コメントなしで提供したものもあります。これらの決定が行われた理由を説明するときが来ました。
NB: , ; ad hoc , . API ; , , .
, . ?
- , «» ;
- , .
. , ? , «»: , . , :
// POST /v1/recipes { "id", "product_properties": { "name", "description", "default_value" // , // … }, "execution_properties": { // "program_id", // "parameters" } }
, , . , — .
, 11: . :
"product_properties": { // "l10n" — // "localization" "l10n" : [{ "language_code": "en", "country_code": "US", "name", "description" }, /* */ … ] ]
— default_volume
? , , , . , , , «300 », «10 ». :
- , ;
- , .
, API - — , API. , — . .
, , API . — name
description
? , . — /v1/search
, : search
?
— , UI . -, name
description
— , ( ) ( ). , API . , UI ? , , : name
— «-» , . -, , UI; -, . , , «», «» «» « » « ».
— UI ( ) , ( , , ). product_properties
, , .
, — . , , , () ( , ). API « », . , : . .
: , . — , (, , .. API) .
, . - , API, — , API . - API :
l10n.volume.format(value, language_code, country_code) // l10n.formatVolume('300ml', 'en', 'UK') → '300 ml' // l10n.formatVolume('300ml', 'en', 'US') → '10 fl oz'
API , , , . , , :
// // PUT /formatters/volume/ru { "template": "{volume} " } // // «» PUT /formatters/volume/ru/US { // // , "value_preparation": { "action": "divide", "divisor": 30 }, "template": "{volume} ." }
NB: , , , , , (, , ), (.. ). .
name
description
. , , (, , API) «». name
description
, UI. UI .
GET /v1/layouts/{layout_id} { "id", // , // // "kind": "recipe_search", // , // // "properties": [{ // , `name` // // — // `seach_title` "field": "search_title", "view": { // , // "min_length": "5em", "max_length": "20em", "overflow": "ellipsis" } }, …], // "required": ["search_title", "search_description"] }
, , . :
PUT /v1/recipes/{id}/properties/l10n/{lang} { "search_title", "search_description" }
:
POST /v1/layouts { "properties" } → { "id", "properties" }
, UI , , .
— , — execution_properties
, , . :
POST /v1/recipes { "id" } → { "id" }
, «» , . , , -, :
POST /v1/recipe-builder { "id", // "product_properties": { "default_volume", "l10n" }, // "execution_properties" // "layouts": [{ "id", "kind", "properties" }], // "formatters": { "volume": [ { "language_code", "template" }, { "language_code", "country_code", "template" } ] }, // , // // … }
, — . , — , , - . , , , , : ( ), , 11.
POST /v1/recipes/custom { // : // , "namespace": "my-coffee-company", // "id_component": "lungo-customato" } → { "id": "my-coffee-company:lungo-customato" }
, : , . , "common", . (, , , API .)
, . , API 9 «» « ». , program-matcher
:
GET /v1/recipes/{id}/run-data/{api_type} → { /* API */ }
:
- API -;
- API ;
- API .
, — , , API -. , «», , «».
program_run_id
, . .
, , . API - API. , , -, API. API , - ?
, API : , () . API — , :
// // - PUT /partners/{id}/coffee-machines { "coffee-machines": [{ "id", … "program_api": { "program_run_endpoint": { /* - */ "type": "rpc", "endpoint": <URL>, "format" }, "program_state_endpoint", "program_stop_endpoint" } }, …] }
NB: API ( program_run_endpoint
, program_state_endpoint
, .)
API , , API . .
- (.. API), : , .
- : .
2 , 1. , , — , , . , , program_modify_endpoint
, ( , ). , , ( , ) .
- , . : , API , . , , , modify
API — , . , , , : , - , « ». , , , , , , , , , , , .
, , program_takeout_endpoint
. :
-
program_takeout_endpoint
,program_modify_endpoint
; -
program_modify_endpoint
,program_takeout_endpoint
.
, . , takeout
. - modify
, . , , — API , .
, API , . , , «» , , : , API -, . — , , — , , .
, . API « », .
? : , . ? - :
- API , ; , : - - , , - ;
- API , API ; , .
, , , : , . , « ».
:
- , ;
- : , .
, , (- ) . SDK :
/* - */ registerProgramRunHandler(apiType, (program) => { // // let execution = initExecution(…); // // program.context.on('takeout_requested', () => { // , // execution.prepareTakeout(() => { // , // execution.context.emit('takeout_ready'); }); }); return execution.context; });
NB: HTTP API , GET /program-run/events
GET /partner/{id}/execution/events
, . , Apache Kafka Amazon SQS.
, , , , :
-
takeout
takeout_requested
/takeout_ready
; - , API ,
context
, ; - , .
. API , . API : . ? , ; - ( !) , ( ).
, . , :
- , API — ; , , ;
- — , , , .
, — , - .
, , (, ) API, , . program
( , , ); execution
( , , API). , execution
- , - API, program
- , .
, . API, , , , . , UI. , SDK.
, , . , — . :
/* - */ registerProgramRunHandler(apiType, (program) => { // // let execution = initExection(…); // // program.context.on('takeout_requested', () => { // , // execution.prepareTakeout(() => { /* , , */ // execution.context.emit('takeout_ready') program.context.set('takeout_ready'); // : // program.setTakeoutReady(); }); }); // // - // return execution.context; }
, . : , . , , , , . .
, , , :
- , , — ;
- , , API . API , .
, API API , «» «-».
NB: . , — Redux. Redux :
execution.prepareTakeout(() => { // // , // // dispatch(takeoutReady()); });
, , — , API, . ( -) , , : , , .
execution.prepareTakeout(() => { // // , // // program.context.dispatch(takeoutReady()); });
// program.context.dispatch ProgramContext.dispatch = (action) => { // program.context // , // , globalContext.dispatch( // // // // this.generateAction(action); ) }
これは、API開発に関する私の本の次の下位互換性セクションにある2つの新しい章のドラフトです。作業はGithubで行われます。同じ章の英語版がメディアで公開されています。redditで共有していただければ幸いです。私自身、プラットフォームのポリシーに従うことはできません。