ソースコードを読む技術 アプローチ編

twcritique
1)ソフトウェアとして構成されるソースコード一式を入手する(対象とする範囲を明確にする)2)システムの全体像を把握する意味で、そのソフトウェアが利用しているライブラリ、インタフェースへの問い合わせをすべて列挙する3)列挙したうえで、それを分類し、理解をふかめる

ソースコードとは何か?「読む」とはどういうことか?

ソースコード(Source code、ソースプログラム、原始プログラム)とは、人間が記述した、ソフトウェア(コンピュータプログラム)の元となる一連の文字の羅列である。
ソースコード – Wikipedia

コードを読むということは、そのソフトウェアを理解することにあたり、そのソフトウェアの定義が必要となってくる。

ソフトウェアをまず、マンマシンインタフェースとしてモデル化する

マンマシンインタフェース(man machine interface)とは、人間と機械の間で情報のやりとりを行う際に情報伝達の仲介を行う機器やコンピュータプログラムの総称である。
マンマシンインタフェース – Wikipedia


https://matome.naver.jp/odai/2137573089366767001/2137573570567685603
配置モデル(仮1)
ここでは構成を実行環境と仕様とで大きく二つに分け、ソースコードを仕様に仮に分類して考察する。
矢印は依存関係を示しており、オープンソースを前提とすると仕様が明確に存在しないケースもあるため、それを考慮して仕様は必須としない。

実行環境においては、ソフトウェアはインスタンスが入力または出力のインターフェースに依存して存在する構成として考える。

ソフトウェアを「読む」ことを、ここでは入出力ライブラリとの関連で考えてみる


https://matome.naver.jp/odai/2137573089366767001/2137573570567685803
配置モデル2(仮2)
つまり、ここでは「読む」ことを利用するライブラリ(インタフェースを規定し、動かすもの)との関連を中心に理解することと定義する。
これは、アルゴリズム、言語系そのものの理解、ソフトウェアそのものの内部仕様理解に先んじて、インタフェースを理解する方向性であることを明記している。

https://matome.naver.jp/odai/2137573089366767001/2137573570567685903
配置3
オープンソースの時代になり、理想的ではあるが現実に起こりえないケースは、グレーで示したようなケースである。ここでは、ソースコードの理解は、内部仕様(またはそれに類する要求)をもとに行われるべきであると考えられている。
ライブラリもまた、仕様の明記があったうえで、(自分でない誰かが)それを適切に設計、実装し、完璧に評価している前提でソフトウェアを理解しようとする。この場合、ライブラリやインタフェースは、言語系にある命令の一つにすぎない。

ソフトウェアを「読む」ことを、ライブラリその他のインタフェースとの関連性において理解するとここでは仮に定義する

ライブラリへのインタフェースと、そのライブラリ自体を理解し、それをどのように使っているかを理解することを、ソフトウェアのソースコード、アルゴリズム、内部メモリ管理の理解よりも優先して行う。

このモデルが対象とするもの、しないもの

このモデルが主に対象とするものは、オープンソースの組み合わせにより、外部のライブラリに依存したかたちでコードが構成されているソフトウェアやシステムである。

インタフェース/ライブラリをどのように理解するか?

ライブラリ自体は抽象的なものであり、実際は実行環境と処理系によって表現も実装も異なる。OSでの切り口から考えたとき、例えばunix/linux系では、デバイスはファイルとのやり取りとして表される。多くの言語系もそれを踏襲している場面はあるし、javaではストリームという内部表現があってデバイスとやりとりする場合が多い。C言語ではファイルのI/Oとしてデバイスとやりとりする場合が多い。
インタフェースの対象や実体がファイルだけとは限らない。
多くのリレーショナルデータベースでは、SQLと呼ばれる文字列の情報により、データベースを操作するし、インターネットの時代になるとHTTPを利用したやりとりも重要になっている。この場合は、取り決めに基づいたレスポンスコードに従って処理が分岐し、その後たいていの場合はファイルとしてボディ情報の読み込みを行い、問い合わせが終わる。

どの場合も、処理系、言語系の組み合わせによって、いくつかの問い合わせの類型が導きだせる。この類型は、他のソフトウェアでも利用されている可能性が高いので、この類型を探ることが、ソースコードを読むうえでの一つの重要な目的になる。

実際、どのような手順で読んでいくか?

以下を提唱する
1)ソフトウェアとして構成されるソースコード一式を入手する(対象とする範囲を明確にする)
2)システムの全体像を把握する意味で、そのソフトウェアが利用しているライブラリ、インタフェースへの問い合わせをすべて列挙する
3)列挙したうえで、それを分類し、理解をふかめる
1−3の手順を繰り返しながら、ソースコードを読んでいく

javaでの例 1ラウンド目
1)ソースコードを入手する。
2)ソースコードのパッケージ構成(javaの場合はフォルダ構成となる)を列挙する。次に各パッケージごとに、importが行われているパッケージを列挙する(javaの場合はこれで、利用しているライブラリ、インタフェースの概括は殆どのケースで行えるはず。importをしないで直接クラスライブラリを呼び出しているケースでは、呼び出しの列挙をしてくれるようなツールを利用する)
3)パッケージ同士の呼び出し、パッケージからライブラリに対する呼び出しを、配置図(Deployment Diagram)としてまとめる


https://matome.naver.jp/odai/2137573089366767001/2137573744767779403
1ラウンド目 手順3の例示
ここでは短いコード wget/java
http://pipasoft.com/free-java-classes/download/wget.java
を利用して、パッケージの配置図を書いてみる。

不確定性のなかでソースコードを読む

例示では、ソースコードはjava.io/java.net/java.util(Vector)を利用するはず、ということしかまだ分からない。
ただし、高い確率で、io/net/Vectorに具備された機能以外は使っていないコードである、ということはこの時点でも云えるはず。

native等の利用により、全く別の用途で実装されている可能性はある。あるいは、呼び出しておいて利用しない可能性もある。あくまで概括と予想のもと、ソースコードを「読んで」いる

このパッケージは、データストリーム、直列化、ファイルシステムによるシステム入出力用に提供されています。

ネットワークアプリケーションを実装するためのクラスを提供します。

Vector クラスは、オブジェクトの可変長配列を実装します。

どこまで読むのか

目的や用途に応じて概括の粒度は変わっていく。

javaでの例 2ラウンド目
1)他に参照した方が良いソースが無いか(ソースコードの範囲の再定義)考える
2)ワイルドカードなどのパッケージ呼び出しがある場合は、パッケージ中具体的にどのクラスが呼び出されているかを列挙してみる
3)具体的なクラスまで落とし込み、どのパッケージが、どのようなクラスを呼び出しているかを概括する。

https://matome.naver.jp/odai/2137573089366767001
2017年09月26日