レガシーシステムと向き合う際の個人的な心得をまとめてみる
はじめに
気温も乱高下な日々で秋があったようななかったような、そんな季節の変わり目ですね。
今年は新しめのプロダクトを触ることもあれば、レガシーなシステムの保守に向き合う時間も多くありました。今回はレガシーシステムと向き合う際に取り組んでいること、意識したいことをまとめてみます。
マインドセット編
ポジティブシンキングでいよう
いきなり精神論からですが、まずはポジティブに向き合うことが重要だと考えています。
「古い」「遅れている」「保守しづらい」といったネガティブな視点ももちろんありますが、企業の収益を支え、我々の給与を生み出している大切な資産という観点も重要でしょう。
個人的には6色ハットの思考法が好きで、ネガティブだけでなくポジティブ、事実と感情など、物事をいろんな角度で捉えるようにしたいものです。
個人的には「伸びしろ」という言葉を良く使います。どうせ改善に取り組むなら前向きなチームで改善を推し進めたいですね。
知の高速道路に自身がいることを忘れない
先人たちが構築してきたものによってより効率良く、高速に知識を得ることができるようになってきています。昨今の生成AIの進化もまさにそれを加速させています。「巨人の肩に乗る」なんて表現もよく言われますよね。
jQueryのコードを見て「なんで仮想DOMの環境で実装できないんだ」などと思うのは、そのコードが書かれた当時は一般的ではなかっただけかもしれません。現在の知識・技術だけで評価するのではなく、当時取りうる選択肢の中ではベストを尽くしたんだろうなという受け止めも必要でしょう。過去は変えられないので、「今ならどうするか」という視点で改善を進めたいものです。
ボーイスカウト・ルールを意識する
プログラマが知るべき97のことにも書いてあるボーイスカウト・ルールは改善にあたって重要なマインドセットです。
何らか機能追加のチケットを担当することになった際に、実装を済ませるだけでなく「来た時よりも美しく」の精神で改善できるポイントを探してみましょう。
- フォーマッターを整備してみる
- コメントが不足してそうな箇所のコメントを充実させる
- 未使用のコードを発見したので削除する
- READMEの文書構造を改善する
などなど、なんらか改善できるポイントはないか意識するだけでもアウトプットが変わってくるはずです。
恩恵を受けれないなら触らないのも手
実装はあまりイけていないが変更頻度の低いプロダクトやコードを改修しても恩恵を受けることがほとんどなく、修正によるデグレのリスクが上回るだけです。完璧な設計や美しいコードを目指すあまり、信頼性が損なわれるのは本末転倒です。
皆がよく触りうる箇所や、今後の開発で触るであろう領域に対して改善ができると中長期的に効いてきます。自己満足にならないように、時間軸を進めた際にその改善による恩恵が本当に受けられるのかは常に意識したいものです。
実践編
これまで説明したマインドセットを踏まえて、具体的な改善手順に移ります。
開発サイクルの整備
コードの詳細に入るより、まずは開発プロセス全体を回せる状態にあるかを確認します。
- ブランチ戦略
- CI/CD
- リリースノート管理・デプロイフロー
などなど、細かいコードの是非よりはまずは周辺環境の改善を狙います。
具体的には、以下のような作業をよく行っています。
- ブランチ戦略の見直し
- mainブランチ1本+リリースタグによる運用で十分であればmainブランチを軸にした開発に変更する
- いわゆるトランクベース開発を目指す
- release-drafterを導入してリリース内容の見える化
- ブランチ戦略の変更に伴うCIの調整(そもそもCIがなければ足すところから)
- branch protectionの再設定
- mainブランチ1本+リリースタグによる運用で十分であればmainブランチを軸にした開発に変更する
- 検証環境、デプロイ方法、ローカルでのテスト実行方法などの明文化
- 自動テストの整備(テストの話はさらに後述)
こういった改善はプロジェクト全体にじわじわと効いてくるので、早期の整備が重要です。
品質を担保する取り組み
開発プロセスの全体像が見えてきたら、自動テスト、静的解析を活用して安全かつ快適に改善を進められる環境の実現を目指します。
自動テスト
何はともあれ自動テストです。
- CI上でテストが動作する環境を整える
- CI上でテスト用のDBを起動し、それらに接続できるように設定ファイルを調整していくなど
- 動作するテスト、動作しないテストの整理
- 動かないテストは
@skip
で一旦動かさないようにする。テストランナーごとにテストをスキップできる仕組みがあるはずなのでそれらを利用する - 動作するテストはCIで常に回し続ける
- 動かないテストは
といった活動をし、新規にテストを書いたらそれが動き続ける状態を目指します。
テストが書ける環境が整えば既存の振る舞いに関するテストを書いて安全にリファクタリングするもよし、新規実装時に新しいコードベースはテストで守られている状態を作るもよし、改善活動の要となります。
勇気を持って既存の実装を変えるにはテストが必須です。
formatter・linter
formatter, linterを積極的に追加しましょう。最悪CIが用意できなくとも各自のエディタで静的解析が効く状態を作れます。
- すべてのファイルに適用するのは困難な場合は新規分だけ適用する
- 特定のフォルダだけ適用する
- 既存のエラーは一旦すべてignoreにしてCIが動く状態にしておき、新規分ではエラーが出てくるようにする
といったアプローチも効果的です。一気に100点は目指さず段階的な導入を試みましょう。
知識を増やすための活動
レガシープロジェクトでは有識者不在で詳細が分からない、仕様がブラックボックスしているなど多々あります。「これを作った人、今はいなくて。..」も残念ながらこの業界ではよく聞く話です。そのため、知識を増やし、共有を促進するための活動が不可欠です。
テーブルスキーマの理解
最近だと tbls を導入してデータベースドキュメントを充実させて知見を溜めやすくする活動をしています。
- 「このテーブルは今把握している限りだとXXのように使われている」
- 「このカラムは歴史的経緯により現在使われていない」
などなど、得た知識をコメントとして蓄積することでチームの知見が増えてます。コメントを書いた設定ファイルはリポジトリで管理でき、organizationの検索などでもヒットするので、参照しやすいです。
viewport機能も便利です。「XX機能」といった機能のくくりでテーブルをまとめても良いし、「YYシステムから参照されているテーブル群」のような連携の観点でまとめるもよし、同じテーブルでも観点ごとに説明できます。
まだ導入ほやほやでCIでの活用など検討中というステータスですが、もっと社内でも育てていければと思ってます。
コメントを普段より気持ち多めに書く
レガシーシステムの場合、そもそもの仕様が複雑なだけでなく、言語のバージョンが古くて今は推奨されない書き方があったりと、新しい人が入ってきて読む際につまづくハードルが多数あります。
コードリーディングをしたり周辺の実装を触った際には、冗長なくらいコメントを書いて良いと考えています。マシマシでいきましょう。
// 今のバージョンではこの書き方は推奨されない
// 既存実装にならっているが、本来はXXのパターンで実装するのが望ましそう
// このメソッド内でXXが呼ばれ、最終的にYYが実行される
などなど、コメントを意識的に書き足すと良いでしょう。コードの動きは変えずとも立派な改善です。
ストック型の知識管理を意識する
レガシーシステムに携わるとSlackのようなチャットツールで仕様を確認したり、運用対応の流れを確認したりするといったことは日常茶飯事かと思います。
一方でこれらの情報はフロー型であり、膨大なチャットの流れで埋もれてしまいます。そこで、slackでのやり取りを別のナレッジベース(弊社だとConfluenceなど)に貯めるようにしましょう。簡単な概要と、当時の議論のリンクだけでも、将来役に立つ可能性があります。
一方でチャットツール内での検索機能も活用しつつ、
- slackなりGitHubのコメントなり、口頭での会話内容はテキストに残すこと
- ストック型のナレッジベースにも貯めること
を意識しましょう。レガシーシステム問わず、リモートワーク全盛のこの時代で重要な活動です。
まとめ
レガシーシステムに立ち向かう際に意識していることを書いてみました。システムを作る以上、それが価値を出し続けられるように運用、保守することは重要ですね。
イチローも
ちいさいことを重ねることが、とんでもないところへ行くただひとつの道
と言っていました。いきなりすべてを変えることはできないので、チームで前向きなマインドセットを持ち、優先順位とバランスを考えながらコツコツと改善を進めていきましょう!
Discussion