Slide 1

Slide 1 text

レガシーシステム 洗い出し大作戦 2018/08/18 Kyoto.なんか

Slide 2

Slide 2 text

こんにちは

Slide 3

Slide 3 text

id:Sixeightです はてなで働いています (@tomohi_ro)

Slide 4

Slide 4 text

みなさん引っ越したことはありますか

Slide 5

Slide 5 text

古い部屋から 新しい部屋に 荷物を移動するのは とにかく大変

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

レガシーシステム ↓ 新システム

Slide 11

Slide 11 text

引っ越し ● 古い部屋のにもつをすべて出す ● 要るもの要らないものに分けてダンボールに詰める ● 計画をたてて ● 新しい部屋の適切な場所に配置していく

Slide 12

Slide 12 text

システムマイグレーション ● 古いシステムの機能を洗い出す ● 整理して移行する機能と廃止する機能に分ける ● 計画をたてて ● 新しいシステムを適切に実装する

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

はてブの情報

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

システム移行の歴史 1. コア部分の開発 (Scala) 2. フロントエンド部分の開発 (Perl) 3. データ移行 4. 面の移行 5. それ以外の移行

Slide 17

Slide 17 text

システム移行の歴史 1. コア部分の開発 (Scala) ← 理想のはてブを作る 2. フロントエンド部分の開発 (Perl) ← 理想のフロントエンドのベースを作る 3. データ移行 ← レガシーシステムのデータを理想の形に変換する 4. 面の移行 ← 実際に画面を移していく 5. それ以外の移行 ← 例えばAPIとか

Slide 18

Slide 18 text

2つのシステムが同時に動いている状態 もちろんDBなどもそれぞれ持っている (そういう話はまたいつかの機会に)

Slide 19

Slide 19 text

ここから洗い出しの話

Slide 20

Slide 20 text

システム移行の歴史 1. コア部分の開発 (Scala) 2. フロントエンド部分の開発 (Perl) 3. データ移行 4. 面の移行 ← ここをやったときには 5. それ以外の移行

Slide 21

Slide 21 text

面の移行時の洗い出し

Slide 22

Slide 22 text

面の移行時の洗い出し ● 勘でIssueを登録していく ○ 新たな仕様が発掘されたら Issueを追加する ● Projectで管理 ○ MAY/SHOULD/MUST ○ BACKLOG/DOING/WAITING/確認/DONE ○ まとめ・情報 ● 依存関係は別のProjectを作って管理

Slide 23

Slide 23 text

依存関係とスケジュールをまとめて管理する ● 機能間の依存関係を勘で並び替えて、それぞれ勘で見積もってこの週にはこれを やりますというのを決めた ● 新たな依存関係が見つかったら並び替える ● 「今週の進捗はこんな感じです、来週これをやるので、この辺の調査や調整をお願 いします。」みたいな確認作業をするのにも使っていた

Slide 24

Slide 24 text

システム移行の歴史 1. コア部分の開発 (Scala) 2. フロントエンド部分の開発 (Perl) 3. データ移行 4. 面の移行 ← ほぼ完了したものの… 5. それ以外の移行

Slide 25

Slide 25 text

先の見えない不安 ● あとどのくらい残っているのか分からない ○ 全体でどのくらいの量があって、いまどのくらい終わっているのかが分からない ○ 樹海を闇雲に走っている状態 ● 次から次へと想定外の出来事が発生 ○ こんな仕様もあったぞ! ○ こっちのリソースにも依存していたからこれを先にやらないと! ○ これは実はこういう握りがあって …

Slide 26

Slide 26 text

問題への対策 ● あとどのくらい残っているのか分からない ○ → 網羅的に洗い出すしかない ● 次から次へと想定外の出来事が発生 ○ → 依存関係を明確にするしかない

Slide 27

Slide 27 text

ちゃんと洗い出しをしないといけない

Slide 28

