API出力制御のシリアル化の重要性





この記事では、著者はデータとオブジェクトの表示を変更する問題と、この変更に必然的に追随する妨害を検討します。 そのような場合、どこでも、どこでも、あるプレゼンテーション形式を別の形式に可逆的に変換できるシリアライザを使用することを提案します。 これにより、ネットワーク経由でデータを転送してファイルに保存するだけでなく、 カスタマイズされたシリアル化ライブラリがある場合、プロジェクトを妥協することなく、都合の良いときにデータストアを変更できます。 また、リクエスターが便利に受信できる形式で応答を返すことも簡単になります。



免責事項 habrahabr.ru/post/260975を読み始めました 翻訳は非常に不器用でハッキーです。 特定のフレーズを翻訳するための耳のオプションに慣れている著者に、彼がすべてを修正するために書くことを始めましたが、読んだときに3つおきのフレーズでつまずくことに気付きました。 私は自分のバージョン全体を切り裂くことにしました。 これは完全に正直ではありませんが、翻訳をこのレベルで強制的に読むことはあまり人間的ではありません。 私も非常に機械的に言うでしょう。 まあ、コミュニティの裁判官にさせてください。 テキストは本当に複雑です。コメントは斜体で残します。 私はすでにdrondoの翻訳見ることなく翻訳ています。 一致する場合、変更しません。 それでも、私は英語の単語をdrondoのような最も類似したロシア語に翻訳しますが、悪魔は詳細にあります。 PMのタイプミスについてお知らせください。午前中にすべてを修正します。 ありがとう



その年、私はAPIの危険な場所について何千回も話しました。 2015年にのみ:





私が「データへのプレゼンテーションレイヤーの追加」と呼んでいるレポートの一部(シリアル化について説明している部分)は、大きな反応を得ました。



MSDNは次のように言っています:

シリアル化とは、オブジェクトを保存したり、メモリ、データベース、またはファイルに転送するために、オブジェクトをバイトストリームに変換するプロセスです。 その主な目的は、オブジェクトの状態を保存して、必要に応じて再作成できるようにすることです。 逆のプロセスは、逆シリアル化と呼ばれます。

ソース: 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」 (approx.per。:PlaceController)を使用した例では、内部使用のために「連絡先メール」を追加する必要がある場合があります。 数か月かけて仕事をして独自の接続を確立した場合(おおよそTransl。:ビジネスで) 、これらの住所を競合他社に流したくないでしょう。



はい、多くのORMでは、表示または非表示のプロパティのリストを指定できます。 しかし、時間が経つにつれて、すべての重要なオプションを隠す可能性はなくなります。 特にあなたが後輩になった場合、これらの分野の1つが極秘であることをまだ知らない人。 忙しい一日で疲れた審査官は、すべてが気付かれずに漏れることができます。



これは、私のPHPシリアル化ライブラリであるFractalの 1つの例です。これは、APIでのシリアル化を簡単にするために行いました。



 <?php use League\Fractal\Manager; use League\Fractal\Resource\Collection; // Create a top level instance somewhere $fractal = new Manager(); // Ask the ORM for 10 books $books = Book::take(10)->get(); // Turn this collection $resource = new Collection($books, function(array $book) { return [ 'id' => (int) $book->id, 'title' => $book->title, 'year' => (int) $book->yr, 'author' => [ 'name' => $book->author_name, 'email' => $book->author_email, ], 'links' => [ [ 'rel' => 'self', 'uri' => '/books/'.$book->id, ] ] ]; });
      
      





はい、ここでもすべてが非常に単純化され、クラスの代わりにコールバックが使用されますが、主なアイデアは明確です。



同じツールは、世界中のすべての言語で使用できます。 ActiveModel Serializerを使用しました 。 彼はほとんど同じです。



今週使用する言語に関係なく、なぜこれがそれほど重要なのかを説明したいと思います。 これを行う方法は、あなた自身で調べることができます。 そして、この記事はその理由についてです。



属性データ型



データバインディングドライバーに関しては、PHPを含む多くの言語はあまりスマートではありません。 MySQLやPostgreSQLのようなものには、整数、浮動小数点、ブールなどの多くの種類のデータ型があります。 しかし、ユーザーに来るのは常に文字列です。



