Share
Embed
Transcript
32 slides
-
複数チームのAPI開発でよくある話(2/4) 6 フロント エンド サービスA サービスB このAPI仕様で 提供します! OK、その仕様で クライアントコード書くね
画面項目もバッチリ! {“yen”: 100} {“yen”: 100} 100円 -
複数チームのAPI開発でよくある話(3/4) 7 API仕様に 追加しておくね! Modelを直さなきゃ ごめん、ドル金額も 追加で返してほしい フロント エンド サービスA
サービスB {“yen”: 100, “dollar”: 1.0} {“yen”: 100} 100円 -
複数チームのAPI開発でよくある話(4/4) 8 昨日リリースしたよ ごめん、古い版を見てた あれ、レスポンスに 項目Bがないんだけど フロント エンド サービスA サービスB
{“yen”: 100, “dollar”: 1.0} {“yen”: 100} 100円 (0ドル) -
ワラフォーさん(仮名) • 手戻りのないようにレビューを徹底するのじゃ • Excel様式でしっかり設計するのじゃ アージャイルさん(仮名) • チーム横断のミーティングを設けよう! • フィーチャーチームだ!
Team 解決策? 9 Team フロント エンド サービスA サービスB -
複数チームによるAPI開発の課題 目を背けてはいけない事実: • 完全なAPI仕様を初期に決めることは不可能 • API仕様の変更には相応のコストがかかる • 完全に独立したフィーチャーチームは作れない インクリメンタルなAPI設計に必要なもの: 1.
複数のチームが安全にAPI仕様を変更できる仕組み 2. 担当者やツールがボトルネックにならないこと 10 -
解決策1:API仕様の共同所有 API仕様を提供側チームと利用側チームで共有する。Pull Requestを通して変更やレ ビューを進めることで、共通認識を作る。 11 API仕様 利用側 チーム 提供側 チーム
• 提供側チームが主体的に管理 • Gitのバージョン管理やPull Requestによ るレビューに適したテキストファイルで記 述 • Excelは適さないのでダメ -
解決策2:API Client, Serverのペア生成 API仕様からAPI Client, Serverのコードを生成する。 API Client Libraryは利用側チームに提供する。 12
利用側AP 提供側AP Client Server API仕様 利用側 チーム 提供側 チーム Client Server 必ず同一の 仕様になる -
解決策3:Semantic Versioning 破壊的な仕様変更をインクリメンタルに取り込めるようにする。 13 利用側AP 提供側AP Client Server API仕様 (1.1.0)
Client Server API仕様 (1.0.0) Client Server 1.1.0に上げて、 コンパイル エラーを修正 -
コード生成の光と影(1/2) 14 Pros. • 同一の仕様からClient, Serverを生成するので等価性を保証できる • 単純作業(量産体制)を排除してチームを小さく保つ Cons. •
自動生成されたコードを修正すると、仕様変更がカオス化 • ツール職人がボトルネックになりがち -
コード生成の光と影(2/2) Good use cases • 宣言の自動生成(Controller、モデル) • ビルド時に動的にコードを生成する(Ephemeral) • 汎用的なツール(オープンソース)
Bad use cases • ロジックの自動生成 • 仕様とソースコードの二重管理(Excel) • 特定の場合にしか使えない 15 -
ビルドツールで自動的にコード生成を実行する。 • 自動生成されたコードを修正できない仕組みを強制する • 開発者がコード生成を意識しない 16 解決策4:ビルドシステムにコード生成を組み込む Executable JAR API仕様
(YAML) Client (Java) Server (Java) アプリケーション Client JAR Nexus デプロイ APIドキュメント (HTML) S3 中間生成物 -
OpenAPI Specification(Swagger) REST APIの仕様を記述するための規格 • OpenAPI Initiativeが策定 • 現在はOpenAPI 2.0
主要なツールセット • Swagger Editor(エディタ) • Swagger UI(ビューア) • Swagger Codegen(コード生成ツール) 18 -
paths: /pets: get: responses: "200": schema: type: "array" items: $ref:
"#/definitions/Pet" definitions: Pet: type: "object" properties: id: type: "integer" format: "int64" name: type: "string" https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/yaml/petstore-minimal.yaml YAML Swagger Editor Swagger UI http://editor.swagger.io 19 -
Swagger Codegen OpenAPI仕様からソースコードを生成するツール • 多くの言語やフレームワークに対応 https://github.com/swagger-api/swagger-codegen API clients: ActionScript, Apex,
Bash, C# (.net 2.0, 4.0 or later), C++ (cpprest, Qt5, Tizen), Clojure, Dart, Elixir, Go, Groovy, Haskell, Java (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign), Kotlin, Node.js (ES5, ES6, AngularJS with Google Closure Compiler annotations) Objective-C, Perl, PHP, Python, Ruby, Scala, Swift (2.x, 3.x), Typescript (Angular1.x, Angular2.x, Fetch, jQuery, Node) Server stubs: C# (ASP.NET Core, NancyFx), C++ (Restbed), Erlang, Go, Haskell, Java (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, RestEasy, Play Framework), PHP (Lumen, Slim, Silex, Zend Expressive), Python (Flask), NodeJS, Ruby (Sinatra, Rails5), Scala (Finch, Scalatra) API documentation generators: HTML, Confluence Wiki Others: JMeter • Executable JARが提供されている • mustacheのテンプレートをカスタマイズ可能 20 -
21 Gradle Swagger Generator Plugin Gradleで各種ジェネレータを利用できるプラグイン • OpenAPI YAMLのバリデーション •
Swagger Codegenによるコード生成 • Swagger UIの生成 • ReDocの生成 https://github.com/int128/gradle-swagger-generator-plugin -
サービス開発におけるOpenAPIの利用 23 ビュー API Client Controller ビジネスロジック API Client PHP7
Spring (Java8) YAML フロントエンド チーム バックエンド チーム Swagger UI API連携でコード生成とAPIドキュメント生成を利用している YAML コンテンツ プロバイダ 外部サービス -
Swagger Codegenテンプレートのカスタマイズ Spring MVCテンプレート(APIサーバ) 1. リクエストモデルのバリデーションを追加 2. 独自バリデータ対応 3. サービスクラスをDIして呼び出すように変更
Spring Cloudテンプレート(APIクライアント) 1. API Proxyの生成 24 -
★リクエストパラメータのチェック (GET) {{#allParams}} {{^isBodyParam}} {{#required}} if ("{{dataType}}".equals("Integer") || "{{dataType}}".equals("Long")) {
if ({{paramName}} == null) { throw new ValidationException("..."); } } {{/required}} ★Bean Validatorのアノテーションを モデルクラスに付加 @DecimalMin("{{minimum}}") @DecimalMax("{{maximum}}") @NotNull @Size(min={{minLength}}{{#maxLength}}, max={{maxLength}}{{/maxLength}}) @Size(max={{maxLength}}) @Pattern(regexp = "{{pattern}}") @Valid Spring MVCテンプレートの改造(1/3) OpenAPIの型や制約に対応するバリデーション処理を追加 25 -
Spring MVCテンプレートの改造(2/3) definitions: Pet: properties: code: type: string x-validations: hiragana:
true 26 public class Pet { @Hiragana @Valid private String code = null; } YAMLのVendor Extensionsで独自のバリデータを指定できるように拡張 (TERASOLUNAが提供しているバリデータ*1を利用) YAML Java (*1) http://terasolunaorg.github.io/guideline/5.3.0.RELEASE/ja/ArchitectureInDetail/GeneralFuncDetail/StringProcessing.html#stringprocessinghowtousecodepoints -
生成したコードを一切修正せずに利用するため、ControllerからServiceの呼び出しを追 加 @RestController public class HelloController { @Autowired private HelloService
helloService; @RequestMapping(“/foo/{id}”) public ResponseEntity<FooRequest> foo(@PathVariable(“id”) int id) { return helloService.foo(id); } public interface HelloService { ... } } Spring MVCテンプレートの改造(3/3) 27 アプリケーション側でServiceを 実装して実行時にDI -
API Proxyの自動生成 フロントエンドと外部サービスをつなぐ一部のAPIはビジネスロジックが必要なかったた め、ControllerからAPIクライアントの呼び出しを自動生成 Controller API Client 28 フロントエンド 外部サービス
YAML バリデーション インターセプタの共通処理 (OAuth、トレースID等) -
ControllerからAPIクライアントの呼び出しを生成 @RestController public class HelloController { @Autowired private final HelloClient
helloClient; @RequestMapping(“/foo/{id}”) public ResponseEntity<FooRequest> foo(@PathVariable(“id”) int id) { return helloClient.foo(id); } } Spring Cloudテンプレートの改造 29 実際にはレスポンスの取捨選択が必要 • Content-Lengthヘッダは返さない • FeignExceptionのハンドリング