$30 off During Our Annual Pro Sale. View Details »

大規模リファクタリングの極意

Yosuke Imairi
September 17, 2021

 大規模リファクタリングの極意

iOSDC 2021 での登壇資料となります。

登壇内容
https://www.youtube.com/watch?v=yWO47AFkDls

以下、スライド内に登場するリンク一覧です。

MoT Teck Talk vol.3 「タクシー配車ならではの技術が盛りだくさん!iOSアプリの開発現場」
https://www.youtube.com/watch?v=KwaMV7-uMdI

不要なコードを検知して PR にコメントする Danger プラグイン
https://github.com/imairi/danger-detect_unused_definition

xcode-select の自動切り替えツール
https://github.com/klaaspieter/chxcode

RIBs アーキテクチャのボイラープレート自動生成 + 依存解決ツール
https://github.com/imairi/RIBsCodeGen

タクシーアプリ GO の iOS エンジニア採用ページ
https://hrmos.co/pages/mo-t/jobs/2100002

Yosuke Imairi

September 17, 2021
Tweet

More Decks by Yosuke Imairi

Other Decks in Technology

Transcript

  1. Mobility Technologies Co., Ltd.
    ⼤規模リファクタリングの極意
    Yosuke Imairi

    View Slide

  2. Mobility Technologies Co., Ltd.
    2
    Yosuke Imairi
    ⾃⼰紹介
    - JapanTaxi (2017.05 - 2020.4)
    - શࠃλΫγʔ
    - ૬৐ΓλΫγʔ
    - +BQBO5BYJ
    - Mobility Technologies (2020.4 - )
    - .07
    - (0

    View Slide

  3. Mobility Technologies Co., Ltd.
    3
    タクシーアプリの歴史
    JapanTaxi
    DeNA
    2011.11
    「全国タクシー」リリース
    2018.09
    「全国タクシー」が「JapanTaxi」に名称変更
    2017.09
    「タクベル」リリース
    2018.12
    「タクベル」が「MOV」に名称変更
    2020.04
    2020.09

    View Slide

  4. Mobility Technologies Co., Ltd.
    4
    タクシーアプリの歴史
    2011.11
    「全国タクシー」リリース
    2018.09
    2017.09
    「タクベル」リリース
    2018.12
    「タクベル」が「MOV」に名称変更
    2020.04
    事業統合 & 社名変更
    Mobility Technologies
    2020.09
    「全国タクシー」が「JapanTaxi」に名称変更

    View Slide

  5. Mobility Technologies Co., Ltd.
    5
    タクシーアプリの歴史
    2011.11
    「全国タクシー」リリース
    2018.09
    2017.09
    「タクベル」リリース
    2018.12
    「タクベル」が「MOV」に名称変更
    2020.04
    事業統合 & 社名変更
    Mobility Technologies
    2020.09
    「MOV」 が「GO」に名称変更
    「全国タクシー」が「JapanTaxi」に名称変更

    View Slide

  6. Mobility Technologies Co., Ltd.
    6
    タクシーアプリの歴史
    2011.11
    「全国タクシー」リリース
    2018.09
    2017.09
    「タクベル」リリース
    2018.12
    「タクベル」が「MOV」に名称変更
    2020.04
    2020.09
    09/19 17:20〜 LT
    「全国タクシー」が「JapanTaxi」に名称変更
    「MOV」 が「GO」に名称変更

    View Slide

  7. Mobility Technologies Co., Ltd.
    7
    ⼤規模なリファクタリングを実施
    2011.11
    「全国タクシー」リリース
    2018.09
    2017.09
    「タクベル」リリース
    2018.12
    「タクベル」が「MOV」に名称変更
    2020.04
    2020.09
    本腰をいれて⼤規模なリファクタリングを実施
    ・2018.03 - 2018.10 『JapanTaxi』 のリアーキテクチャ
    ・2020.07 - 2021.04 『GO』 のリアーキテクチャ
    「MOV」 が「GO」に名称変更
    「全国タクシー」が「JapanTaxi」に名称変更

    View Slide

  8. Mobility Technologies Co., Ltd.
    8
    1「なぜ」リファクタリングするのか
    Agenda
    2「なにを」リファクタリングするのか
    3「だれが」リファクタリングするのか
    4「いつ」「どこを」リファクタリングするのか
    5「どうやって」リファクタリングするのか
    6 ⼤規模なリファクタリングを終えて

    View Slide

  9. Mobility Technologies Co., Ltd.
    「なぜ」
    リファクタリングするのか
    9
    01

    View Slide

  10. Mobility Technologies Co., Ltd.
    10
    タクシーアプリ「GO」が抱えていた課題
    ❏ 既存設計の限界
    ❏ αʔϏε֦େʹ൐͍ɺෳࡶԽ͢Δ࢓༷ʹطଘͷઃܭ͕଱͑ΒΕͳ͘ͳ͖ͬͯͨ
    ❏ ౰࣌͸ͦͷઃܭͰ͏·͘ճ͍͕ͬͯͨɺ૿͑ଓ͚Δ৽ػೳ΍ 6*ͷେ෯ͳมߋ
    ͳͲʹ௥͍͚ͭͳ͔ͬͨ
    ❏ ಛఆͷ DMBTT͕ංେԽ͠΍͘͢ɺࡉ෼Խ͢Δ͜ͱ͕ۃΊͯࠔ೉ͳঢ়ଶʹ͋ͬͨ
    ❏ 技術的負債に対処するための時間的な余裕がない
    ❏ ๲େͳҊ݅։ൃʹ௥ΘΕɺٕज़తෛ࠴ͷฦࡁ͕ߦΘΕͳ͍··։ൃΛਐΊΔ͠
    ͔ͳ͔ͬͨ

    View Slide

  11. Mobility Technologies Co., Ltd.
    開発スピード落ちる
    バグが起きやすい状態に陥る
    新機能開発が始まる
    避けられないコードの肥⼤化
    既存の仕組みから脱却できないことによる、無理のある(妥協した)実装が増える
    11
    負のスパイラルが⽣まれる
    バグ修正に追われる⽇々
    リファクタリングやコード品質向上のための改善をする余裕がない

    View Slide

  12. Mobility Technologies Co., Ltd.
    💡リファクタリングの⽬的を明確にしておく
    ❏ 今後の開発・運⽤を滞りなく⾏えるようにする
    ❏ コードが肥⼤化せず、適切に細分化できるような仕組みにする
    ❏ iOS チームメンバ内で設計思想を統⼀する
    ❏ ࣄۀ౷߹ʹΑΓΤϯδχΞ͕ഒʹͳͬͨͷͰ
    12
    安⼼安全な開発を取り戻すために
    ⼤規模なリファクタリングを全⼒で取り組む

    View Slide

  13. Mobility Technologies Co., Ltd.
    「なにを」
    リファクタリングするのか
    13
    02

    View Slide

  14. Mobility Technologies Co., Ltd.
    14
    タクシーアプリ「GO」が抱える技術的負債
    … etc
    肥⼤化し続けるルーティング処理
    体系的にデザイン管理が⾏えていない
    テスタビリティが低い
    複雑度の⾼い実装を⾒直したい
    責務が明確になっていない
    不統⼀な実装
    状態管理を整理したい
    脱・Storyboard
    UI の Preview 機能の拡充
    多⾔語化対応への準備不⾜
    ・・・
    ・・・
    ・・・

    View Slide

  15. Mobility Technologies Co., Ltd.
    解消すべき技術的負債は何か
    15
    効果が⼤きい
    効果が⼩さい
    難しい(時間がかかる)
    簡単(すぐできる)

    View Slide

  16. Mobility Technologies Co., Ltd.
    解消すべき技術的負債は何か
    16
    効果が⼤きい
    効果が⼩さい
    難しい(時間がかかる)
    簡単(すぐできる)
    後回し

    View Slide

  17. Mobility Technologies Co., Ltd.
    解消すべき技術的負債は何か
    17
    効果が⼤きい
    効果が⼩さい
    難しい(時間がかかる)
    簡単(すぐできる)
    普段の開発と合わせて対応する
    後回し

    View Slide

  18. Mobility Technologies Co., Ltd.
    解消すべき技術的負債は何か
    18
    効果が⼤きい
    効果が⼩さい
    難しい(時間がかかる)
    簡単(すぐできる)
    普段の開発と合わせて対応する
    後回し
    今すぐやる︕
    現実は⼀つもなかった

    View Slide

  19. Mobility Technologies Co., Ltd.
    解消すべき技術的負債は何か
    19
    効果が⼤きい
    効果が⼩さい
    難しい(時間がかかる)
    簡単(すぐできる)
    普段の開発と合わせて対応する
    後回し
    今すぐやる︕
    計画を⽴てて本腰⼊れてやる必要あり
    現実は⼀つもなかった
    後回しにするのは簡単、楽なこと。
    これこそ挑戦すべき課題︕

    View Slide

  20. Mobility Technologies Co., Ltd.
    20
    タクシーアプリ「GO」が抱える技術的負債
    肥⼤化し続けるルーティング処理
    体系的にデザイン管理が⾏えていない
    テスタビリティが低い
    複雑度の⾼い実装を⾒直したい
    責務が明確になっていない
    不統⼀な実装
    状態管理を整理したい
    脱・Storyboard
    UI の Preview 機能の拡充
    多⾔語化対応への準備不⾜
    ・・・
    ・・・
    ・・・
    … etc

    View Slide

  21. Mobility Technologies Co., Ltd.
    … etc
    21
    タクシーアプリ「GO」が抱える技術的負債
    肥⼤化し続けるルーティング処理
    体系的にデザイン管理が⾏えていない
    テスタビリティが低い
    複雑度の⾼い実装を⾒直したい
    責務が明確になっていない
    不統⼀な実装
    状態管理を整理したい
    脱・Storyboard
    UI の Preview 機能の拡充
    多⾔語化対応への準備不⾜
    ・・・
    ・・・
    ・・・
    09/19 14:10〜 Track C

    View Slide

  22. Mobility Technologies Co., Ltd.
    … etc
    22
    タクシーアプリ「GO」が抱える技術的負債
    肥⼤化し続けるルーティング処理
    体系的にデザイン管理が⾏えていない
    テスタビリティが低い
    複雑度の⾼い実装を⾒直したい
    責務が明確になっていない
    不統⼀な実装
    状態管理を整理したい
    脱・Storyboard
    UI の Preview 機能の拡充
    多⾔語化対応への準備不⾜
    ・・・
    ・・・
    ・・・
    みんなが課題感を持っていた
    早い段階で対処しておきたい
    アプリ全体の設計を
    ⾒直す必要がありそう

    View Slide

  23. Mobility Technologies Co., Ltd.
    ❏ アーキテクチャ変更についてチーム内で熟議を交わす
    ❏ 本当にアーキテクチャ変更が必要なのか
    ❏ アーキテクチャ変更によってどういう効果が期待できるか
    ❏ アーキテクチャ選定の基準
    23
    アーキテクチャ変更(⼤規模なリファクタリング)への挑戦
    https://www.youtube.com/watch?v=KwaMV7-uMdI
    Check!! 👉

    View Slide

  24. Mobility Technologies Co., Ltd.
    ❏ アーキテクチャとして RIBs を採⽤することで、技術的負債の解消を試みる
    ❏ JapanTaxi での RIBs 開発 / 運⽤経験から GO でもその効果が⾒込める
    ❏ すべてを置き換えるのではなく、ルーティング部分に絞って適⽤する
    ❏ View やビジネスロジックは基本的にそのまま再利⽤
    24
    アーキテクチャ変更(⼤規模なリファクタリング)への挑戦
    💡リファクタリングの対象範囲や
    あえて変更しない点をあらかじめ決めておく

    View Slide

  25. Mobility Technologies Co., Ltd.
    「だれが」
    リファクタリングするのか
    25
    03

    View Slide

  26. Mobility Technologies Co., Ltd.
    ❏ 事業統合のかねあいで事業案件がたくさんあった
    ❏ ⼤きな効果を得られるリファクタリングにはまとまった時間が必要
    26
    事業案件を⽌めずにリファクタリングを進められる体制
    事業案件を開発するチーム リファクタリングや⾃動化に専念するチーム
    💡リファクタリングや⾃動化など
    開発効率向上に集中できるチーム体制

    View Slide

  27. Mobility Technologies Co., Ltd.
    ❏ 既存仕様に詳しい⼈がいる / リファクタリング該当箇所の元実装者がいる
    ❏ 既存仕様を熟知しているほうが正しくリファクタリングが⾏える
    ❏ 既存実装の背景やワークアラウンド、注意したい実装などに気づきやすい
    ❏ アーキテクチャの知識が豊富な⼈がいる
    ❏ リアーキテクチャの場合、そのアーキテクチャでの実装経験者がいるとよい
    ❏ なるべく⼈員の流出を防ぐ
    ❏ 事業案件の開発が忙しいなどで駆り出されないようにする
    ❏ リファクタリングにもロードマップはあるので、
    その計画を崩さないようにしたい
    27
    ⼼強いリファクタリングチーム

    View Slide

  28. Mobility Technologies Co., Ltd.
    「いつ」「どこを」
    リファクタリングするのか
    28
    04

    View Slide

  29. Mobility Technologies Co., Ltd.
    ❏ アーキテクチャを適⽤しやすいところ
    ❏ RIBs だとアプリの根元(AppDelegate)から置き換えていくのが理想
    ❏ 課題を抱えているところ
    ❏ リファクタリングによる効果が期待できる
    ❏ あまり触られていないところ
    ❏ 事業案件の開発とのコンフリクトを避けられる
    ❏ 事業案件と同じところ
    ❏ ⼤幅な UI 変更や機能改修がある場合に便乗する
    ❏ QA コストを抑えられる
    ❏ リリースブロッカーにならないように注意すること
    29
    どこからリファクタリングをしていけばよいのか

    View Slide

  30. Mobility Technologies Co., Ltd.
    ❏ 今後どんな事業案件の開発が⾏われるかを気にかけておくことが⼤事
    ❏ リファクタリングの修正はいずれどこかでリリースすることになる
    ❏ 事業案件のロードマップのどこに差し込めるかを意識しておく
    ❏ 事業案件のロードマップから逆算してリファクタリングする箇所を検討する
    30
    事業案件の流れをしっかりチェックしておく
    ❏ できればリファクタリングの予定もロードマップ内に組み込めるころが理想
    ❏ ⼤規模なリファクタリングは何回かのフェーズに分割して計画しておく
    ❏ PDM や QA などとのコミュニケーションを⽇頃からとっておくことで、
    リリース前の調整がしやすくなる

    View Slide

  31. Mobility Technologies Co., Ltd.
    「どうやって」
    リファクタリングしたのか
    31
    05-1
    (下準備)

    View Slide

  32. Mobility Technologies Co., Ltd.
    ❏ 既存の仕様や設計で理解不⾜があるところをコードリーディングする
    ❏ 思い込みや先⼊観を拭うためにも⼀度⾏っておくとよい
    ❏ 仕様書はあくまでも参考程度にする
    ❏ 後続の案件などで仕様が変わっていることはよくある
    ❏ 当時の仕様が満たせていない状態になっているかも
    ❏ 独⾃の仕組みがある場合は重点的に理解を深めておく
    ❏ よく知られている設計パターンではなく、独⾃に作られた仕組みが導⼊され
    ている場合、その設計や思想を理解しておかないと考慮漏れが発⽣する
    32
    既存仕様および設計の理解を深める
    💡 正確にリファクタリングを⾏えるようにする

    View Slide

  33. Mobility Technologies Co., Ltd.
    ❏ チームメンバにリファクタリングしている旨をきちんと伝えておく
    ❏ リファクタリングをするモチベーション
    ❏ 解決される課題
    ❏ おおまかな設計思想
    ❏ 実装着⼿前に必ずレビューしてもらう
    ❏ ⾃分にない視点での意⾒がもらえる
    ❏ 事業案件とのコンフリクトを事前検知
    33
    リファクタリングの計画を共有する
    💡チームメンバに共有しておくことで
    ⼤きな⼿戻りや認識の⾷い違いを避けられる

    View Slide

  34. Mobility Technologies Co., Ltd.
    ❏ 使われていないコードは消しておく
    ❏ リファクタリング時に無駄に考えてしまわないようにする
    ❏ 静的解析で⼀括除去
    ❏ 今後無駄なコードが増えないための対策
    ❏ Danger で未使⽤のコードを⾃動検知する仕組みを導⼊
    ❏ https://github.com/imairi/danger-detect_unused_definition
    34
    リファクタリングのためのリファクタリング ①

    View Slide

  35. Mobility Technologies Co., Ltd.
    ❏ 既存のアーキテクチャに則った実装を試みる
    ❏ GO の場合はルーティングまわりのリファクタリングが対象
    ❏ 既存の Router に ViewModel があったり通信処理が⾏われていたり…
    ❏ 本来あるべき姿に可能な限り寄せておく
    35
    リファクタリングのためのリファクタリング ②
    ❏ あとから絶対に必要となる共通ロジックの実装
    ❏ 最初に作っておくことで、複数⼈によるリファクタリングがしやすくなる
    ❏ 案件開発でも積極的に利⽤してもらう
    etc...

    View Slide

  36. Mobility Technologies Co., Ltd.
    36
    こういった下準備に 2 ヶ⽉以上かかったが、
    この下準備のおかげでリファクタリングの本作業は滞りなく⾏えた

    View Slide

  37. Mobility Technologies Co., Ltd.
    「どうやって」
    リファクタリングしたのか
    37
    05-2
    (⾃動化)

    View Slide

  38. Mobility Technologies Co., Ltd.
    ❏ 実装に時間を使いたい︕
    ❏ 時間を消費しがちなことに着⽬する
    ❏ 無駄にコミュニケーションを必要としている作業
    ❏ 何度も⼿動で⾏っている同じような作業
    ❏ 待ち時間が発⽣する作業
    38
    リファクタリングに集中するために
    💡実装時間を増やすために、どんどん⾃動化を進める

    View Slide

  39. Mobility Technologies Co., Ltd.
    ❏ ⾃動的に指定したバージョンの Xcode が開けるようにした
    ❏ 既存のコードを参照したり動作確認のためにブランチを切り替えることがある
    ❏ ブランチごとに利⽤している Xcode のバージョンが異なることがある
    ❏ 都度チームメンバに聞く必要があった
    ❏ chxcode
    ❏ https://github.com/klaaspieter/chxcode
    ❏ .xcode-version で Xcode のバージョンを指定
    ❏ ブランチを切り替えと同時に xcode-select が⾃動的に更新される
    ❏ make open で指定した Xcode が開けるようにした
    39
    ⾃動化してよかった取り組み ①

    View Slide

  40. Mobility Technologies Co., Ltd.
    40
    ⾃動化してよかった取り組み ①
    .xcode-version で指定したバージョ
    ンの Xcode が⾃動的に選択される
    コマンドラインから適切なバージョン
    の Xcode でプロジェクトが開ける

    View Slide

  41. Mobility Technologies Co., Ltd.
    41
    ⾃動化してよかった取り組み ①
    Bitrise の Step で
    Xcode のバージョンチェックを⾏う
    想定していない Xcode のバージョン
    でビルドが⾏われることを防ぐ

    View Slide

  42. Mobility Technologies Co., Ltd.
    ❏ リファクタリング以外の修正を定期的に取り込む
    ❏ 並⾏して開発されている別ブランチの修正を反映させる
    ❏ さまざまな⼿間があった
    ❏ ⼿動マージ + Unit Test (CI) + PR レビュー依頼 + PR マージ
    ❏ ⼿動マージ : 業務時間中にやらなければならない
    ❏ Unit Test (CI) : 20 - 30 分待つ必要がある
    ❏ PR レビュー依頼 : チームメンバの⼿を⽌める必要がある
    ❏ せめてコンフリクトがない場合はもっと楽に取り込みたい
    42
    ⾃動化してよかった取り組み ②

    View Slide

  43. Mobility Technologies Co., Ltd.
    ❏ CI によるベースブランチの⾃動マージ
    ❏ Bot がマージ + Unit Test (CI) + Bot が PR レビュー依頼 + PR マージ
    43
    ⾃動化してよかった取り組み ②
    ❏ よくなった点
    ❏ ベースブランチの取り込み忘れがない(常に意識する必要がなくなった)
    ❏ 朝に Unit Test (CI) が終わった状態の PR が作成されている
    ❏ マージボタンを押すだけ(誰かにレビュー依頼を出す必要がない)
    ❏ コンフリクトがある場合
    ❏ コンフリクトを解消してレビュー依頼後にマージ
    夜間に⾏う

    View Slide

  44. Mobility Technologies Co., Ltd.
    ❏ 機械的なコーディングを⾃動化する
    ❏ RIBs にはボイラープレートがたくさんある
    ❏ Router + Interactor + Builder + (ViewController) + ComponentExtension
    ❏ テンプレートによる⽣成に加え、既存コードの改修が必要だった
    44
    ⾃動化してよかった取り組み ③
    ❏ Builder
    ❏ 親 Dependency に⼦ Dependency を追加
    ❏ 親 Builder の build メソッド内で⼦ Builder を初期化
    ❏ 親 Router ⽣成時に引数として⼦ Builder を追加
    ⼿動で毎回同じような作業をしているのが煩わしい
    リファクタリング作業に集中したい
    ❏ Router
    ❏ 親 Interactable に⼦ Listener の追加
    ❏ 親 Router に⼦ Builder の定義を追加
    ❏ 親 Router のイニシャライズに⼦ Builder を追加
    ❏ 必要であればイニシャライズの override を削除
    ❏ 親 Router が保持する⼦ Builder の初期化

    View Slide

  45. Mobility Technologies Co., Ltd.
    ❏ RIBsCodeGen
    ❏ https://github.com/imairi/RIBsCodeGen
    ❏ ボイラープレートの⾃動作成(R / I / B / VC + ComponentExtension)
    ❏ 既存のコードを静的解析し、必要な最低限のつなぎこみも⾏う
    45
    ⾃動化してよかった取り組み ③

    View Slide

  46. Mobility Technologies Co., Ltd.
    - **NormalDispatch**
    - **InitialNormalDispatch**
    - **BannerStateChecker**
    - AccountLockControlArea
    - CruisingTaxiPaymentSetting
    - PayPayChargeRemindAlert
    - DPaymentChargeRemindAlert
    - CruisingTaxiPaymentSettingCompletion
    - **OneShotPromotionChecker**
    - AppRenewalPopup
    - JTXAccountTransfer
    - PaymentSettingIntroduction
    - SelectPickup
    - PickupSetting
    ...
    46
    ⾃動化してよかった取り組み ③
    RIBs ツリーの作成
    (チーム内での設計の議論)
    Markdown
    設計に従い必要なボイラープレートを⽣成
    & 最低限の依存関係の解決

    View Slide

  47. Mobility Technologies Co., Ltd.
    - **NormalDispatch**
    - **InitialNormalDispatch**
    - **BannerStateChecker**
    - AccountLockControlArea
    - CruisingTaxiPaymentSetting
    - PayPayChargeRemindAlert
    - DPaymentChargeRemindAlert
    - CruisingTaxiPaymentSettingCompletion
    - **OneShotPromotionChecker**
    - AppRenewalPopup
    - JTXAccountTransfer
    - PaymentSettingIntroduction
    - SelectPickup
    - PickupSetting
    ...
    47
    ⾃動化してよかった取り組み ③
    RIBs ツリー(設計) Markdown
    💡アプリの設計からすばやく実装開始できる状態にする

    View Slide

  48. Mobility Technologies Co., Ltd.
    48
    06 ⼤規模なリファクタリングを終えて

    View Slide

  49. Mobility Technologies Co., Ltd.
    ❏ 技術的負債に打ち勝った証
    ❏ リファクタリングだけで 15 万⾏の修正
    ❏ ルーティングの細分化
    ❏ 15 個の 独⾃ Router ⇒ 160 個の RIBs Router
    ❏ 無限にスケールが可能(肥⼤化を確実に防ぐ)
    ❏ 責務がより明確になった
    ❏ 設計思想が統⼀された
    49
    約1年間におよぶ⼤規模なリファクタリングの成果

    View Slide

  50. Mobility Technologies Co., Ltd.
    ❏ 安⼼安全な開発は取り戻せる
    ❏ チームメンバで技術的負債に対して議論
    ❏ リファクタリングに集中できる体制づくり
    ❏ 綿密な計画のもとリファクタリングに取り組む
    ❏ 事業案件のロードマップを常に意識する
    ❏ リファクタリング前の⼊念な下準備
    ❏ 機械的な作業を⾃動化し、本作業に時間を当てる
    50
    約1年間におよぶ⼤規模なリファクタリングの成果

    View Slide

  51. Mobility Technologies Co., Ltd.
    51
    07 お知らせ

    View Slide

  52. Mobility Technologies Co., Ltd.
    52
    タクシーアプリ「GO」の開発を⼀緒にしませんか
    https://hrmos.co/page
    s/mo-t/jobs/2100002

    View Slide

  53. ⽂章·画像等の内容の無断転載及び複製等の⾏為はご遠慮ください。
    Mobility Technologies Co., Ltd.
    53

    View Slide