Slide 1

Slide 1 text

地点検索の進化と DX を⽀える 地点検索の進化と DX を⽀える リアーキテクチャ リアーキテクチャ

Slide 2

Slide 2 text

ABOUT ME ABOUT ME Yu Mochizuki @ NAVITIME JAPAN Co., Ltd. MY WORK MY WORK 地点検索の研究開発 全サービス共通 API 基盤開発 開発者向け検証サポート

Slide 3

Slide 3 text

MY CAREER MY CAREER 1. コア技術である経路探索エンジンの開発 2. B2B 事業 厳しい制約条件の中, 技術的負債に向き合い, DX の重要性に気づく. 開発リーダーを担当し, DX 重視の現場運営を実践. 3. バックエンドサーバ開発に そんな中で巡ってきたリアーキテクチャ案件が, 今⽇の話. ※ DX = Developer Experience ( 開発者体験)

Slide 4

Slide 4 text

SUMMARY SUMMARY 地点検索技術の発展を促すことを⽬的にリアーキテクチャに取り組み, 開発効率 や DX を改善した話.

Slide 5

Slide 5 text

AGENDA AGENDA 1. なぜリアーキテクチャが必要になったか 2. 共通 API 基盤からマイクロサービスへ 3. フルスクラッチリプレイス 4. DX First な開発ポリシー 5. リアーキテクチャ経験の副次的効果

Slide 6

Slide 6 text

なぜリアーキテクチャが必要になったか なぜリアーキテクチャが必要になったか

Slide 7

Slide 7 text

ナビタイムジャパンが⽬指すもの ナビタイムジャパンが⽬指すもの 経営理念 : 経路探索エンジンの技術で世界の産業に奉仕する ナビゲーションサービスにおける, 地点検索の⽴ち位置とは...

Slide 8

Slide 8 text

地点検索が正確でないと ... 地点検索が正確でないと ...

Slide 9

Slide 9 text

地点検索が正確だと ... 地点検索が正確だと ...

Slide 10

Slide 10 text

ナビゲーションサービスにおける地点検索 ナビゲーションサービスにおける地点検索 経路探索は 正確に⽬的地が選べなければ成⽴しない. 詳しく知りたい⽅は: 「安⼼な移動」のための POI 検索

Slide 11

Slide 11 text

ナビタイムの共通技術資産 ナビタイムの共通技術資産 経路探索を中⼼にいろいろな技術資産を持っており, 共通 API を通じて提供され ている.

Slide 12

Slide 12 text

地点提供のはじまり 地点提供のはじまり もともとはシンプルなデータフェッチだったので, 共通 API チームが地点検索機 能を開発していた.

Slide 13

Slide 13 text

地点検索のはじまり 地点検索のはじまり " もっとよく当たる検索を!" という要求が⽣まれ, SQL では限界を迎えたので, 全 ⽂検索システム (Solr) を使い始めた. ひとまず共通 API チーム持ちになった.

Slide 14

Slide 14 text

地点検索の⾼度化 地点検索の⾼度化 " もっともっと正確で便利な検索を!" という要求から⽣まれ, 全⽂検索システムの チューニングが必要になった. 専⾨的になってきたので, 地点検索チームができた.

Slide 15

Slide 15 text

検索 API の⾼度化 検索 API の⾼度化 地点検索の改善には, 共通 API サーバ上の機能が想像以上に重要だった.

Slide 16

Slide 16 text

検索 API の開発 検索 API の開発 地点検索チームも, 共通 API を積極的に開発するようになった.

Slide 17

Slide 17 text

課題 : リリースサイクルが合わない 課題 : リリースサイクルが合わない 共通 API サーバは多くの機能が相乗りしている (= Monorithic). 頑張って作った機 能がなかなか世に出せない.

Slide 18

Slide 18 text

課題 : 複雑化した実装を改修するのが⼤変 課題 : 複雑化した実装を改修するのが⼤変 共通 API サーバは⻑年の運⽤で技術的負債が増えてきた. 難しい開発にチャレン ジしにくい. コードが複雑になり, 機能追加もテストも⼤変. フレームワークの作者もいなくなった.

Slide 19

Slide 19 text

課題を解決するために 課題を解決するために リアーキテクチャに取り組むことに. マイクロサービス化 → リリースサイクルを独⽴させる. フルスクラッチリプレイス → 改修コストを下げる. そして, いい機会なので DX First に取り組んだ.

Slide 20

Slide 20 text

共通 API 基盤からマイクロサービスへ 共通 API 基盤からマイクロサービスへ

Slide 21

Slide 21 text

マイクロサービスとは マイクロサービスとは アプリケーションを⼩さな独⽴したサービスの組み合わせによって実現するアー キテクチャ. クライアント サービス サービス サービス サービス ID プロ バイダー マイクロサービス API ゲー トウェイ リモート サ ービス 管理 CDN 静的コン テンツ サービス検索 https://docs.microso .com/ja-jp/azure/architecture/guide/architecture-styles/images/microservices-logical.svg

