2016-06-20 16 views
0

RESTful APIのURIをバージョン管理するためのベストプラクティスをたくさん読んでいますが(例:http://api.example.com/v1/users - >http://api.example.com/v2/usersおよびHATEOAS)、コード内のディレクトリまたは名前空間の構造に関することはあまりありませんベース(PHP + silexフレームワーク)。 コードベースは、現在、複数のバージョンのAPIをサポートしています.VoltまたはAcceptヘッダーを認識し、識別されたAPIバージョンに基づいて異なるコントローラ/クラス/メソッドを呼び出すことができます(v1のv1のUserController::listUsers()、v2 :UserControllerV2::getListUsers())。 APIのバージョンはますます多くなりますが、ある時点で古いバージョンをコードベースから削除する必要があります。ディレクトリ/名前空間バージョン管理されたREST APIの構造

だから、質問はバージョン管理する必要がありますどのようなクラス

  • ですか? (コントローラー、モデル、ビューなど)
  • ドメイン駆動型デザインのバンドルをしたときのやり方は? (完全なバンドルディレクトリのバージョン、またはバンドルの中身のみ?)
  • どのようにバージョン管理する必要がありますか?少ないコードの重複と(クラスの継承(どうやって?)、ディレクトリ構造...)
    • 、古いバージョンの
    • 容易に除去
    • 少ない副作用バージョン
    • の間で共有されますバグ修正に何かあれば

Current srcpublicvendorは1つのレベルアップしている):

. 
    └── TestNext 
     ├── ApiV1 
     │   └── Route 
     │    └── ApiV1RoutesProvider.php 
     ├── Configuration 
     │   ├── Controller 
     │   ├── Loader 
     │   │   └── YamlConfigLoader.php 
     │   ├── Model 
     │   └── Service 
     │    └── SymfonyConfigServiceProvider.php 
     ├── Security 
     │   └── Authenticator 
     │    └── TokenAuthenticator.php 
     ├── Shared 
     │   └── Controller 
     │    └── BaseController.php 
     ├── User 
     │   ├── Controller 
     │   │   └── UserController.php 
     │   ├── Model 
     │   └── Service 
     ├── Bootstrap.php 
     ├── Console.php 
     └── Constants.php 

答えて

2

まず第一に、それは概念を離れて分離する価値があります。あなたにはドメインがあり、API層があります。レイヤーを作成した後、API層はドメインの上に位置する必要があります。ドメインはAPIの存在を完全に意識する必要がありません。

src/Acme/Api/ 
src/Acme/Core/ 

APIのすべてがHTTPレベルの通信を処理します。これは、次のようなものです。ルーティング、要求&レスポンスマッピング、ステータスコードなど

コアのすべてがビジネス関連の操作を処理します。 CQRSスタイルのアプローチに続いて、あなたのようなもので終わることができます:

src/Acme/Api/Controller 
src/Acme/Api/DTO/Request/ 
src/Acme/Api/DTO/Response/ 
src/Core/Domain/ 
src/Core/Command/ 
src/Core/CommandHandler/ 
src/Core/Infrastructure/ 
src/Core/ReadModel/ 

しかし、実際に、レイアウト&命名が柔軟になるだろう、それは多少あなたが適用しているものの建築パターンにより異なります。 DDDコンテキストでは、集約、モデル、値オブジェクト&のリポジトリを共通の名前空間(Domain)の下に置くことが重要です。

は、個々の問題に対処するには、次のどのようなクラス

をバージョン管理すべきですか? (コントローラ、モデル、ビューなど)

私の考えでは、バージョンモデルには意味がありません。モデルは常にビジネスの最新の表現でなければならず、より古いのルールを維持することは不要と思われる。

バージョン管理はどのように処理するかはあなた次第です。それを完全なAPI(パス+要求/応答ペイロード)にバージョンアップする方法として扱うこともできますし、要求/応答ペイロードだけをバージョンすることもできます。 APIを完全にバージョン管理することはおそらく最も柔軟ですが、そのような劇的な変更を行うことは比較的まれです。 Accept/Content-Typeヘッダーを利用して、要求レベルごとにバージョン管理することを検討してください。両方の組み合わせを使用することもできます(URLのメジャーバージョンバンプを使用してパスを再定義し、特にContent-Typeのバージョンを強制します)。

