Slide 1

Slide 1 text

#RAKUSMeetup ©2022 RAKUS Co., Ltd. 20年以上のレガシーシステム で始める リファクタリングの半歩 株式会社ラクス 四方 大輔

Slide 2

Slide 2 text

#RAKUSMeetup 自己紹介 ● シカタ ダイスケ ● 株式会社ラクス メールディーラー/開発チームリーダー ● 多趣味おじさん 料理/酒(ハイボール、お茶系)/オーディオ/カメラ/ スポーツ観戦(サッカー、野球、競馬)/ランニング/ダーツ/コーヒー

Slide 3

Slide 3 text

#RAKUSMeetup いきなりですが… 技術的負債の返済、やってますか? リファクタリング、やってますか??

Slide 4

Slide 4 text

#RAKUSMeetup “レガシー”を言い訳にしてませんか? うちのシステムは古いし… 手遅れでリファクタリングなんてできるわけない… 技術的負債とはズッ友!BFF!! 技術的負債 技術的負債 レガシー システム

Slide 5

Slide 5 text

#RAKUSMeetup 今回のお話 リリースから20年以上のレガシーシステム メールディーラーでアーキテクチャを見直した事例を紹介します。 これによって、安全にリファクタリングや機能改修ができるようになり、 少しずつ技術的負債が返せる状態になりました。

Slide 6

Slide 6 text

#RAKUSMeetup 今回のお話 リリースから20年以上のレガシーシステム メールディーラーでアーキテクチャを見直した事例を紹介します。 これによって、安全にリファクタリングや機能改修ができるようになり、 少しずつ技術的負債が返せる状態になりました。 レガシーシステムでも、諦めないで。

Slide 7

Slide 7 text

#RAKUSMeetup メールディーラーとは? クラウド型メール共有管理システム

Slide 8

Slide 8 text

#RAKUSMeetup メールディーラーとは? 今年21歳のレガシーシステム ● 社内最長老 ● シェアナンバーワン ● めちゃくちゃ多機能 ● PHP4の頃から開発 ● フルスクラッチで開発 ● バックエンドはノンフレームワーク

Slide 9

Slide 9 text

#RAKUSMeetup メールディーラーとは? 今年21歳のレガシーシステム やっぱりコアなところになればなるほど “レガシーシステム”あるあるが…

Slide 10

Slide 10 text

#RAKUSMeetup “レガシーシステム”あるある // javascriptが文字列で定義 $js = ""; $js .= "alert(123);"; $js .= ""; // DBアクセス $sql = "select * from hoge_table"; $result = $db->exec($sql); // 何かのロジック $hoge = commonFunction(); // 突然のprintでHTML出力 if ($hoge === "hoge") { print "
"; print "hogehoge"; print "
"; } else if ($hoge === "fuga") { print "
"; print "fugafuga"; print "
"; } else { print "
"; print "piyooo"; print "
"; } ビューロジックとビジネスロジックが混在

Slide 11

Slide 11 text

#RAKUSMeetup “レガシーシステム”あるある class ReceiveMail { // 受信したメールを解析処理 // DBに取り込む // 受信をトリガーに連動する処理が続く … // 神クラスの出来上がり } class SendMail { // 作成されたメールからメールデータ作成 // 送信をトリガーに連動する処理が続く … // 新規作成、返信、転送、送信予約 …などなどいろんなメール種別ごとの処理 // 神クラスの出来上がり } 上から下へ処理がベタ書きの神クラス

Slide 12

Slide 12 text

#RAKUSMeetup “レガシーシステム”あるある // 便利な関数がいっぱいの神クラス!! // 気づけば1万行超え!! class commonFunctions { function commonFunction1 () { // あるテーブルからデータ取得する便利な関数 } function commonFunction2 () { // いろんな画面に表示されるとある項目を描画する便利な関数 } function commonFunction3 () { // いろんな画面から呼ばれる条件分岐をまとめた便利な関数 } } 便利な神共通関数たちを従える神クラス

Slide 13

Slide 13 text

#RAKUSMeetup “レガシーシステム”あるある

Slide 14

Slide 14 text

#RAKUSMeetup UI刷新プロジェクト ~始動~ ある日、1つの要望が… UIが古いから 最近流行りのイケイケな感じに して欲しいんですよね~ メール一覧、閲覧、作成の 主機能画面の刷新お願いしますー! インパクトが大きいので 新/旧デザイン並行運用の期間を ある程度想定してます。

Slide 15

Slide 15 text

#RAKUSMeetup メールディーラーが抱えていた問題 レガシーシステムだけに長年、継ぎ足し継ぎ足しの開発が行われていた そして、以下の問題が… ● デグレード、考慮不足による不具合が多い ● 手動テストで品質を担保するしかない ● テストにリソースを大量投下していた

Slide 16

Slide 16 text

#RAKUSMeetup メールディーラーが抱えていた問題 つまり、 プロダクトコードの保守性低下によってテスト工数が肥大化している状況 継ぎ足し開発の末、大規模なUI刷新はとてもできる状態ではない ● 品質を担保できる保証がない(莫大なテスト工数が必要) ● アーキテクチャを見直さないとさらに継ぎ足しコードが増える ○ ビューロジックとビジネスロジックが密結合状態 ● さらに保守性を悪化させてしまう

Slide 17

Slide 17 text