真と偽の代わりに、「1」と「0」、さらには「t」と「f」が表示されます。 -41.235からの浮動小数点数は「-41.235」に変換されます。



タイピングが弱い言語では、これはそれほど重要ではないように思われるかもしれません。 しかし、そのような変更が発生すると、強く型付けされた言語が飛び出します。 ORMプロセッサーの何らかの種類の数学により、数回の文字列が整数に変わることが何度か見られましたが、「1」+「2」= 3です。 。 しかし、iOSアプリケーションの場合、これは単に頭を吹き飛ばします。



RailsのActiveRecordは、移行によってスキーマに追加されたときにデータ型がどのフィールドであるかを追跡します。 しかし、アクセッサで、または回路の種類を変更するときに、何かが変更された場合は、トラブルを待ちます。



上記の例のようにシリアル化を使用する場合、データに自分で型をキャストできます。出力時には、必ず同じ型であり、シリアライザーで自分で変更した場合にのみ変更されます。



フィールド名を変更



データウェアハウスのフィールドの名前を変更しても、APIが破損することはありません。 すべてのテストを更新するのが苦痛に思える場合は、モバイル開発者や他のフロントエンドチームが新しいアプリケーションを更新および展開する方法を想像してください。 ロックステップを忘れたかもしれません(注:このケースの翻訳に協力が必要です。ロシア語の最も近い単語は、一見面白いと思われますが、「並列化」されていることがわかります) 。 その場合、ユーザーは機能しないアプリケーションを使用していることに気付くでしょう。iOSでアップデートをリリースしても、アップデートするまでは機能しません。



フィールド名を変更するというこの地獄を回避するために必要なのは、シリアル化レイヤーです。これにより、外観を変更せずにフィールドへのリンクを更新できます。



さまざまなデータウェアハウス



これらのORMシリアル化方法の多くには、非常に重要な仮定が1つあります。すべてのデータは常に同じストレージに存在します。 そして、データの一部がSQLを離れてRedisまたは他の場所に移動した場合はどうなりますか?



データの一部をSQLからRedisに転送しなかった場合でも、テーブルを2つに分割できますか? または、ピボットテーブルを使用し始めましたか? ほとんどのORMシリアライザーは、試してみると簡単に機能します。 (注:誰かが興味を持っているなら、それは「彼らの顔に着地する」でしょう-彼らの顔に着地します。この表現にはかなりの残酷さと無礼が投資されているので、私はこれを非常に適切な言葉に翻訳することにしました)



または、代わりに、Laravelで非常に人気のある「リポジトリ」パターンを使用しますか? すべてのデータを、保存されている場所からシリアライザに転送できます。シリアライザは結果の一貫性を処理します。



シリアライザーのバージョン



かつて、異なるバージョンのシリアライザーがありました。 v1およびv2のFooSerializerは両方とも存在でき、それぞれに独自のテストがあり、APIクライアントのさまざまなニーズを満たします。 (約。私はそれが何であるか理解できませんでした。おそらくv1とv2は非常に異なっているため、独立した製品として認識され、並行して存在しています)



シリアライザーの形式



Fractalはまだ成功していませんが、v1.0で修正される予定であるのは、フォーマットのさまざまな「アダプター」です。 これはすでにRailsコミュニティで行われています-異なるヘッダーを送信し、異なる応答形式を受信できます。







MIMEタイプを送信することで、潜在的に複雑なロジックですべてのコードを詰まらせることなく、応答を送信する形式でシリアライザーに伝えることができます。



解決策



飛行する理由を説明することはできましたが、今日、私の飛行機は午前5時に着陸し、隣の席の人たちは一晩中眠らせませんでした。



シリアル化の理由については説明しましたが、方法については説明しませんでした。 これについては、次のソリューションをご覧になることをお勧めします。





RailsConf 2015で、新しい友人であるJoãoMouraの素晴らしいレポートを聞きました。AMSLove Story、API、RailsおよびDevelopと呼ばれ、いくつかのクールな機能が明らかになっています。



どのシステムを選択しても、どこにでも1つのアイデアがあります。



あらゆる種類のAPIを作成している場合は、これを使用してください。



APIは、SQLコマンドの単なるプロキシではありません。 計画、検討、および慎重な保守が必要です。 そして、保管場所を変更するだけでは、すべてのネットワークアプリケーションとサービスが損なわれることはありません。



All Articles