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.

    View Slide

  2. 2
    ⾃⼰紹介
    Yusuke Ohashi
    Application Architect@Rakuten Group, Inc.
    LT at iOSDC 2016(初のiOSDC) in 練⾺
    https://github.com/junkpiano
    https://yusuke.cloud

    View Slide

  3. 3
    What Architect team is doing
    Standardization
    Productivity
    Innovation
    Cross-Platform, Cross-Functional team
    - ソリューションの提供、標準化
    - 技術調査、選定
    - 開発者の⽣産性向上

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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/

    View Slide

  9. 9
    OASとは

    View Slide

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

    View Slide

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

    View Slide

  12. 12
    背景〜OASの導⼊〜

    View Slide

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

    View Slide

  14. 14
    背景 〜OASの導⼊〜
    API
    API
    API
    API
    API
    API
    * 2022/08/01 時点

    View Slide

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

    View Slide

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

    View Slide

  17. 17
    背景 〜OASの導⼊〜
    BFF
    API
    Gateway
    API
    Gateway
    API
    API
    API
    API
    API
    API
    How to design?
    * 2022/08/01 時点

    View Slide

  18. 18
    BFFのデザインにOASを導⼊

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  22. 22
    OpenAPI Specificationの管理
    - API ProviderがGitで管理
    - Pull RequestでAPIスペックのレビュー
    - Mobileのエンジニアも修正に参加

    View Slide

  23. 23
    OpenAPI Specificationの管理
    - Open API Specificationのガイドライン
    - Yamlのvalidationツールの使⽤
    - $refをまとめるための、Bundleツールの開発

    View Slide

  24. 24
    ここまでがOASの仕込み

    View Slide

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

    View Slide

  26. 26
    Code Generatorの開発

    View Slide

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

    View Slide

  28. 28
    ⾃前のCode Generatorの開発
    Official Custom
    不要な依存 あり なし
    テンプレート変更 難 容易
    テスト
    モックライブ
    ラリなどで可

    容易

    View Slide

  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の⽅は継承元のクラスから実装を参照
    Þドキュメントに乏しい。コードを読みながら書く。

    View Slide

  30. 30
    ⾃前のCode Generatorの開発 〜OASの拡張〜
    OASのServerブロックを拡張する例
    -> サーバーに名前を追加(Vendor Extension)

    View Slide

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

    View Slide

  32. 32
    ⾃前のCode Generatorの開発 〜OASの拡張〜
    - 公式のものを使うか、カスタマイズするかは利便性と
    メンテナンス性のトレードオフ
    - チームの優先順位に応じて決める
    - Swiftによる実装もあり(未検証)
    - https://github.com/yonaskolb/SwagGen

    View Slide

  33. 33
    誰がコードを⽣成するのか︖

    View Slide

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

    View Slide

  35. 35
    Jenkins as Frontend
    Jenkins is
    - ⾔わずと知れたCIエンジン
    - ⾃由な拡張性
    - 豊富なプラグイン
    - Web Applicationにもなる(APIもある)

    View Slide

  36. 36
    Jenkins as Frontend
    Jenkins logo by https://jenkins.io/
    Slave Node
    Master Node

    View Slide

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

    View Slide

  38. 38
    Master Node

    View Slide

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

    View Slide

  40. 40
    Slave Node
    Lint
    - Push Podspec
    - Push SDK
    Git Git
    - Pull OAS
    - Code generation

    View Slide

  41. 41
    Delivery
    Jenkins logo by https://jenkins.io/
    Developers

    View Slide

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

    View Slide

  43. 43
    Swift Package Manager対応

    View Slide

  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]
    )

    View Slide

  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]
    )

    View Slide

  46. 46
    Protocolと実装クラスの⽣成

    View Slide

  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}}
    }

    View Slide

  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?
    }

    View Slide

  49. 49
    Protocolと実装クラスの⽣成

    View Slide

  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 ...
    }
    }

    View Slide

  51. 51
    Swift Concurrency対応

    View Slide

  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}}}

    View Slide

  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)
    }

    View Slide

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

    View Slide

  55. 55
    まとめ

    View Slide

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

    View Slide

  57. 57

    View Slide

  58. View Slide