📐

古文書のようなソースコードと向き合った日

2024/05/13に公開

数年前、古文書のようなソースコードの改修案件を担当したことがあります。

  • 変更履歴が無い(ソースコード管理をしていない)
  • 社内で誰も触ったことが無い
  • 仕様書もなく、そもそも他社の製品
  • 言語が懐かしい(VB6)
  • でもお客さんは基幹システムとして利用している
  • 多分10年以上、15年以上昔から動いている

特徴としてはこのような感じで、このシステムの改修案件を当時の営業担当が持ち帰ったことが対応の発端でした。当時エンジニア2年生だった私はこの改修プロジェクトのリーダーに任命され、製造作業を担当することとなりました。
具体的には、ソフトウェアへ新たに「営業管理・受発注管理・財務管理」のようなERP的な機能を追加するといった作業でした。

10~20年近く前の「生産管理システム」で、生産計画 / 製造管理 / 資材管理 / 実行予算管理 / 購買・在庫など一貫した製造工程に対応することから様々な機能を内包することからデータベースは複雑にリレーションを張っていることはすぐに想像できましたが、改修するためにはいずれにせよソースコードを読み込んでいく必要があります。この案件で、いわゆるリバースエンジニアリングっぽいことをした時に取り組んだことや経験したことを記載します。

VB6の読み方を理解する

VB6を触ったことがなく読むのも初めてだったため、まずはVB6の特徴を覚えるために当時お世話になったサイトです(懐かしい)。dobon.netとMicrosoftの公式リファレンスを読み、開発環境を作り試しに動かしてみる、みたいなことを何度かやって書き方・読み方を覚えました。C#にかなり似ていたので、習得にそこまで時間はかかりませんでした。
dobon.net https://dobon.net/

とにかく対象の言語を覚える(都度 調べながら書ける)ことを最優先にしました。その言語をマスターするのにはある程度時間が必要になりますが「業務上使うことが出来る」のレベルであれば、恐らく一番時間がかからないタスクだと考えたからです。
改修に取り組む対象の分からないが多すぎるとどこから手を付けて良いかパニックになりそうですが、1つずつ確実にタスクを減らしていくことで着実に進捗すると考えたので、一番簡単そうな作業から着手しました。

VB6を覚えたあとは、実際にソフトウェア内でのコーディングルールを覚えるべくソースコードの読み込みを行うのですが、その際一番驚いたのはVB6にtry-catchが存在しないことでした。
ではどのようにして例外処理を行っているのかというと、GoToステートメントをめちゃくちゃ多用していた状況で、それまで「GoToは禁忌」だと教わってきた自分としてはかなりの衝撃を受けました。例外処理が8割で、2割程度それ以外でもGoTo文が使用されていたと思います。
私はこの時キーボードを放り投げるところでした。これまでtry-catch-finallyを可能な限り綺麗にスマートに書くことを意識してきたのに、世の中にGoTo文を乱用している製品もあるんだ(あったんだ)ということを初めて知った為です。

例外処理を行う為に使用しているGoToに関しては「try-catchによるラップがされていないだけ」と捉えれば特段違和感はなかったのですが、それ以外のGoToに関してはソースコードに矢印を引くような作業が必要で可読性が非常に悪かったです。
またソースコード管理がなされておらず変更管理はコード中のコメントのみから読み解く必要があった為、ほとんど推理ゲームのようなコード読み取りを行うケースもあり このあたりは非常にカロリーを使った気がします。

  • // 20xx.xx.xx 3行追加
  • // ごめんなさい

こういう1行コメントばっかり……

ユーザヒアリングを行う

古いアプリケーションであり、お客様もそれなりの年数このアプリケーションを使い続けていることが推察できます。全機能の中から利用していない機能を除き、利用されている機能を中心に業務フローを作る為、お客様へヒアリングを行いました。

どの機能を誰が何人くらいでどのような場合に利用しているのかを2~3回に分けてヒアリングし、アプリケーションに関わる人々を明らかにしフロー図を作成。フロー図を元に自分でもソフトウェアの動きや流れを再現し、ブレークポイントを置きながらコード上での呼び出しも一緒に確認し、コンポーネントの繋がりも理解をしていきました。

簡易的な仕様書を作成

言語仕様の理解、ユーザの業務フローの理解、コンポーネント間の繋がりの理解
この3点の理解を行ったところでプロジェクトメンバーの増員準備を行いました。予算的に開発工数を充てられる期間はおよそ1ヵ月程度であることが分かったため、私1名ではかなり苦しいスケジュールになることが想定されたためです。自身の理解を他メンバーに共有する為、簡単な仕様書を作成。また改修機能と新規開発範囲を図示し、画面設計書と共にチーム展開を行えるよう整備いたしました(仕様書はsphinxで作成)。

コーディング

コーディングの際「コメントをたくさん追記する」よう気を付けていました。
社内のだれが作ったわけでもない、誰も知らないソースコードを書き換えていくにあたり 自身のコード改修部分は勿論、改修に際し関連する機能部分のコメントもついでに追記をしていきました。
「自分の次にこの案件に携わる人」の道しるべを少しでも多く残すことを意識したためです。2回目の改修や、バグ修正の際は同じような工数負担を強いないようにするため いつもより気持ち多めにコメントを残すようにしています。

また当然ですが、元の製品のコーディングルールに沿って記述するよう心掛けました。ただし上述の「無意味なGoToステートメント」だけは利用しないよう、チーム内でのポリシーとして定め開発作業を進めていきました。

開発工数がかなりシビアでしたが、約1ヵ月でテスト含めなんとか開発を終えます。内心炎上ギリギリというか最初から燃えている雰囲気のあるプロジェクトでしたが、焦らず仕様把握に時間をかけたことが最終的には功を奏した形となります。

リリースをシンプルに

本件のシステム改修作業と本筋から離れるのですが、業務フローをヒアリングした際に「リリース作業が非常に面倒なことになっている」ことが判明しました。
具体的には、リリース用のサーバにデプロイしたのち各自が業務用PCで手動でexeファイルやライブラリのファイルを入れ替えている = 作業手順書を元に実施しているという状況らしく、これらが原因でテクニカルサポートの工数が増加したり、システムバージョンの不整合が生じているらしいことが分かったのでした。

個別でシステム配信プログラムを開発し、システム起動をトリガに最新版を自動でダウンロードするように組み込むことで、常に最新状態を保持 + バージョン差異を無くすことに成功しました。リリース後にユーザが実施しなければならない作業がゼロにになったことで、次に案件担当される方も余計なことを考えずに開発に専念できるようになりました。

Discussion