さらに理論的には、要求/応答のペイロードを定義するJSONスキーマをバージョンアップすることができます。

GET /1.0/user/317684e2-3704-11e6-8172-b0bea8105888/payment/2caad76e-3705-11e6-8172-b0bea8105888 
Accept: application/vnd+acme+json; schema=payment.out.v1.json 

HTTP/1.1 200 OK 
Content-Type: application/vnd+acme+json; schema=payment.out.v1.json;  charset=UTF-8 

{ 
    "payee": "Bob Dylan", 
    // snip 
} 
``` 

レスポンス・ペイロードに非後方互換性の変化を紹介したい場合は、あなたは、クライアントが支払いのために「V2」JSON Schemaに対して要求できるようにすることができます:例として

GET /1.0/user/317684e2-3704-11e6-8172-b0bea8105888/payment/2caad76e-3705-11e6-8172-b0bea8105888 
Accept: application/vnd+acme+json; schema=payment.out.v2.json 

HTTP/1.1 200 OK 
Content-Type: application/vnd+acme+json; schema=payment.out.v2.json; charset=UTF-8 

{ 
    "payee": { 
    "forename": "Bob", 
    "surname": "Dylan" 
    }, 
    // snip 
} 

メジャーAPIバージョンは変更されていませんが、応答ペイロードは異なります。古いバージョンを廃止するか、または主要なAPIバージョンをバンプして、ペイロードレベルで最小値を設定することができます。

Content-Typeヘッダーを利用することで、リクエストボディに同じ手法を適用できます。

ドメインドリブンデザインをバンドルしたときにどうしましたか? (完全なバンドルディレクトリをバージョンアップするか、バンドルの中に入れる?) バージョン管理はどうすればよいですか?

恐らくすでに答えられていますが、Symfonyスタイルのバンドルについて考えることはできません。 Core、またはそれを呼びたいものは、それに固有のSymfony/Silexを何も持たないはずです。 Infrastructureでは、おそらくDoctrineを使用してRepositoryインターフェースの実装をしているかもしれませんが、それはsymfony/Silexをフレームワークとして使っているのではなく、Doctrineをライブラリとして活用しています。理論的には、全く違うフレームワークのためにAPIレイヤーを交換してCoreに変更することができます。

ただし、避けられないものがいくつかあります:依存性注入&設定。 symfonyではこれまでこれを解決するためにCoreBundleを作成しました。これはCoreの外にあります。

ちなみに、このようなプロジェクト内では1つの限定されたコンテキストのみを包含するのが賢明かもしれませんので、もっと分類することを心配しないでください。少ないコードの重複で

それは重複が発生することは避けられないですが、あなたは動作を定義するオブジェクトをバージョン管理されないので、これは唯一、あなたのDTOの場合でなければならないとき(あなたのモデル) 。 DTOでの複製は実際には大きな問題ではありません。失われたものよりも明快さが得られれば、バージョンごとにクラスを定義するだけです。ツールはコピーされたコードをコードに伝えるかもしれませんが、そのようなコンテキストを理解できるツールではありません。

古いバージョンを容易に除去

あなたが別々のDTOを定義する場合、そのような作業は簡単でなければなりません。 DTOを削除し、JSONスキーマを削除します。これで、APIは指定された古いバージョンのリクエストを拒否します。

少ない副作用、あなたのAPI層で/レスポンスオブジェクトを要求するためにマッピングされている場合はバージョン

の間で共有されますバグ修正何かが、それは、変更によって影響を受けることができ、あなたのマッピングコードだ場合モデルで。 API契約テスト、インプロセスコンポーネントテスト、単体テストなどのテストでは、モデルの変更によってAPIのすべてのバージョンが異なる動作をしないことを確認する必要があります。

関連する問題