解析を早くするのは難しい

はじめに

 先日、後輩がソース解析に苦しんでいました。
 「仮説と検証だよ」と苦し紛れにアドバイスをしましたが、「そんなこと言われても」困るよなぁ、と後になって思いました。

 また別の日には、「まずは概要だよ」と後輩に言ってみました。
 言われた後輩はなんか困ってました。

 でまあ、反省をしまして。
 後輩から突っ込まれるの覚悟で、私のやっている方法をもう少し具体的に説明する元ネタにしようという、そんなメモです。

前提

  • Javaで書かれたソースを解析対象とします。
  • モジュール単位ぐらいを想定します。
    例えば、「org.apache.wicket.markup.MarkupCacheがキャッシュしているのは、Wicket利用者からみて何に対応するものなのか」とか。
    ……実際何をキャッシュしているんでしょうね。ちょっと気になってきた。


解析の流れ

 私は下図の流れで解析してます。
 

 思いつくままに解析して、それで知りたいことがわかったら、それはそれで。
 「どうやら手強そうだぞ」となったら、解析の手がかりを増やすために真面目に解析に取り組みます。

概要の仮説を立てるとは

どう立てる?

 仮説というと大げさですので、妄想とか想像とかという単語で表現した方がいいかもしれません。

 現在分かっていることを踏まえて、「ま、こういう要素があるだろう」というノリで「多分存在する要素」を抽出し、「要素間にはこんな関係があるだろう」というノリで関連にあたりをつけます。

 「どの程度まじめに作ればいいの?」と思われると思いますが、下記の「何の役に立つ?」の節に記載したメリットを享受できる程度のもので良いかなぁと。
 概要の構成要素の例は、「概要の例」の章に書いてみました。

 作った仮説は図にして紙に描いても良いですし、脳ににとどめておいても良いかと思います。

何の役に立つ?

 まず、自分がどの抽象度で解析取りかかろうとしているか分かります。これは、解析の際に「まず」描いてみる図を決める指針となります。
 扱う抽象度に応じて描く図を選択するのですが、明確な基準があるわけでもないので、結局のところフィーリングになってしまいますけどね。

 私が保持している選択肢を下記に挙げます。
 ですが、多くのケースについて、クラス図で概略が掴めます。他の選択肢は「クラス図では分かりにくそう」という時に採用します。


 また、ここで立てた仮説は洗濯物リストとして機能します。洗濯物リストとは、「存在しているものかもしれないもの」のリストのことを言います。
 下記の役に立ちます。

  • 「あると思っていたものがない」というのは、経験上解析の強力なヒントになります。
  • 「ここも解析しておいた方が良い」というポイントについて、解析漏れをする確率が減ります。

 仮説を立てた場合、仕事で解析する時に得られるメリットとして、進捗を他の人に伝えやすいというメリットがあります。
 解析の初期のみ有効な話ですので、いうほど進捗報告がしやすいというメリットは生きないかもですが。

概要に含まれる要素の例

 今回の前提の範囲において、多くの場合、下記の内容を押さえたら、概要を把握できたと言っていいと思っています。
 オブジェクト指向的でなくて嫌だと思っているのですが、役立つことが多いのも事実だったり。

  • メイン処理を呼び出す処理
  • メイン処理への入力データのデータ型
  • メイン処理
  • メイン処理結果または出力データ

仮説の例

 文章で書いていてもぴんとこないとこないと思いますので、恥を忍んで「ややこしそうなのを解析するときは、こんなのを脳内に作っている」というのを絵にしました。
 思いついたら、関連の線と、数も書いておきます。
 描いた絵は同僚に見せることもあるかもしれませんが、どうせ一瞬しか見せないので、恥ずかしがらずに思いついたことは明記しておくといいです。
 あと注意事項としては、記号には凝らないこと。記号に凝ると、妄想を素直に描くことに抵抗が生まれがちなので。

概要のクラス図の例

 仮説で得た、「存在するはずの要素」を調査し、概要を調べたのが下図です。
 ここまでくると、「IMarkupLoaderのロード処理のソースを次は読んでみるか」とか「MarkupContainerがMarkup読み込みのキー要素っぽいからそこを読んでみるか」とか作戦を立てられます。

概要に含まれる要素の例とクラス図の項目との対応

概要の例に挙げた要素 図の要素
メイン処理を呼び出す処理 MarkupContainer.getAssociatedMarkupStream()
メイン処理への入力データのデータ型 MarkupContainer
(多分)
メイン処理 MarkupCache.getMarkupStream()
メイン処理結果または出力データ MarkupCache.markupCache
MarkupCache.markupKeyCache
(多分)

仮説の要素とクラス図の項目との対応

仮説の例に挙げた要素 図の要素
MarkupCacheクラスからデータを取得する誰か MarkupContainer.getAssociatedMarkupStream()
MarkupCacheクラス MarkupCache
キャッシュされたデータ MarkupCache.markupCache
MarkupCache.markupKeyCache
(多分)
Markupを新規生成する誰か IMarkupLoaderを継承するクラス
キャッシュにデータを突っ込もうとする誰か MarkupCacheクラス

最後に

 書き終えてみると、「そんなこと言われてもなぁ」から脱出できるに至るクオリティか怪しい気もしますが、あんまりつっこまないでください。
 ま、私と後輩のコミュニケーションには役立つでしょう、きっと。

参考文献

洗濯物リストが何なのかは、下記の本に書いてあります。