ソーソコードの追い方読み方がまるでわからない。
基本的なことを含めほとんどプログラム知識がないのに、それでもソースコードを読んで改修などをしないといけない……らしい。
自分のような知識なしの人間がどうやって追っていきソースコードを効率よく読み解けばいいのか、関連知識や読解方法を調べたり試行錯誤したことをまとめていこうと思います。
目次
ソースコードを読めなくて困っていた状況
私は右も左もプログラミングのことをわかっていない人間です。
「ソースコードを読んで改修をして」と言われると、そこで試合終了してしまう人間です。
思考できない自分の頭が悪いという絶望。
わからずに時間ばかりが進んでいく絶望。
ドキュメントの場所さえわからない絶望。
誰も教えてくれる人がいないという絶望。
さらには、、、
文法を知らないプログラミング言語という絶望。
インターネットがつながらない環境という絶望。
そんな絶望だらけの状況を変えられたらなということで、的を外したことを書きまくっていても、とにかくこの記事を書いておこうと思った次第です。
ソースコードを追うときに起こりうる問題
関数やクラスなんかが多くなってくると、それぞれの部分部分では読めても、全体としてどんなことをするプログラムなのかが把握できない。
コードを上から読むと、関数などを読むことであちこちに飛び回ることになって頭が混乱する。
どの行を読んでいたのか、あるいは、なんのために読んでいたのか忘れる。
読んだはいいけれど、処理するデータのイメージが湧かない。
このつらい状態が続くと……
- ボーっとしてしまう
- 暇になる
- 眠ってしまう
- 泣きたくなる
上記のようになる。
こういった困った事態をどうにか解決するための対策として、ソースコードを読むときに考えること、行うことを以下に書いていきます。
ソースコードを読むとは【コードリーディングの定義】
コードリーディングの定義
大前提として、「ソースコードを読むとは、どういう行為なのか」定義を一言で書いておきたいです。(あくまで私の認識です)
「ソースコードを読むとは、プログラムの意味(≒プログラムの実行結果。現実世界での効果)を、想像できること」だと思っています。
(プログラム意味論とかいう分野もありますが、、、私には知る必要のない高度分野です)
コードの構成要素は「文」と「式」
また、余談ですが、「プログラミング言語」という言葉からわかるように、プログラミングは自然言語(英語、日本語とか)にアナロジーされているかと思います。
私がプログラミング言語の入門書を初めて読んだときは、「文」という言葉が自然と出てきて、ほぼ説明が書かれていないかったのですが、プログラミングにおける「文」とは、(副作用を起こしうる)プログラムの実行単位です。
また、プログラミングにおける「式」とは、(値を返す)プログラムの評価単位です。「式」という言葉からわかるように、プログラミングは数学にもアナロジーされていると思います。
「文」「式」を意識しているプログラマーは、意識していないプログラマーよりも、キレイなコードを書く、、、はずです。
それくらいには、大切な基本だと思っています。
なぜか入門書だとあまり説明されていないのですが、入門者向けではないのかな。。。
なぜ大切なのか気になる人はプログラミングにおける副作用の意味とはを読んでみてください。
気にしたことなかった人には面白い内容だと思います。私は初めて知ったときに「へぇ」となりました。
コードリーディングという行為に必要な知識とは【コードリーディングの行為分解(別定義)】
ここでは、ソースコードを読むとは、どういう行為なのか、なぜ難しいのか、どんな考えがあるとよいのか、もう少し詳しく書いてみます。
ソースコードを読むことの難しさ【ソースコードの特徴】
まず、前提として、ソースコード(ソフトウェア)は、難しいものです。
ソースコードの難しさの特徴の一つとして、「不可視性」があります。
ソースコードとは、あることを実現するために、記述されているわけですが……
色んな状況から判断して、意思決定がされた結果として、ソースコードが記述されています。
けれど、そのソースコードが書かれる(実装)までの背景事情(仕様、設計)は、ソースコードだけからは知ることができません。だから、難しいです。調査したり、頭の中で推測する必要が生まれます。
また、プログラム実行の状態(≒結果)は、常に可視化されて目に見えるわけではありません。だから、難しいです。調査したり、頭の中で推測する必要が生まれます。
(※この難しさを軽減するために、プログラミング言語や開発環境は進化しているし、コーディングの作法もある)
コードリーディングの別定義【コーディングの逆過程行為】
ソースコードの難しさの特徴を踏まえて考えれば想像できると思いますが、ソースコードを読む行為は、単純にその1行のソースコードを見ていればできるという行為ではありません。
下記の図のように、様々な知識が必要になってきます。
(図の階層の区分けや列挙は適当です)
様々なことを考えながら読む必要があります。
コードリーディングという行為の定義を別の言い方ですれば、「コーディング(仕様→設計→実装)過程の、どこか途中からさかのぼって、現実世界における意味を理解すること」になります。
自分が担当する内容次第で、求められる知識範囲や重要度は変わってきますが、少なくとも基本文法だけを知っていればできるという行為ではありません。
(と言っておきながら、私の経験上だと、設計や実装をする人は、様々な知識がないとキレイなコーディングができないですが(そして、汚いコードだと読む人は苦労する)、読むだけなら別にさして知識がなくてもできると思っています。まさに読むことで知識を増やしていくことができますので)
コードリーディングの別定義【文法観点と文脈(文意)観点の変換行為】
ソースコードを読むことは、「現実世界における意味を理解すること」と書いていますが、この意味を別の表現で言い直すと、コードリーディングとは「文法観点と文脈(文意)観点の変換行為」とも言えます。
この変換行為が、自然言語よりもプログラミング言語の方が難しいのかなと思います。
どういう意味かというと、例えば、(オブジェクト指向言語で説明しますが)
object A {
object B;
}
このように文法上、オブジェクトAが、メンバ変数としてオブジェクトBを保持しているとします。
このとき、オブジェクトが何なのかによって、下記のように文意はガラリと変わります。
オブジェクトA | オブジェクトB | 文意(現実での意味) |
---|---|---|
人間 | 人間 | 関連(協調) |
人間 | お金 | 所有 |
人間 | 手 | 集約(コンポジション) |
プログラミング言語は、自然言語よりも文法が少ないので、文法上は違いが見られないけど、意味上は違うということが起こります。
なので、プログラムを読むときには、文脈(前後情報、背景事情、設計、仕様)を把握できているかどうかの差が読解に与える影響が大きくなります。
なぜソースコードがわからないのか把握する
ソースコードが読めない主要因
「あー、読んでもソースコードがわからない。頭に入ってこない」みたいな状態になったときは、まず、なぜソースコードがわかないのかを把握しましょう。
コードリーディングにはつまずく段階があります。たぶん。
- 文法
- 概念・フレームワーク
- 暗黙の作法(ルール)
- 業務知識・担当機能への理解
- 理解はできるけど記憶できない(読んでいるうちに内容を忘れる)
上の図だと、自分はどのあたりでつまずいているのか把握して、それを補うように対策をやってみればいいんじゃないでしょうか。
読みにくいソースコードの状況・条件とは
ソースコードが読めない主要因について、もう少し掘り下げてみます。(読む必要はないです)
この記事を読んでいる人は、今までにソースコードを読めなくて困った経験がある人だと思いますが、読みにくいソースコードの条件、あるいはソースコードが読めなくて困る状況とは、どんなときか具体例をひとつ挙げておきたいと思います。
例えば、読みにくいソースコードの例・状況としては、
「決済の結果を、ユーザーが求める形に整えて、明細書に出力する」ソースコードを読むことを想像してみます。
このときの状況は下記です。
- 自分の知らない文法が使用されている
- 自分は上記の業務で実現したいことの知識がまるでない状態
- 変数が処理の先頭で20個も定義されている。しかも、1000行に渡って散らばっていて、変数の値が色んな場所で書き換わっている。業務知識がないから、変数が表すデータが現実でなんなのかわからない
- if文で1000行近くが大きく囲まれている
- for文が5つ出てくる。しかも、それぞれのfor文の階層も5階層もある
(ここまでひどいソースコードは出会ったことがないですが、)上記の状況を想像すれば、「読みにくい」と感じるはずです。
「読みにくい」と感じる理由は、プログラムを読むときに、下記の条件があるということでしょう。
- 知識が足らず処理をあいまいに想像するしかない箇所が出てくる(=文法知識不足)
- 記憶しておくべき実行状態が多いこと(=if、forなどの条件分岐を伴う処理構造が多い、変数の意味が多い、変数の状態変更が多い、そして処理の流れが覚えられない)
- 結局のところ、現実世界でやりたいこととソースコードの処理の結びつきが想像できない(=現実世界の事象と、処理構造、変数が結びつかない)
「読みにくさ」は、読むときにわからないこと(知識不足)、覚えておくべきこと(脳内メモリによる一時的記憶)が多ければ多いほど、二次関数的に増していきます。
そして、限界を超えると、「読めない」になります。
やる気を失います。
コードリーディングするには、わからないこと、覚えておくべきことを減らすようにして、自分の制御範囲内に留めるのが大切だと思います。
ソースコードを読む上での心構え
まず、ソースコードを読むうえで、以下のことは大前提として常に意識しておくようにするように心掛ける。
自分にとって必要な部分に集中して読むようにする。
(完璧にすべてを細かく読もうとはしない。必要に迫られたら、そのときに読めばいい)
自分の携わっているシステム、部分の役割や流れを把握しておく。
そのプロジェクトでの書き方の決まりがあればそれを頭の片隅に意識しておく。
そのソースコードを書いた人が何を思いながら書いたのか想像しながら読む。
楽しみながら読む。
そのソースコードの行き着く先、役割はなにか。
(なんのためのソースコードなのか。扱うデータ(構造)と処理フローを意識する)
ソースコードの解析方法の分類
ソースコードを読んで追っていく方法は大きく分けて2種類に分かれる。
動的にソースコードを追う方法
デバッガなどを使って実行時の動きを追う方法。
静的にソースコードを追う方法
ソースコードそれ自体を読んで追う方法。
ソースコードを追う手順
できることなら、ソースコードを読むときの手順は以下がよい。
動的にソースコードを追う方法 → 静的にソースコードを追う方法
静的な解析は、あくまでプログラムの動作を予想することになる。
対して、動的な解析で見るのはプログラムの動作の事実。
プログラムの動きがわからない状況なら、まずは実際の動きの事実を見ておいたほうが、当然にコード読解の予想の方向付けがしやすいので、速く正確にできる。
静的なソースコードの読み方
状況によって最適な方法は変わってくるのかと思いますが、今、調べて出てきた方法を書いておきます。
ドキュメントを読む・人に聞く
仕様書や設計書、コード規約など、ソースコードを読むときに役に立つ資料は読む。
機能について知っている人がいれば聞く。
ソースコードを読むことは、プログラムの処理で現実世界でなにを実現したいのかを知ることなのだということ、また、その際に文脈の把握が重要だということは上述した通りです。
実現したい業務の知識について知っていれば、プログラムの処理を読解する難易度は各段に下がります。
充実したドキュメントと優しい人に囲まれた環境の人は活用しましょう。
メモを取る
フローチャート、クラス関係図、関数呼び出し関係図、データ構造図、コードの行番号とその該当処理など、とにかく自分が必要だと思ったことについては簡潔にメモを取っておくようにする。
追記:やはりメモを取ることは重要だと思いました。
私のようなショボイ奴だと、興味のないコードを見ているときや集中していないときは眺めているだけだと頭がボーッとして頭に入ってこない。
また、なにかの理由で作業が中断したときに内容を思い出せなくなるなんて事態も防げる。
さらには、実装完了してから1か月後とかにプロジェクトマネージャーから、内容を詳しく教えてとか言われても、忘れてしまっていてすぐに答えられないなんて事態も防げる。
読解レベルが上がるまでは、時間があればたとえそれに関する設計書がすでにあったとしても、自分の手で自分がわかりやすいように軽くでもメモを取っておく。理解しやすくなるし記憶にも残りやすい。
ツールのショートカットを使って読む
IDEやテキストエディタなど、ソースコードを読むときに自分が使っているツールのショートカットは使えるようにしておく。知っているかどうかで効率が違ってくる
ディレクトリ構造を読む
どういう方針でディレクトリが分割されているのかを見て把握する。
それぞれのモジュールがどういう関係にあるのか確かめる。
そのプログラムがどのように分割され組み立てられ作られているのか概要を知る。
ファイル構成を読む
ファイル名も含め、ファイルの中に入っている関数(名)も合わせて、どういう方針でファイルが分割されているのか見る。
システムの各機能の流れを書いてみる
自分が調べたい箇所に関係するシステムの全体の流れについて、図なりにして書いてみる
略語の調査
わかりにくい略語があればリストアップしておいて早めに調べる。
英語だと単語の頭文字をとったり、母音をなくすとかが多い。
また、対象プログラムの分野で有名な略語は説明なしで使われている。
関数の呼び出し関係を把握する・関数を読む
関数同士がどのようにつながっているのかを把握する。
関数の動作、内容を理解する。
データ構造を知る
プログラムは、あくまでデータを処理するためにある。(らしい)
なので、どんなデータが入出力されるのか、どう変化していくのかに着目しておくようにする。
Javaなどオブジェクト指向言語のソースコードの読み方
変数(≒オブジェクト)のスコープ(可視範囲)を意識すること。
オブジェクト指向言語のコードは「上から下に」だけ読む物ではない。(らしい)
私はコードの一行一行を読むときは当然「上から下に」読むのですが、処理単位で読むときは「多方向に」関係を読むイメージをしています。
「多方向に」とは、オブジェクト同士の関係を意識しようという意味です。
(たしか)オブジェクトは関連した処理とデータをまとめた存在(カプセル化)であり、オブジェクト指向プログラミングは(情報隠蔽によってブラックボックスの)各オブジェクト同士の相互影響で成り立つ世界です。
日本語のような自然言語や、手続き型プログラミングのように、上から下のように順々に読んでいくものだという認識だけでなく(最初の頃はこの認識だった)、ネットワークのように張り巡らされた状態の言語だと思って読むのがラクです。
プログラミング言語やフレームワークの設計パターンを知っておく
こういう優れた、各プログラム言語でよく使わられる定石や公式といったものを知識として蓄えておくようにしていく。
動的なソースコードの読み方
動的にソースコードを解析してくれるデバッガツールを使いましょう。
プログラムを動かしてみる
実際に動かしてみて、どんな動きをするのか見てみる。
メジャーなプログラミング言語なら、IDEなどの開発環境には、たいていはデバック実行・ステップ実行ができるようになっていると思います。
デバッグツール(デバッガ)の使い方を知る
デバッグツールの使い方を最低限知っておくとよいです。
極端に言うと、開発ツールの機能のうち、最も初心者が知るべき機能だと思います。
また、極端に言うと、ほとんど文法を知らないプログラミング言語で、フレームワーク知識のない状態でも、一行一行の処理をデバッグで止めて、その都度データの状態を確認することができるなら……
朝から晩までひたすらコードをデバッグし続ければ、どのような記述のときに、どんな処理がされるのか、ある程度は推測できるようになると思います。
(知らないプログラミング言語を読まないといけない状況になったら実感できるかと)
なのでデバッグは必須知識です。
デバッグはGoogle検索と並ぶプログラミングの先生です。
好きに操作して動かしてみる(推測の確認)
デバッグをするときは、「ある処理(行)のときに・データ状態はこうなっているはず」という自分の推測を確かめる、仮説検証の行為だと思っています。
自分の推測と実際の処理動作が正しいのかどうか。
推測と実際のズレはどこにあるのか。
それを考えながらやっていくのがオススメです。
処理の途中で値を変えてみたら、動作にどんな影響を与えるのかを見ながら動かしていくとか。(デバッグ中に値を変えられる機能です)
自分の着目したタイミングでのみコードを見たいから、条件付けして止めてみたり。(特定の条件のときのみ処理を止める機能です)
詳しくないですけど、フィルターをかけてみたり、REPLで確認したり、インスペクトしたり、監視したり。。。
自分の開発環境でできるデバッグ機能を使って、好きに操作していきましょう。
ソースコードを読むということ
ソースコードを読むということは、誰にとっても瞬きでできるようなことではなく、たぶん誰にとっても多かれ少なかれ手間がかかるものなのだなと感じました。
現時点で軽く調べたことを慌てて書いてしまっただけなので、この記事は勉強用のくせにまとまっていなし、レイアウトもかなり読みにくいですが、ひとまず直近はこの記事で書いた内容でソースコードを読み解けるのかどうかを試してみようと思います。
そして、ソースコードを読むに当たって助けとなる方法の情報があれば、随時書き加えていけたらなと思います。
1年後の追記
この記事を書いてから、1年ほど経って見返してみると、見にくいしまとまっていないけれど、書いてあること自体はそんなに的は外していないんじゃないかなと思いました。
ソースコードを読解するのに知っておきたい前提知識などで勉強したり、少し開発経験を積んだあとに見返してみると、「ああ、なるほど、これは意識したい」と思えることが書いてありました。
またいずれ、徐々にきちんとまとめ直そうと思います。
(メソッド呼び出しの流れを追っていると、途中でインターフェースに行き着いてしまって、その先の実装コードが気になってモヤモヤはするけど、どうすればいいのかわからないなんてときにどうするといいのか、など具体的なこともそのうち書き加えていきたいです……少し具体的な内容を書きました。→ コードリーディングやコーディングの効率を爆上げしてくれる機能のまとめ)
1年半後の追記
この記事を読んでいる人には早いのかもしれませんが、フリーランスエンジニアのエージェント会社のサービスをまとめて比較するの記事の最後の部分は読んでおくと良いかもしれません。
また、エンジニアの人月単価はどのように決まるのかや単価収入を上げる方法については知っておいて損はないと思います。勉強のモチベーションにつながります。
振り返って見ると、私がもっと早くに意識しておくべきことだったと思うことです。コードリーディングやコーディングといった開発スキルだけでなく、他にもエンジニアとして知っておくべきコツはあるのではないかという内容です。