ブラウンフィールド・アプリ開発
タイトルから、中身を推定できなかった方も多いと思うが、今回は我々がソフトウェア開発プロジェクトに参画するときによくある、稼働中のシステムを大改造するプロジェクトについて書く。それは、小さな機能を1つ1つ追加していくメンテナンスレベルの変更ではなく、将来の発展をより容易に行えるようにするための改造や、失敗したプロジェクトを引き継ぐようなアプリ開発だ。
実は、今回私がついたプロジェクトがまさにその種のプロジェクトで、今回の体験を忘れないうちに何かを書こうと思ったことが今回のコラムを書くモチベーションだ。ブラウンフィールドという言葉だが、Wikiのここを見ていただくと分かるが、英語のBrown Fieldのカタカナで、 本来は使われなくなった工業地帯や商業地を再開発するときに使い言葉らしい。実は、Manninigの書籍に、Brownfield Application Development in .NETというものがあり、ソフトウェアの開発でも、Brownfieldという言葉を使うことを知り、タイトルに使った。
Manningのこの本は実は、私は読んでいない。しかし、ブラウンフィールドのソフト開発。その開発を行う方法に決まった方法などはないだろう。担当したプロジェクトごとに、現場に合わせた方法を工夫して行うことがプロのソフト開発者の取るべき道だと思う。そういう考えもあり、この本はあまり読む意味がないかと思う。
しかし、読んでいない一番大きな理由は、あまり売れている本ではないらしく、世界一IT系の書籍が充実している、ここシンガポールの図書館にもなく、こちらのIT系の書店に行っても見つからず、手に入れるにはアマゾンを使うしか方法がないことが分かったこともある。内容を予想できない本は、立ち読みをして、ある程度中身を見た後でないと買う気がしない。
さて、現在立ち向かっているブラウンフィールドのアプリ開発だが、どんな状態か差し支えのない範囲で書く。(0)今のアプリを作った開発者はすでに会社を去っている。(1)ドキュメントは、ほぼゼロ。(2)実装はJava。(3)コメントはかなり少なく、かつ英語でも日本語でもない。(4)実装の骨格はかなり立派。数多くのクラスがあるが、Single Responsibility Principleを真面目に実現している。クラス間の関係も継承やコンポジションを的確に使い、かなりすっきりしている。
また、外部インターフェイス層、ビジネス層、データベース層と、きれいな階層構造も実現している。(5)後になって見つけたのだが、このアプリはマルチスレッドのアプリだが、その実装はとあるO’Raillyの『Java Threads』にあるサンプルコードをベースに作ったもので、かなり立派。 (6)問題は、そのように基本的骨格は立派だが、細かい実装がかなりひどい。
例えば、階層間のデータのやりとりは、Value objectではなく、プロパティ名をキーにしたHashを使っている。Global変数を多用し、変数の変更の捕捉がかなり難しい。コードのDuplicateもひどい。(7)Javaには数多くのオープンソースのコンポーネントがあるが、それらをほとんど使わず、すべてを自分で実装している。(8)現在のスタッフにアプリの仕様を細かく理解している人は誰もいない。
推定するに、こういう構造のアプリは多分、リーダーは優秀だったが、スタッフレベルのプログラマはそれほど優秀でなく、リーダーがスタッフをうまく指導できなかった場合生まれるのだろう。さて、私に課せられたタスクは、大規模なエンハンスとともに、将来の発展に備えてプログラム構造を改善すること。上で書いた(0)から(8)について私なりの対処法を書いていく。
(0)(1)(4)ドキュメントはソースコードを見て最低限のものを自分で書くしかない。まず書いたのは(4)の話と絡むが、静的クラス関連図。クラス間の継承やコンポジションを一枚の図面にした。このとき、一番重要なことはクラス間の関係と、interfaceやabstractなメソッド、そしてコンポジションなど、なので、その辺りだけを記述することにして、それぞれのクラスに数あるメソッド類の記述は省略した。
必要なときには、ソースを見ればすぐに分かる。必要なものはアプリケーションの全体像を見渡せる図面だ。アプリの動きはクラス間の複雑なシーケンス処理で達成されるものなので、シーケンスダイアグラムを書く誘惑にかられたが、それは工数の関係で断念した。もう1つ必要なドキュメントはデータベースのエンティティ関連図。これも、一番重要なことはテーブル間の関連なので、primary key(pk)やforeign key(fk)をヒントに、テーブル間の関連を記述する図面を作った。そこに記述するコラムはpkやfkと、その他は重要なものだけにした。
(2)Javaはカプセル化という強力な仕組みを持つobject指向言語で、この種の改造がやりやすい。
(3)僕自身コメント不要論者、つまりコメントでコードを解説するよりは、変数名、関数名、そしてプログラムの構造でプログラムを分かりやすくするべきだと思っているので、コメントが少ないことは問題ではない。特に、今回のアプリはプログラムの構造自体はしっかりしているので、それぞれの場所でのコードの意図はかなり正確に推定できるので、コメントはあまり必要ではなかった。英語でも日本語でもない、少しだけあるコメントだが、それは必要するところはGoogleのtranslateを使って英語に翻訳していった。
(5)後から、コードをメンテナンスする側にとって、有名な書籍のサンプルコードをベースにプログラム開発を行うやり方は、実にありがたい。願わくは、例えば、書籍名とチャプター名をソースのコメントのどこかに入れておいてもらえれば、今回のようにたまたま見つけるという『運』に頼る必要もなくなる。
(6)階層間のやりとりに、Value objectでなくHashを使う方法はJavaのプロパティの実装があまりに長くなり過ぎるので、採用されたものと推定する。私はこれを、プロパティの実装が楽になるLombokを使って、HashをValue objectに変えていった。Global変数多用の問題は、今のところ対策がない。現在稼働しているシステムだけに、デグラのリスクの高い変更は仲々できない。自動テストコードをある程度準備してから、おもむろに手をつけるという作業になるのかと思う。
(7)自分で実装している部分はオープンソースのコンポーネント利用にどんどん変えていった。例えば、Logはslf4j経由のLog4jに変えた。また、ConfigurationはSpring利用に。 DB層は、JDBCを使った実装だが、これもHibernateに変えたいが、これはあまりにリスクが高過ぎて無理かもししれない。
(8)最大の問題は、アプリの細かい仕様を理解している人がいないこと。実は、このアプリとインターフェイスする、あるハードウェアの開発を外部の業者に依頼しなければならないが、そのために渡す必要があるインターフェイス仕様を書くには、コードを見てリバースエンジニアしていくしか方法がなかった。
ソフト開発のだいご味はもちろんスクラッチ&ビルドだが、例えば自分にとって未知のプラットフォーム使って始めて作るような場合、仲々それは難しい。そういうとき、このように、基本構造は立派なアプリを改造するような仕事は、未知のプラットフォームの実装を学びながら、仕事をできるわけで、自分の仕事の範囲を広げられるいいチャンスだ。ただし、一部のITエンジニア、大手のシステムインテグレータに長年努めているような人はドキュメントベースの仕事に慣れているだけに、多少つらいかもしれない。