Slide 28 text

なぜこれまで出来なかったのか ● 10年を超える歴史の中で増改築を繰り返した結果… ● 膨大なコード量 ○ → 全て洗い出すだけで年単位で工数が必要 ○ → そんな工数取れないでしょという風潮 ● 失われた経緯 ○ → 考古学者のように辛抱強く過去を解きほぐす必要がある

Slide 29

Slide 29 text

システム移行の歴史 1. コア部分の開発 (Scala) 2. フロントエンド部分の開発 (Perl) 3. データ移行 4. 面の移行 5. それ以外の移行 ← いまここ

Slide 30

Slide 30 text

現実的な洗い出し

Slide 31

Slide 31 text

エンドポイント視点で洗い出す ● すべてのエンドポイントを洗い出す ○ → 機械的に洗い出す ● とにかく一覧できるのが重要 ○ → 物量に絶望できる = 物量が見える

Slide 32

Slide 32 text

Googleスプレッドシート

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

エンドポイント洗い出し時にあった方がよい項目 ● Controller#Method (複数のURLが紐付いている可能性があるのでユニークな キーとして扱う) ● エンドポイントのURL (複数あるなら検索用にそれも) ● 調査時点のコードへのリンク (実装にすぐにたどり着きたい) ● Issueへのリンク (対象について扱うIssueを作っておく) ● 用途 (完全に理解したとしても翌日には忘れているので書いておく) ● メモ (これ不要では???みたいなことを書く) ● その他状態を表現するフラグ達

Slide 35

Slide 35 text

リソース視点で洗い出す ● 依存関係を洗い出す ○ → 使っているリソースを明確にする ● 地道な努力 ○ → ひたすらコードを読むしかない

Slide 36

Slide 36 text

エンドポイント単位でのリソース依存の洗い出し ● 一行一依存として記録していくと扱いやすい ○ → 後述 ● まとめIssueを作って、各機能のIssueを紐づけていく ○ → すべてのIssueがクローズされたら、そのリソースへの依存はなくなったとみなせる ○ → まとめIssueに作戦を経緯として残し、各 Issueに細かい経緯を残す

Slide 37

Slide 37 text

他の切り口 ● Worker単位でのリソースの依存 ● Cron単位でのリソースの依存 ● その他のわかりやすい切り口を見つけて洗い出していく

Slide 38

Slide 38 text

一行一依存として記録していくと扱いやすい ● コードを読んで使っているリソースを全て洗い出していきます ○ 1リソース1行で書いていく ● 疲れてくるので、息抜き用のタスクを用意しておくと吉

Slide 39

Slide 39 text

一行一依存として記録していくと扱いやすい 行と列をひっくり返すと、リソースに依存するエンドポイントの一覧が手に入る IFERROR(TRANSPOSE(FILTER(範囲, 条件1, 条件2)), “”)

Slide 40

Slide 40 text

調査時に気をつけること ● 人間の記憶を信頼しない ○ 調べきれていなくても目についたところはメモしておく ● コードへのリンクは細かめに ○ 調査時のリビジョンを必ず含める ○ 重要な処理ごとにリンクをする ● 処理の流れを追える書き方にする ○ 詳細を読まなくても処理が把握できる

Slide 41

Slide 41 text

視点 ● 参照系の移行 ○ → エンドポイント毎にリソースへの依存を明確にする ○ → 依存の下流から移していけば安全 ● 更新系の移行 ○ → グループ化して、グループ毎のリソースの依存と、グループ間の依存を明確にする ○ → まとめて移行する必要がある ○ → 依存の上流から移していけば安全

Slide 42

Slide 42 text

どうしても言いたいことコーナー ● 使ってないコードは消しましょう! ○ 使っていないことを証明するのは困難 ● 辿れる場所に経緯を残しましょう! ○ 辿れない場所にある情報は存在しないのと同じ ○ 本人しか知らない情報は存在しないのと同じ

