プログラマー脳から学ぶコード理解の認知科学


## はじめに

『プログラマー脳 ～優れたプログラマーになるための認知科学に基づくアプローチ』（著：Felienne Hermans）を読みました。エンジニアとして成長する過程で避けては通れない「既存コードを読んだときに感じる混乱」について、認知科学の観点から解説されている部分が特に興味深かったので、自分の理解を深めるためにまとめました。

:::note warn
認知科学、プログラミングに関して初学者なので、誤った理解をしている可能性があります。
誤りがありましたら教えてくださると幸いです。
:::
## 混乱のタイプ

慣れないコードを読む際には、どんな場合でもある程度の混乱が引き起こされます。しかし、全てのコードが同じように混乱を引き起こすわけではありません。本書では、混乱を引き起こす3つの認知プロセスについて説明しています。

### 1. 知識不足による混乱

プログラムを読んだ時に、コードの持つ意味や使われている言語の構文がわからない状態です。

例えば、以下のコードはAPLという数学的操作のために特別に設計されたプログラミング言語で2進数表現をしているものです

```
2 2 2 2 2 T n
```

このコードを見ても、`T`がなにをしているのかわかりません。この混乱は**知識不足**が原因となっています。特定のプログラミング言語や技術に関する知識がないため、コードの意味を理解できないのです。

### 2. 情報不足による混乱

コードの構文や言語は理解できるものの、コードが何を実現しようとしているのか、関数の詳細や使われているAPIについての情報が不足している状態です。

以下はJavaで2進数表現をしているコードです

```java
public class BinaryCalculator {
    public static void main(Integer n) {
        System.out.println(Integer.toBinaryString(n));
    }
}
```

Javaの基本的な知識があれば以下のことはわかります：
- `BinaryCalculator`というクラスを宣言している
- `Integer`型の引数nを受け取る`main`関数を宣言している
- `main`関数の中で`toBinaryString`関数を呼び出している
- 結果を画面に表示している

しかし、`toBinaryString`メソッドが具体的に何をしているかという**情報がない**ため、このコードの詳細な処理内容を理解することができません。

### 3. 処理能力不足による混乱

コードの構文も理解でき、各関数やAPIについての情報も十分にあるものの、変数の状態変化が複雑すぎて追跡するのが難しい状態です。

以下はBASICで2進数表現をしているコードです

```basic
LET N2 = ABS( INT(N) )
LET B$ = ""
FOR N1 = N2 TO 0 STEP 0
    LET N2 = INT( N1 / 2 )
    LET B$ = STR$(N1-N2*2) + B$
    LET N1 = N2
NEXT N1
PRINT B$
RETURN
```

変数N1、N2、B$を定義して何らかの処理をしていることはわかりますが、各ステップで変数の値が次々と変わっていくため、頭の中だけで処理内容を追うことは困難です。正確に処理を理解するためには、各ステップでの中間値を書き留めておく必要があります。

この混乱は、変数に記録される処理途中の値と、それに対する処理内容を全て記憶しながら読み進めることの難易度が高いため、**処理能力不足**が原因となっています。

## 認知プロセスとは

認知プロセスとは、**脳内で起こる一連の化学的および電気的な信号を処理する工程**のことです。プログラミングコードを読む際には、主に3つの異なる認知プロセスが関与しています。

### 1. 長期記憶

長期記憶は、非常に長い間記憶を保持することができる脳の領域です。

- 靴紐を結ぶ方法、英単語の意味、普段使うプログラミング言語の構文など
- 長期記憶はコンピュータのハードディスクに例えることができます

**知識不足によって混乱する場合は、この長期記憶の問題**です。プログラミング言語や特定の技術に関する知識が長期記憶に保存されていないため、コードを理解できません。

### 2. 短期記憶

短期記憶は、入ってきた情報を一時的に保持するために使われる脳の領域です。

- 電話番号を一時的に覚える、メソッド名、変数名、使われているデータ構造など
- 短期記憶はコンピュータのキャッシュのようなものに例えることができます
- 短期記憶は一般的に2〜6個程度の情報しか同時に保持できないとされています

**情報不足によって混乱する場合は、この短期記憶の問題**です。コードの断片を理解するために必要な情報が不足しているため、短期記憶に保持できる情報だけでは処理内容を把握できません。

### 3. ワーキングメモリ

ワーキングメモリは、長期記憶と短期記憶の情報を組み合わせて実際に思考処理を行う脳の機能です。

- 新しいアイデアや問題の解決方法を形成する
- プログラミングコードを読んでいる時、ワーキングメモリを使って脳内でコードを実行しようとしている
- ワーキングメモリは脳のプロセッサのようなものと例えることができます

**処理能力不足によって混乱するのは、このワーキングメモリの問題**です。コード内の変数の変化や処理の流れを追跡するのに必要な計算処理が、ワーキングメモリの処理能力を超えてしまうため、混乱が生じます。

## 認知プロセスの相互作用

長期記憶・短期記憶・ワーキングメモリはそれぞれ別々の認知プロセスですが、コードを理解する際には密接に関連し合っています。

例えば、以下のようなRubyのeach文を見たとき

```ruby
fruits = ["apple", "orange", "melon"]
 
fruits.each do |a|
    puts a
end
```

思考プロセスは以下のようになります：

1. **視覚情報の取得**：目でコードを読み取る
2. **情報の一時保存**：`fruits`という変数に`["apple", "orange", "melon"]`が格納されていることを短期記憶に記録
3. **知識の呼び出し**：同時に、eachメソッドの使い方や`puts`の機能について長期記憶から知識を取り出す
4. **情報処理**：それらの情報をワーキングメモリで処理し、「配列の各要素を順番に取り出して画面に表示するプログラム」という意味を理解する

## 混乱を軽減するためのアプローチ

コードを読む際の混乱を軽減するためには、各認知プロセスの限界を理解し、それに対応したアプローチを取ることが重要です。

### 知識不足への対応
- 使用している言語や技術の基礎知識を身につける
- わからない構文やライブラリがあれば、すぐにドキュメントを参照する習慣をつける
- 定期的に新しい技術や言語の学習に時間を投資する

### 情報不足への対応
- コードにコメントを追加する
- 関数名や変数名を意味のあるものにする
- 適切なドキュメントを作成・参照する
- わからない部分はチームメイトに質問する

### 処理能力不足への対応
- 複雑なコードを読む際はメモを取りながら進める
- デバッガーを使って変数の値の変化を追跡する
- コードを小さな部分に分けて理解する
- リファクタリングを通じてコードの複雑さを減らす

## まとめ

プログラミングコードを読む際の混乱は、認知科学の視点から見ると「知識不足」「情報不足」「処理能力不足」の3つに分類できます。これらはそれぞれ「長期記憶」「短期記憶」「ワーキングメモリ」という脳の認知プロセスに対応しています。

コードを効率よく理解するためには、これらの認知プロセスの限界を認識し、適切な外部ツールやアプローチを活用することが重要です。優れたプログラマーになるためには、単にコードを書く技術だけでなく、脳の働きを理解し、効率的にコードを読み解く能力も必要なのです。