Slide 22

Slide 22 text

マイクロサービスが⽬指すもの マイクロサービスが⽬指すもの それぞれの機能を独⽴に, 専⾨的に発展させる. cf. cf. 今回は, 地点検索を共通 API と疎結合にして, リリースサイクルを独⽴させる. AWS による説明 Microso による説明

Slide 23

Slide 23 text

どこをマイクロサービス化したか どこをマイクロサービス化したか " 検索システムを正しく使う" ところを新規サービスに切り出した.

Slide 24

Slide 24 text

やらなかったこと やらなかったこと " 新しい I/F に移⾏させる" ことはしなかった. I/F 移⾏は⼤変だし, できなくても⽬標は達成できるので, 今回は我慢した.

Slide 25

Slide 25 text

マイクロサービス化の効果 マイクロサービス化の効果 リリースサイクルが共通 API から完全独⽴ → ⽬標達成!

Slide 26

Slide 26 text

おまけ : マイクロサービスと組織構成 おまけ : マイクロサービスと組織構成 今回は が⾃然に当てはまる事例となった. コンウェイの法則 Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure. http://www.melconway.com/Home/Conways_Law.html

Slide 27

Slide 27 text

フルスクラッチリプレイス フルスクラッチリプレイス

Slide 28

Slide 28 text

旧システムに敬意を 旧システムに敬意を 今までお世話になった共通 API に感謝の⼼を持つ. 動いているものこそ⾄上. どんなに恐ろしいコードでも, 価値を⽣んできたシステムの⼀部. ※ 冗談みたいだが本当に⼤事なこと.

Slide 29

Slide 29 text

有識者の確保 有識者の確保 リプレイスにトラブルはつきもので, 意思決定がボトルネックになりがち. 地点検索を知り尽くした開発者とペアプロ中⼼で進めた.

Slide 30

Slide 30 text

実装のモダン化 実装のモダン化 ほぼすべての Java コードを Kotlin で書き直し, 実装をシンプルにした. 例えば, 愚直な検索叩き直しロジックを... final Response response1 = client.execute(createQuery1()); if (response1.isSatisfied()) { return Optional.of(result1); } final Response response2 = client.execute(createQuery2()); if (response2.isSatisfied()) { return Optional.of(result2); } return Optional.empty();

Slide 31

Slide 31 text

