はじめに
おすすめしてもらい、『プログラマー脳 ~優れたプログラマーになるための認知科学に基づくアプローチ』を読んだ。試してみたいと思ったこと、記憶に残ったことを残しておきたい。
記憶に残ったこと
コーディング中の混乱
コーディング中の混乱は、知識不足・アクセス可能な情報不足・脳の処理能力不足、から起きる。
経験豊富なプログラマーのコードの読み方
経験豊富なプログラマーはコードを「チャンク化」して読む。短期記憶に記憶できるものは5個くらいだが、まとまりで記憶することで、より多くのものを処理できるようになる。チャンク化を意識して読むといい。
チャンク化しやすくするには、
- デザインパターンに基づいたコードを書く
- コメントを書く
- ビーコンを残す。ビーコンはコードの内容を理解するのに役立つプログラムの部分のこと。パターンにあてはまる構造やロジック、変数名、クラス名など。
文法は記憶した方がいいのか?
文法を覚えていると、チャンク化しやすくなり情報処理量が増える。割り込み(文法を調べる)が減り効率アップする。
感想:調べたらわかるし、何回か調べたら覚えるだろうと思っていたが、意識的に記憶しなければいけないのだとわかってよかった。
コードを読む時にワーキングメモリにかかる負荷
- コードのどの部分を読むべきかわかっていない
- コードの行の理解と構造理解&読む部分を決めるを同時に行う
学習の転移
- 長期記憶に蓄えられている知識は新しい状況に転移できる
- 習熟度・類似度・コンテキスト・重要な性質に関する知識(共通点に注目するといい)・関連性(どのくらい類似してるか)・感情
- ただし、負の転移(過去に学習した記憶が邪魔をする)場合もある
- pythonが動的型づけ言語とわかっても、Javaの慣習をアンラーニングするのは難しい(本当にそう思う)
- 誤認識を防ぐ方法として、よくある誤認識に陥らないように注意する、ペアプロ、自動テスト、他の人も陥らないようにドキュメントを追加する、などがあるとのこと
自動化
- より大きな問題を特には、プログラミングスキルの自動化(考えずにできるようにする)が必要
- ワーキングメモリがいっぱいになってしまうと、適切な思考も、情報を長期記憶に戻して保存することもできなくなってしまう。
- 自動化するには、習得したいスキルを利用した小さいプログラムをたくさん書くなどが有効。
マルチタスクはだめか
- 自動化されていないタスクは同時にはできない
オンボーディング
- 新人にたくさんの新しい情報を一度に投げつけてしまうと、新人の脳に高い認知的負荷がかかってしまう。(すごくやってしまう。)
- 新人は関連する長期記憶をワーキングメモリを取り出して利用できないし、効率的チャンク化もできないので、熟練者とは全く違う考え方をすることになる
- 発達段階で、論理的で一貫性のある体系的な推論ができるようになる前に、一貫していない推論や一部のコードから推論してしまう段階がありフラストレーションが溜まるが、次の段階に向けて必要。
試したいこと
文法やコマンドをフラッシュカードで記憶する、意識的に覚えようとする
今どきは、NotebookLMに読み込ませるとテストやフラッシュカードを作ってくれるので、業務で使ったコマンドや文法をメモしておき、テストやフラッシュカードを生成して、覚えたい。また、覚えようという気持ちだけでも効果があるようなので、調べた時に意識的に覚えようとしたい。
記憶検索の練習
調べる前に情報をまず頭のなかで思い出そうとするだけでも効果があるとのこと。
認知的負荷軽減テクニック
- 認知的リファクタリング
- その時の自分によって読みやすいコードにする。メソッド順を入れ替えたり、メソッドをインライン化する。理解したら戻してもいい。
- 使い慣れない言語構造の置き換え
- ラムダ式など慣れていないと余計な認知負荷がかかるとのこと。手で書き換えれば書き換える過程で理解も深まりそう。
- 構造の理解
- メソッドに丸をつける方法が紹介されていたが、AIに最初に呼び出し階層やメソッド・変数の出現箇所を書いてもらうだけでもよさそう。
変数
- その変数がどういう役割なのかを考えて読む
コードの要約
- このコードが達成したい目的は何か
- 最も重要な行はどれか
- 最も関係深いビジネス領域は何か
- 最も関係深いビジネス構造は何か
- コード作者の下した決定は何か
無視する部分を意識する
ある程度抽象化できると読みやすくなる。ただ、抽象化しすぎると混乱を招くこともあるので注意。
よくある誤認識チェックリスト
よくある誤認識を認識しておくとよいとのこと。
JavaとPHPのよくある誤認識(違う点)や、共通点のリストをChatGPTに出してもらいたい。
以下はJava経験者がPHPを学ぶ際によくある誤認識を出してもらったもの(コピペ用に簡潔にしてもらった。)。確かにこれを先に読んでおいたらだいぶよかったと思う。特にbooleanは 0
がfalse
になるのははまった。
型はJava並みに厳密(→ 実際は動的型付けで暗黙変換あり)
booleanの扱いが同じ(→ 0, "", null, [] も偽になる)
メソッドのオーバーロードができる(→ PHPは不可)
クラス宣言やファイル構成がJavaと同じ(→ ファイル名とクラス名は無関係)
パッケージ体系やimportがJavaと同じ(→ PHPは名前空間のみ)
例外処理がJavaと同じ(→ PHPはエラー/警告も混在)
main関数が必要(→ PHPは先頭から逐次実行)
オブジェクトはGCで管理(→ 参照カウント方式でリクエストごとにリセット)
配列は固定長(→ PHPの配列は連想配列)
文字列結合は +(→ PHPは .)
標準ライブラリは全てOOP(→ 多数のグローバル関数あり)
Webサーバ常駐プロセスで動作(→ リクエストごとに実行され終了)
スレッドや並列処理が標準で使える(→ 基本シングルスレッド)
命名
- 問題解決と命名を一緒にするのは、ワーキングメモリに負荷がかかりすぎる。後から命名を考えるのも良い。
- 既存コードから一貫したルールの新しい変数名を作るのもよい。(Cursorにやってもらったらよさそう)
- 適切なビジネス領域の概念を利用できると長期記憶を呼び出しやすい。(これがドメイン駆動設計か)
- より良い命名の3ステップ
- 名前に含めるべき概念を選択
- 各概念を表す単号を選ぶ
- その単語を使い命名する
- コードベース全体での整合性、自然言語としても自然な語順、前置詞を追加するなどを意識するとわかりやすくなりやすい
- 略すかどうかは、覚えやすいと理解しやすいのバランス
コードの臭い
- ファウラーが定義したコードの臭い→コードが読みづらい→認知負荷がかかりすぎる
- AIにコードスメルに該当するものがないかレビューしてもらえばいいのだろうか?
コードを読んだ理由も残しておく
- コードを読んだ時に、なぜそのメソッドを読んだのかもコメント書いておくとよい。中断した時に特に役立つ。
- 例:〜から呼ばれているから
割り込みから回復する
- 上記のようにコードにコメントなどを残しておく
- 未来に関する記憶を補助するものを使う(TODOやリマインダー)
- 問題を小さなステップに分割し、それをテキストとして記憶する
感想:最近xbarでMacのメニューバーにその時やっていることを表示するようにしたのだが、これは上記の2つを満たしていて、結構良い対策だったのだなと思った。詳しくは以下のブログに書きました。
オンボーディング
- 初心者の理解プロセス(意味波)
- 抽象 → 具体 → 抽象 の流れで学ぶのがいい
- 抽象だけわかっていても実際どういうものかわからないし、具体だけ知ってもどういう概念か・なぜ便利かがわからない。異なる文脈に適用するためには最後にもう一度抽象化することが必要。
- 抽象 → 具体 → 抽象 の流れで学ぶのがいい
- オンボーディング対象の人の認知的負荷を正しく管理する
- タスクにおけるプログラミング活動を一つずつやってもらう
- 探索・検索・転写・理解・増強のいずれか一つにする。または開発タスクをそのように区切る。
- 例:理解(ドキュメント作成)だけ
- 探索・検索・転写・理解・増強のいずれか一つにする。または開発タスクをそのように区切る。
- コードを一緒に読む
- タスクにおけるプログラミング活動を一つずつやってもらう
感想
あとがきがとてもよかった。
認知について知る前は、複雑な論文を読んだり、見慣れないコードを探索したりするときに、自分の頭がよくないことに腹を立てていました。今は「認知的負荷が高すぎたのかもしれないね」と、自分にもっと優しくなることができます。
今の会社に入社したばかりの頃、とにかく普通のことも何もできなくなり、自分のことを全く信じられない状態になった。(今もまだ回復しきれていないが。)会議を忘れたり、slackで誤ったURLを送りまくったり、技術力も足りないのにそれ以前の問題ではないかと、自分はこんな人間だっただろうかと本当に落ち込んだ。しかし、この本を読んで、認知的負荷が高い状態になっていたのだなと思った。ツールもプログラミング言語も未経験のものばかりで、PCも仕事では使ったことがなかったMacになり、全部調べながらやっていたので、それは認知負荷が高かっただろう。