ソースコードの追い方、読み方などをまとめてみた
ソースコードの読み解き方が分からないとお困りではありませんか?
基本的な知識が少ない状態でも、ソースコードを読み、改修作業を行わなければならない状況が生じることもあるでしょう。
そんな私自身の経験から、ソースコードを追っていくための手順、効率的な読み解き方、必要となる関連知識や読解方法を調査し、ここで一緒に学んでいきましょう。
参考程度にご覧いただければ幸いです。
ソースコードが読めずに困っていた当時の状況
少々、プログラミングの知識はあるものの、初めて触るプログラミング言語の「ソースコードを読み解き、改修をする」ように求められたとき、私は絶望感に襲われました。
当然ながら、未知のプログラミング言語の文法はわからないし、ドキュメントの場所さえ見つけられないという状況でした。
そんな状況をどうにか改善しようと考え、失敗も恐れず、学んだことを書き留め、この記事を作成するに至りました。
ソースコードを追う際に生じる問題
関数やクラスが複数存在する場合、各部分は理解できても、プログラム全体が何を行っているのかを把握するのは難しい。
コードを上から読んでいくと、関数の読解によりコード内を飛び回ることになり、混乱を招く。
コードを読むこと自体はできたとしても、その処理の対象となるデータの具体的なイメージがつかめない。
このような苦しい状況が続くと…
・ぼーっとしてしまう
・何も手につかなくなる
・眠気が襲ってくる
・涙が出そうになる
などの状態に陥ります。
これらの問題を解決するためのアプローチとして、ソースコードを読む際に考慮すべき点や取り組むべき行動について以下で詳述しています。
ソースコードを読むこと【コードリーディングの定義】
まず大前提として、「ソースコードを読むとは、具体的には何を意味するのか」その定義を述べておきたいと思います。
「ソースコードを読む」とは、プログラムの意味(≒プログラムの実行結果やそれが現実世界で及ぼす効果)を想像できる行為だと私は捉えています。
また、余談になりますが、「プログラミング言語」という言葉からも分かるように、プログラミングは自然言語(英語や日本語など)になぞらえられています。
私が初めてプログラミング言語の入門書を読んだ際、「文」という概念が直感的に理解でき、詳細な説明はほぼ必要とされなかったのですが、プログラミングにおける「文」は、副作用を起こし得るプログラムの実行単位を意味します。
同様に、プログラミングにおける「式」は、プログラムの評価単位を指します。「式」という言葉から察するに、プログラミングは数学とも共通性を持っています。
「文」「式」を意識しているプログラマーは、意識していないプログラマーよりも、綺麗なコードを書くことが可能です。
それほどまでに、これらは重要な基礎となりますが、なぜか入門書などではあまり説明されていません。
コードリーディングという行為に必要な知識とは
ソースコードを読むことの難しさ【ソースコードの特性】
ソースコード、つまりソフトウェアは、複雑性を持つものです。
ソースコードが難しく感じる一因として、「不可視性」が挙げられます。
ソースコードは特定の機能を実現するために記述されるのですが…..
それは多様な状況を考慮し、意思決定の結果として形成されます。
しかし、そのソースコードが書かれる(実装)に至る背景事情(仕様、設計)は、ソースコードだけからは把握できません。これが難しさの一つです。調査を行ったり、頭で推測する必要が出てきます。
また、プログラムの実行状態(≒結果)は、常に可視化されて目に見えるわけではありません。これもまた難しさを引き起こします。調査を行ったり、想像力を働かせる必要が出てきます。
(※この難しさを軽減するために、プログラミング言語や開発環境は進化し続けており、適切なコーディングの慣習も存在します)
コードリーディングに要求される知識【コードリーディングの行為分解(別定義)】
ソースコードの複雑さを考慮に入れれば理解できると思いますが、ソースコードを読むという行為は、単純に一行ずつソースコードを見ていくだけの行為ではありません。
多くの知識が求められます。
さまざまな要素を考慮しながら読む必要があります。
コードリーディングという行為を別の言葉で表現すれば、「コードリーディングは、(仕様→設計→実装)の過程の途中から遡り、その内容を理解すること」と言えます。
担当する内容により、必要とされる知識の範囲や重要度は異なりますが、最低限の基本文法だけを知っていれば良いというものではありません。
(そうは言いつつも、私の経験からすると、設計や実装をする人は、多様な知識がないと美しいコードを書くことができません(そして、その結果としてコードの読み手が苦労することになります)。しかし、読むだけであれば、必ずしも多くの知識がなくても可能だと思います。むしろ、読むことによって知識を増やしていくことが可能です)
ソースコードの理解困難さを把握する
ソースコードの理解困難さを把握する
「うーん、ソースコードが全く理解できない!頭に入ってこない!この部分はどう動いているのだろう?」という状況に陥ったときは、まず、なぜソースコードが理解できないのかを把握しましょう。
コードリーディングにおけるつまずきポイントは以下のような段階に分けられることが多いです:
・文法の理解
・概念・フレームワークの理解
・暗黙のルール(コーディング規約等)
・業務知識や担当機能への理解
・内容の理解はできるが覚えられない(読み進めていくうちに内容を忘れてしまう)
これらの段階を確認し、自分がどの段階でつまずいているのかを把握した上で、その部分を補うための対策を考えてみてください。
ソースコードが読みづらい状況・条件とは
ソースコードの読みづらさの主要因について、詳しく見ていきましょう。(詳細な読解は不要です)
この記事をご覧の方は、過去にソースコードが読めなくて困った経験があると思います。そこで、ソースコードが読みづらい条件や、読めなくて困る状況とは一体どんなものなのか、具体例を挙げて説明します。
具体的には、「決済の結果をユーザーが求める形に整えて明細書に出力する」ソースコードを読むことを想像してみてください。
その際の状況は以下のとおりです。
・自分が知らない文法が使用されている
・上記の業務に関する知識が全くない
・20個もの変数が処理の先頭で定義され、しかもその変数が1000行にわたって散らばっており、値がさまざまな場所で書き換わっている。業務知識がないため、変数が表すデータが何を指しているのか理解できない
・if文で1000行近くを囲んでいる
・5つのfor文があり、その階層が5層にも及ぶ
(これほど酷いソースコードに遭遇したことはないかもしれませんが、)上記の状況を想像すると、「これは読みづらい」と感じることでしょう。
「読みづらい」と感じる理由としては、プログラムを読む際に以下の条件が存在するからでしょう。
・知識が不足しており、処理を曖昧に想像せざるを得ない部分が存在する(=文法知識の不足)
・記憶しておくべき実行状態が多い(=if文、for文などの処理構造、変数のデータ)
・結局のところ、現実世界で達成したいこととソースコードの処理との関連性が想像できない(=現実世界の事象と処理構造、変数の関連性が理解できない)
「読みづらさ」は、読む際に理解できない箇所(知識の不足)や記憶しておくべき要素(脳内メモリーによる一時的な記憶)が増えれば増えるほど、二次関数的に増加します。
そして、その限界を超えると、「読めない」状態になります。
やる気が失われます。
コードリーディングを行う際には、理解できない部分や記憶しておくべき要素を減らし、自分の管理できる範囲内に保つことが重要です。
ソースコードを読む際の心得
まず、ソースコードを読む際には以下の点を常に心に留めておくべきです。
自分にとって必要な部分だけに焦点を当てて読むこと。
(全てを完璧に細部まで読む必要はない。必要となったときに読む方針を取る)
自分が関与しているシステムや部分の役割や流れを理解しておくこと。
該当のプロジェクトにおけるコーディング規約や慣習を意識しておくこと。
そのソースコードを書いた人が何を考えて書いたのかを想像しながら読むこと。
ソースコードを読むことを楽しむ心持ち。
そのソースコードの目的や役割は何か。
(どのような目的のためのソースコードなのか、また、扱うデータ(構造)や処理フローを意識すること)
ソースコードの追い方は大きく2種類に分けられる
動的なソースコードの追い方
デバッガなどを使用して、実行時の動作を追跡する方法。
静的なソースコードの追い方
直接ソースコードを読み進めていく方法。
ソースコードの追い方の手順
可能であれば、以下の順序でソースコードを読むのが望ましい。
動的なソースコードの追い方 → 静的なソースコードの追い方
静的な解析はあくまでプログラムの動作を予測するためのもので、一方、動的な解析はプログラムの実際の動作を確認するものです。
プログラムの動作が不明な場合、まずは動作の事実を確認してからコードを読むと、効率的にかつ正確にコードを理解することができます。
静的なソースコードの読み方
最適なアプローチは状況により変わるかもしれませんが、以下にいくつかの一般的な方法を提案します。
ドキュメンテーションを読む・専門家に尋ねる
仕様書、設計書、コーディング規約など、ソースコードを理解するための資料を活用しましょう。
対象となる機能に詳しい人がいれば、その人に質問するのも有効です。
ソースコードの読解は、本質的にはプログラムが現実世界で何を達成しようとしているのかを理解することです。したがって、対象となる業務の知識があれば、コードの理解が格段に容易になります。
良質なドキュメンテーションと協力的な人々に囲まれている環境であれば、それらを最大限活用しましょう。
メモを取る
フローチャート、クラス関係図、関数の呼び出し関係図、データ構造図、そしてコードの行番号に対応する処理の概要など、自分が必要だと思う情報を率直にメモしましょう。
※(補足)メモを取る重要性を改めて強調したいと思います。
私のような平凡な者→(´・ω・`)でも、興味のないコードを眺めるだけでは、意識が散漫になり、情報が頭に入ってこないことがあります。
また、何らかの理由で作業が中断したとき、メモがあれば内容の復習が容易になります。
さらに、例えば実装が完了してから1ヶ月後にプロジェクトマネージャーから詳細を尋ねられたとき、忘れていた内容でもすぐに答えることが可能です。
ソースコード読解のスキルが向上するまでは、既に設計書がある場合でも、時間が許す限り、自分の理解を深め、記憶に残すために自分自身でメモを取るようにしましょう。
ツールのショートカットを活用して読む
IDEやテキストエディタなど、ソースコードを読む際に使用するツールのショートカットキーは、積極的に使えるようになることを心掛けましょう。その使用習熟度が作業効率に大きく影響します。
ディレクトリ構造を理解する
どのような方針でディレクトリが分割されているのか、各モジュールの関連性や、プログラムがどのように分割・組み立てられているのかを理解することは重要です。
ファイル構成を把握する
ファイル名や、ファイル内に含まれる関数(名)などから、ファイルがどのような方針で分割されているのかを把握しましょう。
システムの各機能の流れを描く
調査したい箇所に関連するシステムの全体の流れを、図などを用いて描き出してみましょう。
略語の理解
理解が難しい略語があれば、早めにリストアップし、調査しましょう。英語では単語の頭文字を取ったり、母音を取り除くなどの方法で略語が作られます。また、特定のプログラムの分野で有名な略語は、説明なしで使用されることもあります。
データ構造を理解する
プログラムは基本的にデータを処理するものです。そのため、どのようなデータが入出力され、どのように変化するのかに注目することが重要です。
Javaなどのオブジェクト指向言語のソースコードの読み方
変数(≒オブジェクト)のスコープ(可視範囲)を意識することが重要です。オブジェクト指向言語のコードは、単に「上から下に」読むものではありません。コードの一行一行を読む時は「上から下に」読むこともありますが、全体の処理を理解するためには「多方向」に関係性をイメージすることが有効です。オブジェクトは関連した処理とデータをまとめた存在で、オブジェクト指向言語は各オブジェクト間の相互作用により動きます。日本語などの自然言語のように「上から下」に順次読んでいくのではなく、ネットワークのように張り巡らされた関係性を考慮に入れて読むことが効果的です。
プログラミング言語やフレームワークの設計パターンを学ぶ
各プログラミング言語で頻繁に使われる優れた手法や公式などの設計パターンを理解し、知識として蓄えておくことが有益です。
動的なソースコードの読み方
デバッガツールを用いて、動的にソースコードを解析しましょう。
プログラムの動作確認
実際にプログラムを動かしてみて、動作を観察しましょう。ほとんどのメジャーなプログラミング言語はIDEやその他の開発環境を通じて、デバッグ実行やステップ実行を可能にしています。
デバッグツール(デバッガ)の活用
最低限のデバッグツールの使い方を理解しておくことが重要です。デバッガは開発ツールの中で最も初心者が理解するべき機能であり、コードを一行ずつ停止させて、その都度データの状態を確認できる能力は、ある程度のプログラムの流れを理解するのに役立ちます。
デバッグはプログラミングの必須知識であり、Google検索と並ぶ学習のための重要なツールです。
自由な操作と動作の確認(仮説の検証)
デバッグ時には、「ある処理(行)の際、データの状態がこのようになるはず」という自身の推測を検証する行為として捉えることが有効です。自分の推測と実際の処理動作が一致しているか、推測と実際のズレはどこにあるのかを考えることが重要です。
開発環境で利用可能なデバッグ機能を活用して、自由に操作してみることを推奨します。特定の条件時のみ処理を停止させる、値を変えて動作の影響を観察する、フィルターをかける、REPLで確認する、インスペクトする、監視するなど、多様な方法を試してみましょう。
ソースコードの読み方
ソースコードの読み解きは誰にとっても容易な作業ではなく、ある程度の手間と時間を必要とします。