インターフェースの戻りデータ構造について話しましょう

少し前に、インターフェースのレスポンス形式について議論しているツイートをいくつか見かけました。そのコメント欄には、戻り値にコードとエラーメッセージを含める必要はなく、HTTPコードとコード情報だけで十分であり、単に時間の無駄だという不満が多く寄せられていました。今日は、私の考えについてお話ししたいと思います。  

**以下で説明するインターフェース応答構造はすべて、ブロガーのオープンソース フレームワーク go-sail に基づいています。**  
> 倉庫住所: [https://github.com/keepchen/go-sail](https://github.com/keepchen/go-sail)  

まず、go-sail のインターフェース応答のフィールドを見てみましょう。  
```json  
{
  "code": 200,
  "data": null,
  "message": "SUCCESS",
  "requestId": "5686efa5-c747-4f63-8657-e6052f8181a9",
  "success": true,
  "ts": 1670899688591
}
```  
インターフェース型（他の言語ではジェネリック型と考えることができます）である「data」フィールドを除き、他のフィールドは明確なデータ型です。それぞれに独自の意味と適用シナリオがあります。  

それでは、フィールドの意味を1つずつ説明しましょう。  
- **code**  
ビジネス コードの int 型は、Javascript 言語の数値型、または Java 言語の int 型または Integer 型に対応します。  

- **data**  
データ本体は、ビジネスにおける特定のデータ応答エンティティです。この型はGo言語のインターフェースであり、他の言語のジェネリック型に対応できます。  

- **message**  
プロンプトメッセージ、string列型。  

- **requestId**  
リクエストの一意の識別子、string列型。  

- **success**  
成功か否かを示すブール型。ビジネスロジック処理が成功したかどうかを確認するために使用されます。  

- **ts**  
システムの現在のミリ秒タイムスタンプ、int64型。これは、Javascript言語の数値型とJava言語のLong型に対応します。。  

### code  

リクエストが成功した場合、HTTPステータスコードは既に200なので、ここで再度200を書き込むのは時間の無駄だと言う人が多いようです。以下に説明を記します。 

1. go-sail が提供するデフォルトのコード値は 0 です。使用中、開発者は必要に応じて成功コードを[指定](https://go-sail.dev/ja-JP/docs/concepts/constants/)できます。
2. 成功コードは 0 以外の値に設定することをお勧めします。これは、ボトムアップソリューションを考慮すると、どこかの呼び出しでコードに値を割り当て忘れた場合、コード = 0 の状況は設定した 0 以外の成功コードと等しくないため、重要な瞬間に命を救うことができる可能性があるためです（KPI および BUG 率に関する警告 ⚠️）。  

**では、なぜビジネスコードを設定する必要があるのでしょうか?**  

この質問に答える前に、Alibaba Cloud、Tencent Cloud、Qiniu Cloudといったクラウドサービスプロバイダーの機能インターフェースを統合したことがありますか？これらのインターフェースにはすべてビジネスコードがあることに気づいたことがありますか？ここで私が言及しているのは、大衆に倣うためではなく、もしそれらが存在するのであれば、私もそれについて知るべきです。むしろ、ビジネスコードはそれぞれの理由があって存在するものでなければなりません。そうでなければ、それぞれの設計は驚くほど一貫性を持たなくなるでしょう。  

他のデザイナーのアイデアは分かりませんが、私のデザインのアイデアについてお話しします。  

- ビジネスコードは、ビジネスロジックの処理過程で発生するさまざまな問題を可能な限り詳細に表現したり、より多くのビジネス処理状態や中断状態を表現したりできます。  
- ビジネス コードを組み合わせることで、フロントエンドまたはクライアントに優れた多言語サポートを提供できます。  

まず最初の点についてお話ししましょう。一般的なショッピング注文ロジックを例に挙げてみましょう。コード = 1000 は残高不足、コード = 1001 は在庫不足、コード = 1002 は同時競合による購入失敗、コード = 1003 はネットワークジッターによるデータベースへの書き込み失敗などを示します。  

フロントエンドまたはクライアントが対応するコードを取得すると、フロントエンド、コード、およびユーザーの現在のシステム言語のローカライズされた構成に応じて、「申し訳ございません。現在の商品在庫が不足しています」、「現在の残高が不足しています」、「遅れました。商品は売り切れです」など、十分に人間化されたプロンプトをユーザーに表示できます。  

以下は[Stardots](https://stardots.io)のローカライズ練習コードです。  
```json  
TID_API_CODE_200: 'リクエスト成功',
TID_API_CODE_504: 'リクエストタイムアウト',
TID_API_CODE_999999: '内部サーバーエラー',
TID_API_CODE_100000: 'リクエストパラメータが正しくありません。',
TID_API_CODE_100001: 'ログインステータスが無効です',
TID_API_CODE_100002: '人間と機械の検証に失敗しました',
TID_API_CODE_100003: '認証コードが間違っています',
TID_API_CODE_100004: 'アカウントが存在しません',
TID_API_CODE_100005: 'アカウントとパスワードが一致しません',
TID_API_CODE_100006: 'このサブスクリプション情報は見つかりません',
TID_API_CODE_100007: '送信頻度が制限を超えています',
TID_API_CODE_100008: '送信回数が制限を超えました',
TID_API_CODE_100009: '宇宙は存在しない',
TID_API_CODE_100010: 'スペースはすでに存在する',
TID_API_CODE_100011: 'スペースは空ではありません',
TID_API_CODE_100012: '操作頻度が高すぎる',
TID_API_CODE_100013: 'スペースの割り当てが使い果たされました',
TID_API_CODE_100014: 'ファイルクォータが使い果たされました',
TID_API_CODE_100015: '転送トラフィックの割り当てが使い果たされました',
TID_API_CODE_100016: 'サブスクリプションプランが一致しません',
TID_API_CODE_100017: '宇宙ファイルへのアクセス制限',
TID_API_CODE_100018: 'アップロードされたファイルのサイズ制限を超えています',
TID_API_CODE_100019: 'アップロードされたファイル形式はサポートされていません',
...
```  
  
フロントエンドまたはクライアントは、リクエスト インターセプターで統一された処理を実行できます。    
```js  
//エラーメッセージを上書きする
let message = $t(`TID_API_CODE_${respData.code}`)
```  

`$t` は、ブロガー自身が実装した関数で、言語コードに基づいて言語テキストを取得します。ロジックは比較的単純なので、ここでは詳細には触れません。  

これを読んで、少しは共感を覚えたでしょうか?😛  

さらに、上記の一連のビジネスコードは、別のフィールド「success」の値に影響を与え、success を false にしてしまう可能性があります。これについては後ほど詳しく説明します。  

### message  

プロンプトメッセージは、ビジネスコード列挙を定義し、`RegisterCodeTable`関数を使用して登録すると、go-sailは呼び出し時に自動的にプロンプ​​トメッセージの維持を支援します。私の意見では、このプロンプトメッセージは、開発者向け、またはローカライズが完璧でない場合に備えたバックアッププランです。例えば、上記のコード=1000の場合、ローカライズでは対応する言語コードが見つからないため、インターフェースから返されたメッセージフィールド値を使用するようにダウングレードできます。表示効果が「残高が不足しています」から「残高が不足しています」に変わる可能性がありますが、少なくとも使用できますよね？  

とはいえ、go-sailは多言語ビジネスコード登録機能を提供しており、前述のフロントエンドまたはクライアントのローカライズ作業をサーバー側で行うことができます。どのソリューションを採用するかは、具体的なビジネスニーズによって異なります。  

### requestId  

ユニークなリクエスト識別子であるこのフィールドは、トラブルシューティングのための強固な基盤を築くと言えます。go-sail は、可観測性の一角であるコールチェーン ログ トレース機能を提供します。  

インターフェース応答にエラーがある場合は、トラブルシューティングを容易にするために、requestId に基づいて呼び出しチェーンをトレースできます。  

![GVMadgLbkAAcLmr.jpeg](https://i.stardots.io/keepchen/GVMadgLbkAAcLmr.jpeg?width=500&rotate=0&blur=0&quality=100 "GVMadgLbkAAcLmr.jpeg")  

![GVMalvqbwAAjM1w.jpeg](https://i.stardots.io/keepchen/GVMalvqbwAAjM1w.jpeg?width=1920&rotate=0&blur=0&quality=100 "GVMalvqbwAAjM1w.jpeg")  

写真のブロガーはELKログ収集を使用していますが、もちろんコマンドを使用してローカルファイルから表示することもできます。go-sailのログ収集はローカルファイル出力もサポートしています。  

```shell  
tail -f -n 100 ~/your-logfile.log |grep 72a99ac0
```  

> ログローテーション機能によりログはファイルに出力されるため、ディスクがいっぱいになることがなく安心です。  

この時点で、私は以前のように問題に遭遇しても全く分からないという状況ではなくなったと言えます。😎  

製品マネージャーは、フロントエンドまたはクライアントの同僚にプロンプ​​トポップアップウィンドウに requestId を入力するよう依頼することもできます。これにより、問題が発生したときに、ユーザー フィードバックのスクリーンショットで問題を解決できます。  

このような：  
![iShot_2024-12-18_22.01.31.png](https://i.stardots.io/keepchen/iShot_2024-12-18_22.01.31.png?width=500&rotate=0&blur=0&quality=100 "iShot_2024-12-18_22.01.31.png")  

> ヒント: 図は requestId の一部を示しています。  

ユーザーにはほとんど気づかれません。静かに作業が完了します。🐮  

### success  

ビジネスロジックが成功したかどうかを示します。go-sailは、呼び出し時に設定したコードに基づいて、successの値を自動的に保持します。フロントエンドまたはクライアントは、この値を使用して、ビジネスロジックの処理が成功したかどうかを判断できます。この値に基づいて、緑色のプロンプトポップアップウィンドウを表示するか、黄色または赤色のプロンプトポップアップウィンドウを表示するかを決定することもできます。いかがでしょうか？興味深いと思いませんか？  

### ts  
これはタイムスタンプの略語で、システムの現在のミリ秒単位のタイムスタンプを意味します。設計当初は2つの用途を検討しました。  

- 製品の先行販売カウントダウンなど、フロントエンドまたはクライアントがサーバーの時間を厳密に比較する必要がある場合。製品がグローバルユーザー向けの場合に特に便利です。  
- ユーザーが問題、リクエスト、または操作を発見した時刻。フロントエンドまたはクライアントは、この値をローカルに記録したり、トラブルシューティングを支援するために直接表示したりできます。  

**なぜミリ秒なのでしょうか?**  

Webフロントエンド開発者なら、きっと笑ってしまうでしょう。そう、Dateオブジェクトのコンストラクタはミリ秒単位のタイムスタンプを受け取ります。 
 
```js  
let date = new Date(ts)
```  

1000倍にするべきかどうかを考える必要がなく、そのまま使用できるため、使用時の精神的な負担が軽減されます。また、ミリ秒単位の粒度は、ほとんどのアプリケーションシナリオをカバーするのに十分です。  

### data  

ビジネスデータエンティティ。このフィールドは、特定のビジネスロジックのレスポンスデータを読み込むために使用されます。レスポンスデータは、配列、マップ、構造体、または単純な数値、文字列、ブール値のいずれかになります。  

フィールド名の命名は重要ではなく、明確な構造と明確なアイデアが重要です。ブロガーの指示に従ってこの記事のメインコンテンツを完成させた今、どう感じましたか？ぜひコメント欄でご意見をお聞かせください。  

最後に、go-sail オープンソース プロジェクトにぜひご注目ください。  

> 倉庫住所: [https://github.com/keepchen/go-sail](https://github.com/keepchen/go-sail)  

---  

#### 元のブログアドレス [https://blog.keepchen.com/a/talk-about-api-response-structure.html](https://blog.keepchen.com/a/talk-about-api-response-structure.html)