本書を選んだ理由
日々、プログラムを組んでいるときに自分の頭の中がどういう働きをしているのか。という普段、特に疑問に思わないことだが、興味が湧いたのと、サブタイトルである「〜優れたプログラマーになるための認知的科学に基づくアプローチ」というテーマにも興味をそそられました。それで本書を直感的に選んでみました。また、浅はかではあるが、なぜか装丁が気になる感じだったのでそれも選定した小さな理由の1つでもあります。
プログラマー脳 ~優れたプログラマーになるための認知科学に基づくアプローチ
気になった点をピックアップして、自分の感想を述べていきます。
Part1 コードをよりよく読むために
chapter1 コーディング中の混乱を紐解く
・コーディング中の混乱は、知識不足、アクセス可能な情報の不足、脳の処理能力の不足の3つが存在する。
・認知プロセスは主に3つ。長期記憶、短期記憶、ワーキングメモリ。これらが互いに作用しあっている。
チーム開発でのコーディング中、特に慣れないリポジトリや経験が浅いプロジェクトのソースコードを見ると、圧倒されて混乱することは結構あります。エンジニア5年目ですが、知識不足による混乱が一番多いです。認知プロセスに関しては、まず目や耳で入ってきた情報をまず、短期記憶し、ワーキングメモリを作動させる。そして別方向から長期記憶より必要な情報を引っ張り出してワーキングメモリに対してプラスで情報を与える。このイメージが頭の中でできたのが心地良かった。
chapter2 コードを速読する
・長期記憶に十分な知識がない場合、短期記憶のリソースを使うので容量がすぐに足りなくなる。
・ソースコード上にコメントを書くべきかという点について、そもそもコードそのものがドキュメントであるように。という意見がある。その上で研究結果としてコメントを書くことで初心者や経験の浅いメンバーにはコードを理解するのにとても有用であった。
仕事ではつい、なるべく早く成果を上げないと。とスピード感を持って目の前のタスクや問題に向き合ってしまう癖がある。しかし、長期記憶がないのであれば、どうしても短期記憶のリソースだけで解決しようとして、より成果をあげられずに焦る。という悪循環を生んでしまっているときがあります。
コーディング中にコメントをそもそも書くのか、あるいは、書くときの粒度はどうしようかと結構悩むことがある。それでも、コメントがあるソースコードは個人的に読みやすいしチームで実装していく以上は他のメンバーがチームに参画した際、なるべく早くキャッチアップできる土台を作る店でコメントは大事だなと感じました。もちろんエラーが起こった際にコードを追う時にも役立つだろうし。
chapter3 プログラミング言語の文法を素早く習得する方法
・文法を覚え、暗記することはチャンク化が容易になるため大切。同じ文法を都度調べることは作業の妨げになる。
・記憶の衰えを防ぐのは定期的にその情報に触れ、想起することが大切。
・知識を最大限記憶するには時間がかかる。
コーディング中に関数やメソッドについてネットで検索したり生成AIを利用することは日々行なっている。そして前に検索したことがあるメソッドだと認識しながらもその都度検索していることが往々にしてある。体感的にも無駄な感じがどうしてもある。それもやはり、目の前の不具合やタスクを解決することばかりにフォーカスして、本当にその場で理解して覚えてやるぞ!!!という姿勢ではないからだと思う。つまり受け身。今後は自分の長期記憶へのストックやスキルアップのために検索した際は、多少時間がかかっても焦らずに能動的に理解するよう努めようと思う。長期的に見るとその方が利点は大きそう。また、別の書籍でも想起することの大切さは記載されていた。これからぼちぼち資格の対策を始めようと思うので、忘れないでいようと思う。
chapter4 複雑なコードの読み方
・ワーキングメモリは短期記憶と同様に、一度に2〜6個の事象を処理する能力しか備えておらず、その容量を認知的負荷と呼ぶ。
・リファクタリングは良いことだが、認知的負荷の観点だとその負荷の度合いは読み手の予備知識に依存する。
本書の例にあったが、三項演算子を私もよく使う。単純にシンプルな機能で視覚的にもコードの量も減る傾向にあるので使うことがある。ただ、他にも省略記法があるが使い方は気をつける必要があるなと感じた。省略記法だけでなく、コードの保守性を担保するためになるべくメソッドを機能ごとに分割し、責務を分けようと意識してコードを書くことがある。ただ、自分が書いた場合でも他人の場合でもメソッドが方々に飛びすぎていて読みにくく、処理に流れを掴むのが難しいパターンはある。もちろんサービスを運営する上で保守性は絶対高いに越したことはない。でも、チームで開発する上ではそれがすべてではなく、ときには1つのメソッドが肥大化しそうであってもそれまでの流れなどを考慮して、同じメソッド内で処理をそのまま書くことも必要なんだろうなと思った。まだまだコーディングのスキルや経験が十分でなくいので、その塩梅や調整は下手くそだが、意識していこうと思う。
Part2 コードについて考える
chapter5 コードの深い理解に到達する
・初心者と熟達者のコードの読み方は異なる。まずコードは自然言語に比べ、直線的に読まれないことがあり、初心者は熟達者よりも直線的に読む傾向がある。
これは経験から要領やスキルを身につけるしかないのかなと思う。
新聞やSNSの記事を読むときのようにパッと流し読みして文章全体の流れや言っていることをなんとなくでも把握するように、ソースコードも読めればいいがなかなか厳しいんじゃないかなと私は思います。
知識や経験がついてくるまで、じっくりコードを読む方がいいのではないかなと。
chapter6 プログラミングに関する問題をよりうまく解決するには
コーディング中に認知的負荷を下げ、ワーキングメモリをなるべく消費せず問題解決するために、vscodeなどのエディタを使う際に変数や関数の内容を箇条書きでもいいので別タブで展開してすぐに見比べられるようにするのはいいのではと思いました。(実際ここ1週間ほどやってみていますが、いい感じです。エディタ上でなんども上下にスクロールする頻度がだいぶ減りました。)
chapter7 誤認識: 思考に潜むバグ
長期記憶に蓄積される知識は新しい概念を学習する際に活用される。既知の知識が別の言語や領域で役立つことを転移という。
・ある言語に熟達したプログラマーは別の言語を学習する際に、戦略やチャンク、メンタルモデルをより多く持っているので習得が早く恩恵を受けやすくなる。
今最も触れている言語はPHPです。他にもいくつか触れているが他の言語の理解をより深めるために、PHPをより極める意識を持って深い理解を得たいと思う。
・先行学習。すなわち、すでに学習した知識が、新たなタスクを実行する際の学習に対して良い影響を与えることを世の転移と呼び、その逆を負の転移と呼ぶ。BASICのような特定のプログラミング言語は他言語と異なる部分が大きく、間違った思い込みを持つ可能性がある。
変数の初期化が必要か否かなどが言語によって違う、といった機会に触れるほど、たくさんのプログラミング言語で開発した経験がまだありません。ただ、今後のキャリアを考えると、ずっとPHPだけでいくことは考え辛い。そうなったときに間違った理解を頭に入れておくことをなるべく避けるために、あるプログラミング言語に対しての仕様や特徴を理解するのは大切なんだろうなと思う。
Part3 よりよいコードを書くために
chapter8 より良い命名を行う方法
・識別子(コードの中で命名したすべて)は重要。
新たなコードを読むときにその意味をなるべく早く理解するためにコメントが大事なように識別子もその要素の一つである。ビーコンとしても有用である。
現在、社内のあるシステムでスパゲッティコード状態でかつ、命名のルールがバラバラで非常に困っている。例に漏れず、その読み辛いソースコードは識別子名がとても曖昧模糊としていて、変数やメソッドの意図を汲み取るのがとても難しく分かりづらくなっている。今そのシステムのフレームワークの変更を含め、リファクタリングもしながら大きく内部を変更していく段階であるが、コーディングルールとして識別子の命名のルールをしっかり確立させようと思う。コメントも含め、ドキュメント化するくらいの意識でリファクタリングしていきたいと思う。
chapter9 汚いコードとそれによる認知的負荷を避けるための2つのフレームワーク
・コードの臭い(コードスメル)とは理想的な構造になっていないコードの部分であり、リファクタリングする必要がある。
・1つのメソッドやクラスが大きく長いものを神メソッド、神クラスと呼ぶ。そしてそれらはエラーを起こす可能性を上げる要因となるため開発者を悩ませるきっかけとなる。それらは、コーディングの初期にはその姿を見せないが、新しい機能やロジックが追加される事で徐々に神に近づいていく。
先ほども書いたけれど、今まさに社内で開発運用している顧客向けの管理システムのリファクタリングとデザインアップデートを行なっている。
PHPで書かれたソースコードなのだが、レガシーコードの山で、クラスの肥大化が半端ない機能になっているファイルがほぼ大半である。クラスやメソッドの持つ責務が複数になっているため、ある一つの箇所を修正すると別の思わぬ場所でエラーが発生したりと、なかなかなカオスな状態になっている。具体的にはクラスやメソッドの責務をなるべく小さくしたり、定数を1つのファイルにまとめて、流用するのではなく、クラスに対してのプライベートな定数や変数をセットしてあまり機能を外に逃がさないよう試みている。長期的に見てどうなるは現段階ではわからないけど、今よりよくなることは確実です。コーディングルールがないこともカオスになった原因の1つになっています。
chapter10 複雑な問題をより上手に解決するために
・同僚と共同作業をする。そうすることで互いのコードや1つのコードに対して解説し合い意見を交わせる。
・githubを探検する
私は10分ほど問題にぶち当たって解決できないときは他の人に意見を聞いて解決するようにしています。その代わり、結果的にわからなかったとしてもその10分だけは自分の過去の経験や考えられる解決方法を使って、集中して対応するようにしています。エンジニア5年目ですが徐々にその意識が強くなってきました。10分でわからないときやコードリーディング会を開いて他の方の解決方法を聞くと、とても勉強になることが多く、自分の糧になることが本当に多いなと感じます。また最近は特に、自分のチーム以外のコードレビューも見るようにしています。他の方のコードを見るのは自分の考えとのギャップを感じることが多いですがそのギャップが大事だなと思います。この部分はあの人のやり方の方がいいけど、ここは自分のやり方でいいな。とか。プラグラマーとして深みを持つためにも他の方の考えにもどんどん触れていきたいと思います。
Part4 コーディングにおける共同作業
chapter11 コードを書くという行為
プログラミング中の割り込みはコードのメンタルモデルを再構築するのに時間がかかるため、生産性を低下させる。人は認知的負荷の高い作業をマルチタスクできない。
チームのメンバーから私に相談が入ることや、その逆で私が他の誰かに割り込みすることがある。実際、自分が集中していてギアが入ってきたら、内心あとにして欲しいな...とは思う。でも相手の意思を無碍にしたくはないし極力、自分の作業を中断してでもサポートに回ることは1日に1回はある実感。でも、場合によっては一旦待ってもらう勇気を持つことも大事かなと思った。自分も、相手の時間をもらう場合は質問をより明確に考えてから質問したり、厳しければあとで大丈夫です。と言葉にしてはっきり伝えようと思った。そして現状、いつのまにかマルチタスクになることが多々あるので、その状態に気づいたらすぐにシングルタスクになるよう意識したい。
chapter12 より大きなシステムの設計と改善
chapter13 新しい開発者のオンボーディング
・熟達者はコードを抽象的に捉えることができる、参照せずに考える能力を有する。対して初心者は細部に注目して全体像を把握できない。
・オンボーディングの際は長期記憶、短期記憶、ワーキングメモリを補助する情報をあらかじめ与える。
熟達者と初心者のコードの捉えが抽象的なのか、細部に注目するのか、といった差が出るのは当たり前のことだなと私は思った。もっと言えば、熟達者であっても経験の浅いプロジェクトの場合は細かい部分までコードを読むことがあるから。もちろん、そのキャッチアップの早さや、抽象的に捉えられるまでの時間は初心者よりも早いはずだがそれもまた当たり前かなと。熟達者、初心者どちらも、しっかりと今持つスキルと業務知識を最大限使って、ちゃんとコードを読んで理解することが大切だと思います。
オンボーディングに関しては、私も同意です。
なるべく、対象の言語やプロジェクトに対して最初は、負荷をかけずに入りを楽にすることが先のことを考えてもいいと思います。
まとめ
タスクに向き合うとき、問題解決の仕方やソースコードの書き方をもっと意識しないといけない気持ちになりました。ソースコードのカオス化をなるべく避けるため、認知的負荷を下げるためのコメントを書く。メソッドやクラスの責務を大きくしすぎない。しかし、散らばりすぎることもまた問題が起きる可能性はあるのでそこは盲目的にそうするのではなく、状況を見て判断する。など、改善点が多くあるなと感じました。コメントを書くなどできることからコツコツ続けていこうと思います。そうすれば、徐々に良いプログラマーに近づけるのではないかという気にしてくれた書籍でした。
拙い文章ですが、読んでくださった方に感謝いたします。