Slide 43

Slide 43 text

まとめIssueを作る ● エンドポイント/機能単位でのIssueをまとめる ○ まずは先程洗い出したエンドポイントの Issueを紐づけていく ○ すべて閉じたらこのリソースへの依存はなくなっている ○ チェックボックスをつけておくと何かとべんり ● どのような対応が必要かによってセクションを分ける ○ 何をすればいいのか明確にする ● 作戦の相談などもこのIssueでやる ○ 経緯を残しましょう

Slide 44

Slide 44 text

まとめIssueからの洗い出し ● 次はまとめIssueを起点に漏れていたものを調査する ○ たとえば内部的な機能があったりする ○ ステークホルダーを明らかにする ● どんどんIssueを作ってまとめIssueに紐づけていく ○ すべてのタスクが洗い出せている状態を目指す ● このタイミングで別の切り口のまとめIssueができるかもしれない ○ 「ユーザー向けAPI移行作戦会場」とか「 XXX(サービス名)が使っているAPI一覧」とか ○ ロール単位、機能単位、用途単位などのまとめ Issueが出来ていた

Slide 45

Slide 45 text

やっぱりProjectで管理する ● タスクの分類と進捗状況の確認(全体感の把握)を同時にやる ○ 毎日眺めて状況を確認して、調査や調整などの先手を打つ ○ 週一でDと一緒に全体の進捗を確認したり懸念点を洗い出したりする ● 調整が済んで手を動かすだけになったタスクからTODOに入れていた ○ 自分がやるときや、手が空いた人にお願いするときにすぐ出せるリストとして利用

Slide 46

Slide 46 text

ポイント ● 最初に切り口を決めて、その中での優先度順に洗い出していく ○ → すべてを洗い出すのは無理だし、どこから手を付けるかを決める ○ → 機械的に洗い出せるところを起点にすると楽 ○ 例「サーバーの移行が先決、このサーバーを潰すにはこのサーバーが管理しているリソースを使わ なくなればよい、エンドポイントごとにリソースの依存を洗い出そう」 ● その結果を使って、別の切り口で関連するものを洗い出していく ○ → 複数の視点で洗い出さないと漏れができる ○ → 関連するものを見ればいいので取り掛かりやすい

Slide 47

Slide 47 text

機能廃止について ● 断捨離のチャンスなので機能の整理をして、工数も削減するとよい ○ 全ての機能を移行する必要はない ○ もう使われていないものもある ○ 依存が複雑すぎて移行の工数を考えると廃止した方がマシな場合がある ● 廃止したい機能一覧を作って、1つ1つ検討、調整をした ○ 確定したものから廃止していく ○ レガシーシステムから機能やコードを剥がせば剥がすほど移行は楽になっていく

Slide 48

Slide 48 text

まとめ

Slide 49

Slide 49 text

洗い出し成功によって得られた成果 ● 必要な作業の全体像が見えてきて計画が立てやすくなった ○ 物量が見えてきたのでここまでやったら終わりというのが見えてきた ● このサーバーを移行するには、このエンドポイントとこの機能が潰せていると良いで すねのようなことが言えるようになった ○ 作業量見積もりについて具体的な話ができるようになった結果無理な目標も現実的に ● 予期せぬ事態がだいぶ減った気がする (肌感覚) ● 洗い出しにしっかり工数をさけるようになった

Slide 50

Slide 50 text

課題 ● 単純に大変 ○ 必要な工程だと思うがもうちょっと省力化したい ● 見積もりの知見が足りずに成果物を活かしきれていない ○ 大中小くらいで見積もって、これは大だから時間がかかりますねくらいの雑さだった ● コードから分からないことを洗い出すのが難しい ○ この機能は実はこういう握りがあってみたいなのが突然現れて頭を抱えたりする

Slide 51

Slide 51 text

引っ越しがんばりましょう