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

GraphQLとスキーマファーストで切り開く ライドシェアの未来

GraphQLとスキーマファーストで切り開く ライドシェアの未来

newmoは今年の1月に設立された新しい会社です。"移動で地域をカラフルに" をミッションに掲げ、利用者視点に立ったサステナブルな地域交通の実現を目指すスタートアップです。

newmoではAPIのスキーマ定義に、より多くの情報を記述する宣言的なアプリケーション開発を行っています。スキーマからコードを自動生成することで、APIの挙動が理解しやすくなると同時に、各チームが主体的・自律的に開発が進められる状態を実現します。
モバイルアプリとバックエンドAPIとの通信にはGraphQLを採用しました。ディレクティブを活用して、APIクライアントの生成に留まらない、より宣言的なアプリケーション開発を行っています。

本セッションでは、より安全に、高速にiOS開発を進めていくための弊社の取組みをご紹介します。

GraphQLとディレクティブの活用
バックエンドAPIの進捗に依存せず、主体的・自律的に開発を進めるための工夫
最高のiOS開発体験を実現するための取り組み

https://fortee.jp/iosdc-japan-2024/proposal/d3aa5ef5-e561-45bd-a98a-ee1590e23108

@ku KUMAGAI

August 26, 2024
Tweet

More Decks by @ku KUMAGAI

Other Decks in Technology

Transcript

  1. @ku KUMAGAI 自己紹介
 ku 断続的にiOSをやってきました 2008-2010 iView(プライベート) 2010-2014 GREE 2017-2021

    メルカリ(メルペイ部分) 直近はgolangでバックエンドをやっていま す ku
  2. ライドシェアとタクシーの違い
 • ライドシェア (自家用車活用事業) ◦ 一種免許(普通の運転免許)のドライバー ◦ 自家用車 ◦ タクシー会社と雇用契約

    • タクシー (一般乗用旅客自動車運送事業者) ◦ 二種免許を持つドライバー ◦ 会社の車 ◦ タクシー会社の正社員(が多い) • 両者ともタクシー会社が安全管理を行います ▪ 車両の点検 ▪ 健康状態の確認(飲酒、睡眠不足、etc)
  3. 技術的観点での差分
 • デバイス ◦ タクシー ▪ 会社の車両、メーター、スマホ/タブレット端末 ◦ ライドシェア ▪

    携帯端末はドライバーのものを使ってもらう • アプリの仕様 ◦ 例) 決済 ▪ タクシーは現金OK あと払い ▪ ライドシェアはオンラインで事前決済のみ
  4. アプリ構成
 • iOS 17~ • TCA (the Composable Architecture) •

    apollo-ios (GraphQL client) • Swift Concurrency
  5. 生成されるSwiftコード
 Apolloのコードジェネレータがavailable attributeを生成 します struct UpdateProfile: … { public var

    name: String public var email: String @available(*,deprecated,message:”use birthDate”) public var birthDay: String public var birthDate: String }
  6. 利用例1 入力値のバリデーション
 input UpdateProfileInput { name: String! @validateString(minLen: 1, maxLen:

    64) email: String! @validateString(pattern: EMAIL) } • 有効な値の範囲を示すディレクティブ • extensionとしてvalidate()メソッドを生成して入 力値をアプリ側で検証 • validate()が返すエラーをもとにメッセージを表示
  7. 生成するSwiftコード
 extension GeneratedGraphQLPackage.CreateRideInput { func validate() -> CreateRideValidationError? { guard

    (name.count >= 1 && name.count <= 64) else { return .init(field: .name, message: ”...”) } guard try emailRegex.wholeMatch(in: email) != nil else { return .init(field: .email, message: ”...”) } return nil } }
  8. 利用例2 APIスタブの生成
 type NumberPlate { place: String! @exampleString(value: "品川") classificationNumber:

    String! @exampleString(value: "300") hiragana: String! @exampleString(value: "れ") serialNumber: String! @exampleString(value: "2525") } • 値の具体例を示すディレクティブ • 生成したスタブの返す値を明示
  9. 利用例3 権限の管理
 type Query { carsNearMe(): [Cars!]! } type Mutation

    { requestCar(input:…): RequestCarPayload! @requiresMembership } • 認証が必要かどうかを表すディレクティブ • スキーマを見れば認証が必要なAPIがわかる • アプリ側で認証が必要か判断できて、とりあえずリクエストして レスポンスから必要しなくてよくなる
  10. 利用例4 ログのマスキング
 type Customer { id: ID! homeAddress: String! @PII(level:

    STRICTLY_CONFIDENTIAL) bankAccount: String! @PII(level: TOP_SECRET) usageCount: Int! } • 個人情報かどうかを表すdirective • 個人情報を行動ログにそのまま送ってしまいがち • スキーマで定義しておけば機械的にマスクできる
  11. • たこやきのフードトラック近くにブースがあるので遊びに来てく ださい ◦ newmo iOS Design Blueprint ポスターで技術トーク! ◦

    地図とか車とか好きな方 • ニューモタオルや塩タブレットがもらえます(数量限定) ありがとうございました