『レガシーソフトウェア改善ガイド』を読んだ

本を読むと何かをやった気になってしまって良くないです。でも、新たな知識を得るのは楽しいです。娯楽だと思うことにします。

どんな本?

レガシーなソフトウェアを改善するためのガイドです。たぶん。

www.shoeisha.co.jp

著者はThe GuardianのSenior DeveloperであるChris Birchall氏。訳者の吉川邦夫さんという方は、元SEで現在は翻訳を主に手がけられているっぽいです。翻訳リストをみると心なしかMS周りの技術書に多く関わられているっぽいです。

おなじ翔泳社から出ているレガシーコード改善ガイドとシリーズ物かと思いきや、全然別物です*1

なぜ読んだのか

勤務先の技術ブログに、レガシーシステムの改善に関する記事を書きました。その中で本書を紹介していたのですが、その段階でまったく読んでいませんでした。まったく読んでいない本を紹介することに対し、一定の罪悪感が拭えなかったため、渋々読むことにしました。

上記の記事で書いたこと以外にもいわゆる技術的負債と言われる領域に手をつけていく中で、もうちょっとまじめに取り組んだほうがいいよなあ、という思いが強くなってきました。やってきたことやより大きな技術的負債に対してどう立ち向かっていくべきか、指針を得られればと思いました。また、前述の『レガシーコード改善ガイド』ではなくソフトウェアのほうを選んだのは、コードベースを改善するにはまずそれ以前にソフトウェア全体やその開発プロセスの土台が必要と感じているからです。富士山よりも高い意識。

感想など

3部構成になっており、それぞれ「なにが課題なのか」「どうやって解決するか」「そのための環境づくり」について言及されているように感じました。

まず、ソフトウェアの実装に関することは想像以上に、というかほぼ書かれていません。レガシーは人間から生まれるので、必然的にそうなるのかもしれません。ビッグリライトはやめとけ(意訳)とか、マイクロサービスに走るな(意訳)とか、安易にレガシーを正す主張を並べるのではなく、理路整然と価値ある判断ができるように導いてくれています。レガシーソフトウェアと対峙し感情が荒ぶりがちなエンジニアは、一度エディタを閉じて深呼吸し、帰宅して本書を一読することをおすすめします。

具体的なレガシーソフトウェアの例を示し、改善に至るまでの考え方をストーリー仕立て紹介されている箇所があり、大変わかりやすいです。「何がダメで、どうしたいのか、そうすると何が嬉しいのか」を、十分すぎるくらいに説明してくれます。知識を詰め込んだ技術書というよりは、読者にとって読みやすいように配慮されていると感じます。

最後の第3部では主に自動化を主眼に、いかにレガシーを生み出さないかに言及されています。その中で、Ansible、Vagrant、Jenkinsといった具体的なツールを使った環境整備が書かれています。このへんは疲れてきてあんまり読んでません。すみません。個人的には本書は第2部までで十分その価値を持つ、第3部は必要な人だけ読んだらいいという印象です。直近のお仕事でCIをがんばりたい所存なので、まあ、がんばろうという決意を新たにしました。

本書を通じて私は「レガシー」(legacy)を、何か悪い言葉のように扱ってきたが、そうする必要はない。望むと望まないとに関わらず、我々は次世代の開発者に遺産(legacy)を残すのだから、できるだけのことをして、誇らしい遺産にしよう。

やっていきましょう。以下ではときめいた箇所とそれぞれ思ふことをメモっておきます。

「負債」には「利子」がつく

技術的負債がやっかいなのは、ただ存在することがデメリットであることです。テストがなく仕様が曖昧なコードは、その周辺の挙動を知るために読み解く手間がかかります。また、設計が使用に沿わずレガシーとなったデータベーススキーマが存在すれば、それに適応するためにアプリケーションコードが必要以上に複雑になり、新たなレガシーを生み出します。レガシーなソフトウェアを放置すると、エンジニアや組織は利子を払い続けることになります。その意味において、技術的「負債」という言葉は、事象のメタファーとして非常に優れていると感じました。

レガシーカルチャをリファクタする

