API * Lyonsについては、昨年1回話しました。 シリアル化を「
プレゼンテーション層をデータに追加する 」という話をしたとき、多くのレビューと質問が生じました。
MSDNは次のように言っています:
シリアル化とは、オブジェクトを保存したり、メモリ、データベース、またはファイルに転送するために、オブジェクトをバイトストリームに変換するプロセスです。 主な目標は、必要に応じてオブジェクトを復元できるように、オブジェクトの状態を保存することです。 逆のプロセスは、逆シリアル化と呼ばれます。
PHP開発者は、多くの場合、シリアル化プロセスを
serialize ()関数を使用していると
見なします。 はい、これはシリアル化の1つの形式ですが、存在しません。 別の一般的なデータシリアル化のアプローチは、
json_encode ()関数を使用することです。 現在、最新のフレームワークは、コントローラーメソッドから返された配列をJSONに自動的に変換します。
つまり、json_encode ()を呼び出す必要さえありません。
この機能は十分便利ですが、HTTP API(
AJAX / RESTful / Hypermedia )を作成する場合は、返されるものをより正確にする必要があります。
最も一般的な違反は次のとおりです。
<?php class PlaceController extends CoreController { public function show($id) { return Place::find($id); } }
簡略化されたコードで申し訳ありませんが、ここではモデル(
おそらくORMを使用 )を取得し、結果を直接返します。
これは非常に無害なアクションのように見えますが、多くの問題につながります。
隠れない
メソッドAPIを実行するときに、すべてのフィールドを出力に追加します。 これが内部APIである場合、これは正常である可能性がありますが、そのような情報がブラウザのどこにでもある場合、または何らかの形でモバイルデバイスの境界を超える場合、本当に最高の時間はありません。
一般的な例は、ユーザーパスワードです。 もちろん、データは暗号化されていますが、明らかにあなたはそれが間違った手に落ちることを望んでいません。
あまり目立たないものはパスワードリセットトークンであり、そのリークはユーザーのハッキングにつながる可能性があります。
しかし、問題はもっと隠されているかもしれません。
Placeの例では、内部使用専用の連絡先
メールを追加するように求められたときに、機密情報がビジネスから漏洩する可能性があります。 これらの場所を数か月かけて収集し、多くのユニークな連絡先を作成した場合、潜在的な競合他社にすべてのデータが漏洩することは望ましくありません。
ありフィールドはデフォルトで非表示にする必要があり、コードレビュアーの疲労により、この問題が忙しい日に深く浸透する可能性があります。
たとえば、APIアプリケーションのシリアル化を支援するために作成したPHPシリアル化ライブラリ
Fractalは、簡単な例です。
<?php use League\Fractal\Manager; use League\Fractal\Resource\Collection;
これもロジックのクラスの代わりにコールバック関数を使用した単純化された例ですが、一般的な考え方があります。
このようなツールは多くの言語に存在します。
ActiveModel Serializerライブラリを使用しましたが、これはほぼ同じように設計されています。
今週使用する言語に関係なく、これが非常に重要な理由を説明したいと思います。 後でこの問題の解決策を見つけるかもしれませんが、この記事の主な目的はこの問題の重要性を強調することです。
属性データ型
PHPを含む多くのプログラミング言語は、データバインディングドライバーに関しては非常に馬鹿です。 MySQLやPostgreSQLのようなものには、
integer 、
float 、
booleanなどの多くのデータ型がありますが、ユーザーが出力で受け取るものはすべて
通常の文字列です。
trueとfalseの代わりに、「
1 」と「
0 」、あるいは「
t 」と「
f 」が表示されます。 出力の浮動小数点数は、
-41.235ではなく「
-41.235 」を表します。
弱く型付けされた言語の場合、これは特に重要ではないように思われるかもしれませんが、強く型付けされた言語は、そのような変更により落ちます。 ORMプロセッサの数学的操作中に数値の文字列表現が数値型に変更されると、特に不快になります。この場合、「1」+「2」= 3になります。 「
iOSアプリケーションを半分まで壊してしまいます 。」
RailsのActiveRecordは、移行によってスキーマに追加されたフィールドに応じて存在するフィールドのタイプを追跡しますが、これらの変更がアクセサまたはスキーマのデータタイプの変更によって行われた場合、これも問題を引き起こします。
上記の例のように、シリアル化を使用して、データ型を変換して目的の出力形式を提供できます。この型は、シリアライザー自体に変更を加えた場合にのみ変更されます。
フィールドの名前を変更する
データウェアハウスのフィールドの名前を変更しても、APIに違反することはありません。 すべての統合テストを更新する必要があることにうんざりしている場合は、モバイルアプリケーションの開発者、または新しいアプリケーションを更新および展開する必要がある他のフロントエンドチームにとって、これがどれほど煩わしいかを考えてください。 おそらく、ロックステップ展開についても覚えていないかもしれません。 そうでない場合は、エンドユーザー向けに機能しないアプリケーションを取得します。iOS用の更新プログラムを展開しても、ユーザーが手動で更新するまで、アプリケーションは引き続き機能しません。
この問題を回避するには、シリアル化レイヤーのフィールドの名前を変更する必要があります。これにより、外部表現を変更せずに、置換されたフィールドのデータへのリンクを更新できます。
複数のデータウェアハウス
シリアル化プロセスのほとんどのORMソリューションでは、1つの誤解があります-すべてのデータは1か所に保存されます。 一部のデータがSQLからRedisまたは他の場所に流れるとどうなりますか?
データの一部をSQLからRedisに移動しない場合でも、1つのテーブルを2つに分割するか、ピボットテーブルを使用できます。 この場合、これを行おうとすると、ほとんどのORMシリアライザーが
顔に当たり
ます 。
代わりに、
Laravelで一般的になった
Repositoryパターンを使用できます。
リポジトリからすべてのデータを転送でき、シリアル化ライブラリで見つけることができます。シリアライザ自体は出力を変更しません。
バージョン管理シリアライザー
以前、メジャーバージョンのシリアライザーをバージョン管理しました。 FoodSerializerのV1とV2の両方が存在し、テストが異なり、クライアントAPIの多数のニーズを完全に満たします。
シリアライザーの形式
Fractalは完全に何かを達成していません-それはマルチフォーマットの「アダプター」ですが、バージョン1.0でこれを修正しようとしています。 これはRailsコミュニティでかなりうまく実装されており、異なるヘッダーを送信して完全に異なるデータ形式を取得できます。
送信するMIMEタイプに応じて、潜在的に複雑なロジックでコードを詰まらせることなく、出力で必要なデータ形式をシリアライザーに伝えます。
解決策
シリアル化を使用する価値がある理由を説明しましたが、使用方法は説明しませんでした。 これを行うには、次のソリューションをご覧ください。
どのシステムを選択しても、同様のアイデアがあります。 APIを作成する場合は、これを使用してください。
APIはSQLコマンドのプロキシであるだけでなく、APIを計画し、慎重に考え、保守する必要があり、データウェアハウスへの簡単な変更がアプリケーションとサービスのネットワーク全体を破壊しないように注意してください。