Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOS ライブラリをセルフサービスで生成する仕組み

Yusuke Ohashi
September 11, 2022

iOS ライブラリをセルフサービスで生成する仕組み

Yusuke Ohashi

September 11, 2022
Tweet

Other Decks in Programming

Transcript

  1. iOSライブラリをセルフサービスで⽣成する仕組み Sep 11th, 2022 Yusuke Ohashi Architect & SRE Group/Mobile

    Core Team Rakuten Group, Inc.
  2. 2 ⾃⼰紹介 Yusuke Ohashi Application Architect@Rakuten Group, Inc. LT at

    iOSDC 2016(初のiOSDC) in 練⾺ https://github.com/junkpiano https://yusuke.cloud
  3. 3 What Architect team is doing Standardization Productivity Innovation Cross-Platform,

    Cross-Functional team - ソリューションの提供、標準化 - 技術調査、選定 - 開発者の⽣産性向上
  4. 4 セルフサービスとは

  5. 5 セルフサービスとは

  6. 6 セルフサービスとは アプリ、APIを 指定 ユーザーへ デリバリー APIクライアン トの⽣成

  7. 7 Agenda 〜セルフサービスへの道のり〜 背景〜OASの導⼊〜 ⾃動化の仕組みの構築 〜サーバーサイドの整備〜 ⾃動化の仕組みの構築 〜ツール&UIの開発〜 Swiftコード⽣成の実例 まとめ&告知

  8. 8 OASとは - https://www.openapis.org/ - Open API Specificationの略 - APIのデザインドキュメンテーション

    - Method - Headers - Parameters - Response - Etc. - YAML, JSONで記述 - Swaggerとの違い - ここではOASの実装やツールの総称としてSwaggerを使う - https://swagger.io/blog/api-strategy/difference-between-swagger-and-openapi/
  9. 9 OASとは

  10. 10 OASとは Swagger UI https://petstore.swagger.io

  11. 11 OASとは Swagger Codegen – Client SDK/Server Stub Generator https://swagger.io/tools/swagger-codegen/

    https://github.com/swagger-api/swagger-codegen
  12. 12 背景〜OASの導⼊〜

  13. 13 APIの乱⽴によるクライアントの複雑化

  14. 14 背景 〜OASの導⼊〜 API API API API API API *

    2022/08/01 時点
  15. 15 背景 〜OASの導⼊〜 - クライアントにロジックが集中 - スパゲッティコード化しやすい - iOS/Androidで機能の差分が出る

  16. 16 モバイルアプリの機能に合わせたAPIへ

  17. 17 背景 〜OASの導⼊〜 BFF API Gateway API Gateway API API

    API API API API How to design? * 2022/08/01 時点
  18. 18 BFFのデザインにOASを導⼊

  19. 19 背景〜OASの導⼊〜 デザイン ->実装 ⾃動化への基盤 開発者の負担減

  20. 20 ⾃動化の仕組みの構築〜サーバーサイド〜

  21. 21 OpenAPI Specificationの管理 Jenkins logo by https://jenkins.io/

  22. 22 OpenAPI Specificationの管理 - API ProviderがGitで管理 - Pull RequestでAPIスペックのレビュー -

    Mobileのエンジニアも修正に参加
  23. 23 OpenAPI Specificationの管理 - Open API Specificationのガイドライン - Yamlのvalidationツールの使⽤ -

    $refをまとめるための、Bundleツールの開発
  24. 24 ここまでがOASの仕込み

  25. 25 ⾃動化の仕組みの構築〜UI及びツールの開発〜

  26. 26 Code Generatorの開発

  27. 27 ⾃前のCode Generatorの開発 - すでにコード⽣成機能は実装されている - なぜ⾃前のcode generatorが必要なのか︖

  28. 28 ⾃前のCode Generatorの開発 Official Custom 不要な依存 あり なし テンプレート変更 難

    容易 テスト モックライブ ラリなどで可 能 容易
  29. 29 ⾃前のCode Generatorの開発 ⾃前のcustom code generatorを作る。 Þ作り⽅ → https://github.com/swagger-api/swagger-codegen/tree/3.0.0 -

    making-your-own- codegen-modules Þこちらで出来たJavaの雛形(maven project)を基にcode generatorを作成 Þテンプレート(mustache)は既存のSwift⽤の実装を参照 ÞJavaの⽅は継承元のクラスから実装を参照 Þドキュメントに乏しい。コードを読みながら書く。
  30. 30 ⾃前のCode Generatorの開発 〜OASの拡張〜 OASのServerブロックを拡張する例 -> サーバーに名前を追加(Vendor Extension)

  31. 31 ⾃前のCode Generatorの開発 〜OASの拡張〜 Yaml, テンプレートの変更例

  32. 32 ⾃前のCode Generatorの開発 〜OASの拡張〜 - 公式のものを使うか、カスタマイズするかは利便性と メンテナンス性のトレードオフ - チームの優先順位に応じて決める -

    Swiftによる実装もあり(未検証) - https://github.com/yonaskolb/SwagGen
  33. 33 誰がコードを⽣成するのか︖

  34. 34 Jenkins Jenkins logo by https://jenkins.io/

  35. 35 Jenkins as Frontend Jenkins is - ⾔わずと知れたCIエンジン - ⾃由な拡張性

    - 豊富なプラグイン - Web Applicationにもなる(APIもある)
  36. 36 Jenkins as Frontend Jenkins logo by https://jenkins.io/ Slave Node

    Master Node
  37. 37 Master Node WebのフロントエンドとしてのJenkins Active Choices https://plugins.jenkins.io/uno-choice/ GroovyスクリプトでDynamicなFormを構築 e.g.) アプリごとに異なるAPI及びバージョンのリストをREST

    APIで取得
  38. 38 Master Node

  39. 39 Master Node https://www.cncf.io/blog/2022/04/06/how-to-render-jenkins-build-parameters-dynamically/

  40. 40 Slave Node Lint - Push Podspec - Push SDK

    Git Git - Pull OAS - Code generation
  41. 41 Delivery Jenkins logo by https://jenkins.io/ Developers

  42. 42 Swiftコード⽣成の実例

  43. 43 Swift Package Manager対応

  44. 44 Package.swift.mustache // swift-tools-version:5.2 // The swift-tools-version declares the minimum

    version of Swift required to build this package. import PackageDescription let package = Package( name: "{{projectName}}", platforms: [.iOS(.v11), .watchOS(.v4)], products: [ .library(name: "{{projectName}}", targets: ["{{projectName}}"]), ], dependencies: [ ], targets: [ .target(name: "{{projectName}}", dependencies: []), ], swiftLanguageVersions: [.v5] )
  45. 45 Package.swift // swift-tools-version:5.2 // The swift-tools-version declares the minimum

    version of Swift required to build this package. import PackageDescription let package = Package( name: ”SampleLib", platforms: [.iOS(.v11), .watchOS(.v4)], products: [ .library(name: ”SampleLib", targets: [”SampleLib"]), ], dependencies: [ ], targets: [ .target(name: ”SampleLib", dependencies: []), ], swiftLanguageVersions: [.v5] )
  46. 46 Protocolと実装クラスの⽣成

  47. 47 Protocolと実装クラスの⽣成 public protocol {{classname}}Protocol { {{#operation}} /** {{#summary}} {{{summary}}}

    {{/summary}} {{#allParams}} - parameter {{paramName}}: ... {{/allParams}} - parameter completion: completion handler to receive the data and the error objects */ func {{operationId}}({{#allParams}}...{{/allParams}}{{#hasParams}}, {{/hasParams}} completion: @escaping ((_ response: {{{returnType}}}?, _ urlresponse: URLResponse?, _ error: Error?) -> Void)) -> URLSessionTask? {{/operation}} }
  48. 48 Protocolと実装クラスの⽣成 public protocol SampleListBFFAPIProtocol { /** SampleList API for

    iOSDC 2022 - parameter authorization: (header) Authorization token - parameter completion: completion handler */ func sampleList(authorization: String, completion: @escaping ((_ response: SampleListResponse?, _ urlresponse: URLResponse?, _ error: Error?) -> Void)) -> URLSessionDataTask? }
  49. 49 Protocolと実装クラスの⽣成

  50. 50 Protocolと実装クラスの⽣成 public class SampleListBFFAPI: SampleListBFFAPIProtocol { /** SampleList API

    for iOSDC 2022 - parameter authorization: (header) Authorization token - parameter completion: completion handler */ @discardableResult public func sampleList(authorization: String, completion: @escaping ((_ response: SampleListResponse?, _ urlresponse: URLResponse?, _ error: Error?) -> Void)) -> URLSessionDataTask? { return ... } }
  51. 51 Swift Concurrency対応

  52. 52 Concurrency対応 /** {{#summary}} {{{summary}}} {{/summary}} {{#allParams}} - parameter {{paramName}}:

    ... {{/allParams}} */ @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) func {{operationId}}({{#allParams}}...{{/allParams}}) async throws -> {{{returnType}}}
  53. 53 Concurrency対応 /** SampleListAPI for iOSDC 2022 - parameter authorization:

    (header) Authorization token. */ @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) public func sampleListAPI(authorization: String) async throws -> SampleListResponse { let request = ... return try await session.sendRequest(with: request) }
  54. 54 Tips - 無いファイルを追加するときはcode generatorの実装が不可⽋ - Package.swiftの実装 - Protocolの定義など -

    本当に複雑な処理は素直に別にライブラリにする⽅が無難 - ネットワークの実装は単独のライブラリ(共通の実装) - 独⾃の認証処理など - Templateにちょっと何か付け⾜すくらいなら公式のcode generatorで⼗分 - 若⼲の処理の変更 - 関数にコメントを加えるなど
  55. 55 まとめ

  56. 56 Takeaways OASベースのコード⽣成の仕組みの整備 Jenkinsを利⽤したセルフサービスのUI構築 ツール内製の強みを⽣かしたテンプレートの拡張 Swiftはテンプレートに馴染みやすい⾔語

  57. 57

  58. None