レガシー「ソフトウェア」というタイトルから、レガシーコードよりは広い領域だろうな、という想像をしていましたが、本書ではさらに開発プロセスや組織のカルチャにまで言及されています。レガシーなカルチャとして、「変化への畏怖」と「知識の孤立」を挙げています。それぞれについて、個別に取りうる方策を説明しています。使われていないはずのコードを消す恐怖を和らげるためにはアクセスログをみればいいですし、いま記録されていないならまずログを出すところが第一歩です。

本書では言及されていませんが、自分の経験からいうと、技術的負債の返却に対して、組織的・長期的なメリットだけでなく、個人のインセンティブとリスクを取れる文化が必要と感じます。新規開発のプロジェクトと比較して、ユーザよりも開発者にとっての課題のため、それに取り組むモチベーションが内発されにくいです。組織における評価者がソフトウェアの状況を理解し、長期的な価値をふまえた高度な評価をする必要があります。

まずは触ってみるしかない

この「未知への恐れ」を克服する最良の方法は、そのコードに飛び込んで、いじり始めることだ。

レガシーなソフトウェアをみた人間に内発されやすい感情として、「恐怖」と「フラストレーション」が挙げられています。自分の経験とも一致します。これらが開発効率やソフトウェアの品質にもたらす悪影響を評価することは極めて難しいですし、少なくとも定量化は困難と思われます。少なくともいい状態ではないのでなんとかしたいわけですが、なぜ自分が怖かったりイライラしたりするかと考えてみると、「知らないから」というのが多分にあります。なので、そのコードを読んで、何をやっているかを把握することが、解消に繋がります。

そのために本書では、「調査的リファクタリング」が紹介されています。何をやっているかを把握しながら、簡単なリファクタを進めていく、という手法です。人間の心理として調査自体は何かを生産している気にならずコストにみえますが、そのついでに少しでもソフトウェアを改善することで、ある意味で正当化できます。例えば、もう使っていないメソッドや参照を削除することでも、それが残り続けることに比べれば大きな前進です。まずは、小さなリファクタを始めましょう。使っていないクラス、メソッド、変数、参照をみつけたら、削除しましょう。

レガシーの源泉を紐解く

結局、最初は「醜悪な実装」に見えたコードが、実は「複雑な仕様」だった、という場合が多く、それについては、大きな改善が望めない。

複雑なコードが存在するとき、それが必要な複雑さなのかは考える必要があります。そもそもの仕様が複雑ならその実装が(エンジニアにとって)複雑であっても、妥当な複雑さです。さらに一段上のレイヤを考えて、実現したいことが複雑ならその仕様の複雑さも妥当です。ただし、ほとんどの場合、過剰な複雑さだと思います。その場合は、要件の掘り下げが足りていない可能性があります。その場合、リファクタすべきはコードではなく仕様です。

段階的にできるものはそうする

モノリスなアーキテクチャを運用するチームは、世の潮流と自身のギャップを感じ、「マイクロサービスにするぞ!」と士気が高まりがちです。しかしその間はとんでもない距離があり、いざやるとなると不相応にしんどいです。まずはフロントエンドとバックエンドを切りわける、その次にSOAに取り組む、その上でさらに必要ならマイクロサービスを検討する、というふうに進めていけるはずですし、ほとんどのケースでマイクロサービスまでやる必要はないはずです。「マイクロサービス化」を目的としてしまうと、本来の課題が解決できない恐れがあります。

また別の観点として、機能の改善とリファクタリングは切り分けるのが定石です。機能をなおしてからリファクタするのか、リファクタしてから機能をなおすのか、どちらになるかはプロジェクトの性質に依存しますが、いずれにしても同時にやるべきでないことは確かです。

すべてはユーザのため

最も重要なのは(コードについて言えることの、どれよりも、はるかに重要なのは)ユーザーにとって価値のあるソフトウェアを作ることだ。

技術的負債が負債たりうるのは、ユーザに害があるからです。エンジニアがストレスを感じ、必要以上に時間を浪費し、開発速度が落ちて新たな価値を届ける速度が落ちます。また、バグの温床にもなります。ユーザのために技術的負債を返却せねば。

*1:原著のタイトルはそれぞれ"Working Effectively With Legacy Code"と"Re-engineering Legacy Software"であり、出版社も異なる