#RAKUSMeetup つまり、こういうこと。 何も考えずにやると、各ロジックで新UIの分岐が増殖する // javascriptが文字列で定義 $js = ""; $js .= "alert(123);"; $js .= ""; // DBアクセス $sql = "select * from hoge_table"; $result = $db->exec($sql); // 何かのロジック $hoge = commonFunction(); // 突然のprintでHTML出力 if ($hoge === "hoge") { print "
"; print "hogehoge"; print "
"; } else if ($hoge === "fuga") { print "
"; print "fugafuga"; print "
"; } else { print "
"; print "piyooo"; print "
"; } ~~~ // 突然のprintでHTML出力 if ($hoge === "hoge") { if ($isNewUI) { print "
"; print "new ui is cool."; print "
"; } else { print "
"; print "hogehoge"; print "
"; } } else if ($hoge === "fuga") { print "
"; print "fugafuga"; print "
"; } else { if ($isNewUI) { print "new ui is cool."; } print "
"; print "piyooo"; print "
"; }

Slide 18

Slide 18 text

#RAKUSMeetup レイアウト修正できない状況… こんな状況で 安全に大規模レイアウト修正をリリースできるの??

Slide 19

Slide 19 text

#RAKUSMeetup レイアウト修正できない状況… 安全にリリースするには保守性アップが不可欠 どうやったら保守性アップできる??

Slide 20

Slide 20 text

#RAKUSMeetup キーワードは、 リファクタリングのための リファクタリング

Slide 21

Slide 21 text

#RAKUSMeetup 保守性を下げてる要因 is 何? ● グローバルスコープ・グローバル変数を多用 ● ビジネスロジックとビューロジックが密結合状態 ● 継ぎ足し継ぎ足しを繰り返したことでコードの可読性が著しく低下

Slide 22

Slide 22 text

#RAKUSMeetup 保守性アップの方針 1. 自動テスト導入を目的としたリファクタリング 2. フロントエンド/バックエンド(FE/BE)の分離を目的としたフレームワーク導入

Slide 23

Slide 23 text

#RAKUSMeetup 1.自動テスト導入を目的としたリファクタリング ● グローバルスコープにあるロジックを極力変更を加えずクラスのメソッドに移植する ● ユニットテストを作成する 移行対象のロジックを選定 最低限の動作確認 各アクションの クラス、メソッド作成 ユニットテスト作成 機械的にやる 余計な修正は しない

Slide 24

Slide 24 text

#RAKUSMeetup 1.自動テスト導入を目的としたリファクタリング 繰り返すことで、各アクションに対してクラス、メソッドができた状態になる ロジック自体は原型を保っている 移行対象のロジックを選定 最低限の動作確認 各アクションの クラス、メソッド作成 ユニットテスト作成 機械的にやる 余計な修正は しない

Slide 25

Slide 25 text

#RAKUSMeetup 1.自動テスト導入を目的としたリファクタリング 簡単にいうと… リファクタリングのための リファクタリング

Slide 26

Slide 26 text

#RAKUSMeetup 2. FE/BEの分離を目的としたフレームワーク導入 ● 自動テストを盾にビューロジックとバックエンドロジックを分離してフレームワークに移行 ○ アクションごとのクラスを新アーキテクチャへ移植する ○ 新デザインを実装する ○ 随時ユニットテストを動かし、デグレードがないことを確認する

Slide 27

Slide 27 text

#RAKUSMeetup これによって… ● 自動テストを作りやすくなった ● フロント・バックの分離によりロジックの可読性が向上 ● 自動テストを盾に、機能改修が安全に行えるようになった

Slide 28

Slide 28 text

#RAKUSMeetup これによって… ● 自動テストを作りやすくなった ● フロント・バックの分離によりロジックの可読性が向上 ● 自動テストを盾に、機能改修が安全に行えるようになった 保守性アップ!!

Slide 29

Slide 29 text

#RAKUSMeetup しかし… ● 実際はロジックだけ見るとあまり中身は変わっていない ● とにかく安全第一 ● リファクタリングのためのリファクタリング ○ 安全に機能改修できる状態にする ○ 今後の改修に向けての下地やリファクタリングの余地を作る

Slide 30

Slide 30 text

#RAKUSMeetup いざ、リリース!! 2022年3月末 メールディーラー UI刷新第一弾 リリース

Slide 31

Slide 31 text

#RAKUSMeetup いざ、リリース!! 2022年3月末 メールディーラー UI刷新第一弾 リリース クリティカルな不具合はゼロ!! (小さい不具合はいくつかあったけど…)

Slide 32

Slide 32 text

#RAKUSMeetup UI刷新を通して… ● リファクタリングの手順が確立された ○ リファクタリングのためのリファクタリング ○ テスト容易性向上 ● 安全に機能改修できるようになった

Slide 33

Slide 33 text

#RAKUSMeetup ● UI刷新はまだまだ続く… (第二弾は10月リリース予定です) ● もっとリファクタリングしたい欲が出てきた ○ 今まで諦めていたリファクタリングにも挑戦できるようになった まだまだ、終わりじゃない 俺たちの戦いはこれからだ!!

Slide 34

Slide 34 text

#RAKUSMeetup まとめ リファクタリングのリファクタリングはいいぞ ● いきなり大きい改修はできない ● まずは小さなリファクタリングから少しずつ ● とにかく安全第一で

Slide 35

Slide 35 text

#RAKUSMeetup まとめ リファクタリングのリファクタリングはいいぞ ● いきなり大きい改修はできない ● まずは小さなリファクタリングから少しずつ ● とにかく安全第一で “レガシーシステム”でも、諦めないで。

Slide 36

Slide 36 text

#RAKUSMeetup ご清聴ありがとうございました。