Kotlin ( ) で書くと, 興味が分割されて simple & testable に. ※ ポイントはクエリ⽣成が遅延評価されること. Java で真似するとここが⼤変. Sequence val queries = sequence { // 抽象化 testable . yield(createQuery1()) yield(createQuery2()) } return queries.map { client.execute(it) } .firstOrNull { it.isSatisfied() }

Slide 32

Slide 32 text

サードパーティフレームワークへ サードパーティフレームワークへ 内製フレームワークを捨て, 利⽤実績豊富な を利⽤. 実装するより, ググる コードが減るのでバグも減る Spring Framework

Slide 33

Slide 33 text

⾃動テスト ⾃動テスト 開発中のデグレードを防ぐため, ⾃動テスト整備は特に優先した. C0 98% の単体テスト 全⾃動 API テスト : YAML で書ける Web API テスト. Preacher

Slide 34

Slide 34 text

モニタリング モニタリング 運⽤して初めて分かる問題を拾うため, モニタリングを整備した. ※ メモリリーク発⾒

Slide 35

Slide 35 text

リリースゴール設定 リリースゴール設定 新旧差分確認ツールを活⽤し, ゴールを検証可能にした.

Slide 36

Slide 36 text

フルスクラッチリプレイスの効果 フルスクラッチリプレイスの効果 ⼯夫の甲斐あって, つつがなく完了. あっという間に投資を回収でき, 開発効率の改善を実感 → ⽬標達成!

Slide 37

Slide 37 text

DX FIRST な開発 DX FIRST な開発

Slide 38

Slide 38 text

DX の重要性 DX の重要性 プロダクトを継続的に育てるためには, 開発者が楽しいと思えることが理想だと 考えた. 開発者が⾃然と定着する 開発者がスキルアップする

Slide 39

Slide 39 text

DX と技術的負債 DX と技術的負債 開発者の感情は, 技術的負債に敏感に反応する. やりたい -> 効率を上げるための投資 いやだ -> 効率を下げる負債の兆候 技術的負債の程度は, 開発者の感情で測れるのでは?

Slide 40

Slide 40 text

WHY DX FIRST? WHY DX FIRST? プロダクトを育てる⼈を, 継続的に育てる 技術的負債のプライマリバランスを保つ これを実現するために, 開発者が楽しいと思うこと を優先的にやる. 開発者の勘に任せた結果, プロダクトの価値が最⼤化される.

Slide 41

Slide 41 text

DX FIRST の⼤前提 : ⼀流の開発者であり続ける DX FIRST の⼤前提 : ⼀流の開発者であり続ける 開発者の感性が鈍かったら良い⽅向に進むはずがない. → を → に近づける判断ができるようになる.

Slide 42

Slide 42 text

DX FIRST を守るために DX FIRST を守るために 強権を発動され, 短期的に成果を過剰に要求されることが最⼤の懸念. 信頼が厚いメンバを揃えた. ちゃんと終わりそうな案件規模にした. ほかの業務を続けて, 成果を出し続けた.

Slide 43

Slide 43 text

FOR DX: リアーキテクチャ FOR DX: リアーキテクチャ 今回のリアーキテクチャ⾃体が, DX を向上させた. 気楽にリリースする キレイなコードにふれる モダンな技術にふれる

Slide 44

Slide 44 text

FOR DX: テスト・モニタリング FOR DX: テスト・モニタリング バグを恐れず開発するため, テストとモニタリングは特に⼤切にした. デグレードしたらテストで気づく. 万が⼀本番で問題が発⽣しても, モニタリングですぐ気付ける.

Slide 45

Slide 45 text

FOR DX: 構成はシンプルに FOR DX: 構成はシンプルに 本質的な問題に集中するため, 徹底的してシンプルさにこだわった. Clone 即起動. 全機能がローカルで使える. 単⼀ JAR で運⽤.

Slide 46

Slide 46 text

FOR DX: イベントトレース FOR DX: イベントトレース ブラウザだけでデバッグできるように, 外部リクエスト等をトレース. { "items": [ ... ], "_debug": { "externalActions": [ { "url": "https://external.com/api?word=%E6%9D%B1%E4%BA%AC", "params": { "word": "東京" } } ] } }

Slide 47

Slide 47 text

FOR DX: エラートレース FOR DX: エラートレース ブラウザだけでデバッグできるように, 発⽣した例外をトレース. { "code": 503, "message": "A backend service is not available now.", "_debug": { "exception": { "message": "External API returns status code 503.", "stacktrace": [ "jp.co.navitime.foo.ExternalApiClient.kt:123", ... ] } } }

Slide 48

Slide 48 text

FOR DX: 外部リクエスト強制遮断 FOR DX: 外部リクエスト強制遮断 実際にバックエンドを異常にするのは⾯倒. 強制遮断機能を実装. ※ 危なすぎるので, もちろん本番では無効化. $ curl https://spot-search.com/circuit/solr/failure?count=20

Slide 49

Slide 49 text

結局 , DX FIRST とは 結局 , DX FIRST とは 楽しいこと = やりがいがあること. 基本に忠実に, ストイックに, 技術で解決すること こそが, エンジニアの楽しみ.

Slide 50

Slide 50 text

DX FIRST の効果 DX FIRST の効果 新たに join したメンバの感想 機能追加不安だけどテストが書けるので安⼼して進められそう. これ読んでいたおかげで検索システムの⾼速化頑張れそう. モブプロで解説聞いてる間の⼼境は SW EP4 のミレニアム・ファルコン号でル ークがブラスターをライトセーバーで跳ね返す訓練してる時のそれ.

Slide 51

Slide 51 text

リアーキテクチャ経験の副次的効果 リアーキテクチャ経験の副次的効果

Slide 52

Slide 52 text

共通 API 基盤のリアーキテクチャを加速 共通 API 基盤のリアーキテクチャを加速 本案件は共通 API チームにヒントを与えた. リリースサイクルや複雑さに懸念のある技術要素に対し, リアーキテクチャの機 運ができ, 実際に案件もスタートした.

Slide 53

Slide 53 text

共通 API 基盤の技術⾼度化 共通 API 基盤の技術⾼度化 新しい⾔語やフレームワークの知識を得たことで, 共通 API サーバを⾼度化する アイデアが⽣まれた. たとえば, Spring AOP にインスパイアされて AspectJ を導⼊し, 数千⾏のコードを 削減した.

Slide 54

Slide 54 text

⾃⾝のキャリアアップ ⾃⾝のキャリアアップ 開発者検証の抜本的な⾒直しを経験したことで, ⾃⾝の SET (So ware Engineering in Test) エンジニア としてのキャリアを開拓した. 現在は, このリアーキテクチャの中で培ったテストやモニタリングのノウハウを, 社内で啓蒙する活動や, 技術⽀援をしている.

Slide 55

Slide 55 text

まとめ まとめ 実りの多いリアーキテクチャが実現できた. マイクロサービス化 → リリースサイクル改善 フルスクラッチリプレイス → 開発効率改善 DX First → 楽しく継続的に開発できるプロダクト ⾃⾝や周囲への好影響