私は、この数年で、プログラミングスクールの講師や実際の現場でコードを書くなどのエンジニア関係の仕事の比重が高まり、プログラミング学習について考えることが多くなってきました。(それ以前の経験についてはWebサイト制作の個人史とWebサイト制作の個人史2をご参照ください。)
仕事での実践とともに、趣味的に雑多なコードを書いたり学習をしたりしつつ、コーディング原則本なども読み漁りました。
そこで考えたことをこの記事にまとめます。本記事の末尾に掲げた10冊の本の内容を極度に圧縮した記事だと言えます。
私はエンジニアとしての経験が決して豊富ではありませんが、様々な分野での学びと教える経験は豊富なので、これからプログラミング学習を始めようとしている人だけでなく、経験豊富なエンジニアに対しても新しい視点を提供できればと思って執筆しました。
1.プログラミングの特徴
天下り的な記述をさせてもらうなら、プログラミングの特徴は次の2点だと私は考えるに至りました。
(1) プログラムは製作物であるとともにドキュメントである→動作だけでなくわかりやすさも重要
(2) 結果の正しさを容易に観測できる→素早い変化や修正に開かれていることが重要
(1)は、車やテレビなどほとんどすべての製作物はドキュメント(設計図や説明書)とは別個なのだけれども、プログラムは製作物がドキュメントでもあるということです。ですので、求める動作をすることはもちろん、わかりやすさも重要になります。
(2)は、例えば宇宙物理学や心理学や政治学は、(装置や倫理などの理由から)仮説を立ててもその正しさを観測するのが極めて困難であるのに対し、プログラミングでは意図した動作をするかどうかという正しさを容易に観測できるということです。農業は収穫物という形で結果の正しさが目に見えやすいですが、結果を得るまでに数か月から年単位の時間がかかる場合が多いので、分単位や秒単位でPDCAサイクルを回すことのできるプログラミングほどには結果の正しさを観測するのが容易ではありません。この特徴は、プログラミングでは、作って、確かめて、変更して…というプロセスを何度も繰り返すということにつながります。
ChatGPTをはじめとした生成AIでプログラミング関係の精度が高く利用価値があるというのも、この点に関わっているのではないかと私はにらんでいます。生成されたコードが正しく動作すればそれでよいと言えるからです。政治学に関する質問をして生成された回答の正しさをすぐに確かめる術はないこととは対照的です。
2.コーディング共通原則のまとめ
いくつかの本に書かれていて、概ね受け容れられているであろうコーディングの共通原則を、上記の2つの特徴を軸にまとめることができます。以下では、その観点から、私が重要だと捉えているコーディングの共通原則を取り上げてコメントします。
なお、リファクタリングにつきましては、以下の共通原則に従うように適宜コードを見直すことであって、水準が異なりますから、独立した項目にはしませんでした。
わかりやすい名前をつける
これがコーディング原則の第一歩かなと思います。(予約語などの不適切な名前は当然除外するとして)変数や関数などにどのような名前をつけても同じように動作しますが、ドキュメントとしての読みやすさは全然違ってきます。わかりやすい名前をつけると、脳の認知負荷が顕著に減ります。
読みやすいコードを書いてコメントで補う
プログラミングコードは製作物であるとともにドキュメントでもありますから、コード本体が読みやすいのが理想です。読みやすいコードを書けない場合は、コメントで補うべきです。その手の本によく書かれていることですが、数か月後の自分は他人も同然であり、数か月後に変更や修正をすることもよくありますから、わかりやすいコードとコメントはとても大切です。
DRY、KISS、YAGNI
それぞれ、Don’t repeat yourself(繰り返しを避ける)、Keep it simple stupid(シンプルで愚鈍にする)、You ain’t gonna need it(それはきっと必要にならない)の頭文字を取った原則です。繰り返しがなければコードが読みやすくなるとともに変更も1箇所で済み、シンプルであればわかりやすくて機能の追加もやりやすく、プログラムは変更が容易なので先回りしすぎず必要になったときに機能を付け加えると割り切って考えやすいです。
3.議論のあるコーディング原則
以下では議論のあるコーディング原則を取り上げます。混乱を招く可能性があるので、自信のない人は読み飛ばしてください。
オブジェクト指向か関数型か
要はわかりやすいほうを採用すればよいのではないでしょうか。オブジェクト指向にすると、コードのわかりづらい部分を設計図に相当するクラスの部分に書いてインスタンス化して使う部分の記述が簡潔になります。大規模なライブラリはオブジェクト指向で設計されていることが多いので、それを使う際には必然的にオブジェクト指向の記述になります。私は、大規模な仕組みを一から作ることはまずないので、自分で定義する場合には関数型にします。
テスト駆動開発
テスト駆動開発も、効率が上がりわかりやすくなるなら採用すればよいですし、そうでなければ無理に採用する必要はないと考えます。テストは結果の正しさの観測をさらに容易にする仕組みだと捉えることができます。ですので、結果の正しさを観測して変更することを何度も繰り返すことが予想される場合にはテストを書いたほうが効率的ですし、何が正しい動作であるのかがテストによりわかりやすくなります。他方で、テストを書くにも労力がかかり、テストコード自体は読みづらいことも多く、そのデメリットを上回りメリットがなければテストを書かなくてもよいのではないかと私は考えます。
疎結合と密結合
疎結合がもてはやされる風潮がありますが、今後必要とされるであろう変化や修正に開かれていることが重要だということに行き着くと私は考えます。例えば、(WP REST APIを駆使して意識的に疎結合にしようとしなければ)WordPressは簡単に始められることの裏返しとして密結合になりやすいですが、それが問題になるかどうかは状況次第です。小さな団体の外部告知用ホームページなら今後機能面の変更が必要になる可能性は低いのでWordPressで問題ないことがほとんどでしょうけれども、いろいろな機能の追加が予定されているウェブアプリをWordPressで作ろうとすると将来的に苦労する姿が目に浮かびます。仮想化やクラウドについても同様で、変化が見込まれそれらを使ったほうが合理的なら使えばよいし、必要なさそうなら使わなければよいです。
そもそも、何が一つの結合かということにも議論の余地があります。単純化をするべきか過度の単純化を避けるべきかという問題も、結局のところ中庸と言いますか、適度なバランスということになるのかなと思います。
4.「わかりやすさ」と「正しさ」の深堀り
ここまでは「わかりやすさ」と「正しさ」を自明で一つに定まるものと想定してきました。しかし、前節の議論からも垣間見えますように、「わかりやすさ」と「正しさ」は自明でもなければ一つに定まるとも限りません。
「わかりやすさ」は人によって大きく異なります。これは私の学び教える経験から自信を持って言えることです。同じ説明をしても、とてもわかりやすいと感じる人もいれば、まったくわからないと感じる人もいます。その人の前提知識や好みによって大きく左右されます。
コードにコメントを書くときも、未来の自分に向けるなら自分にとって難しく感じたことのメモを書きますし、非エンジニア向けならそうと意識して書きますし、プログラミングスクールの受講生向けなら教育的配慮をしますし、野球の好きな人が読むなら野球のたとえを使います。
使用しているプログラミング言語やフレームワークの慣習に従うと、その慣習を共有している人にとってはわかりやすくなります。ですので、私は、LaravelやDjangoを使うときに、標準的な構成にして、そのビジネスドメイン固有のロジックはUseCasesとして別のディレクトリに切り出すようにしています(5年間 Laravel を使って辿り着いた,全然頑張らない「なんちゃってクリーンアーキテクチャ」という落としどころが提示しているこの方法がわかりやすさの絶妙のバランスを保っていると私は感じています)。
本記事における「正しさ」は「依頼主が求める動作」という意味ですが、これにしても自明で一つに定まるとは限りません。求める動作を事前に依頼主が正確に見極めていることのほうが珍しいです。「顧客が本当に必要だったもの」という標題の下にで示されるブランコの絵は有名ですよね。
顧客が本当に必要だったものから学ぶこと | Casley Deep Innovations株式会社 技術ブログ
ここまでの記述からお気づきの方も多いかと存じますが、私は圧倒的にアジャイル派です。結果の正しさを容易に観測できるというプログラミングの特徴を最大限に活かせるからです。金融や人命に関わるようなミッションクリティカルで大規模なプロジェクトではなく、ウェブや業務効率化などの小規模プロジェクトに従事してきたという背景もアジャイルを推す理由になっています。
5.プログラミング学習のコツ
正しさ=求める動作をはっきりさせる
この流れからプログラミング学習のコツを考えるなら、正しさ=求める動作をはっきりさせるところからスタートすべきです。
現状に不満がなければわざわざプログラミングを学ぶ必要はありませんし、ZoomやkintoneなどのSaaSで解決できるならそのほうが早いです。車輪の再発明をする必要はありませんからね。怠惰は美徳という言葉もあります。どれほど美しいコードも、その仕事が必要ではなくコードがいらないことには劣ります。
自分では特に作りたいものはないけれどもプログラミング関係の仕事ができるようになりたいということでしたら、将来の顧客の立場で何を作りたいか考えてください。
正しさ=求める動作がはっきりしてきて、そのためにプログラミングが必要だということになりましたら、臆せず取り組んでください。自分は専門家ではないからと遠慮しなくてもよいです。何らかの動作を求めるその領域では自分が専門家です。正しさを決めるのはエンジニアではなく依頼主です。自分が作りたいものがあってプログラミングを学ぶということで依頼主とエンジニアが同一人物なら、自分が作りたいものが作れればそれでよいのです。
プロトタイプを早く形にする
その際には、欲張りすぎず、最小の労力で最大の効果が得られる部分を早く形にすることを目指すとよいです。リーンスタートアップで言うところのMVP(Minimum Viable Product、実用最小限の製品)です。80-10-10の法則と80:20の法則に共通して、少しの労力で大部分の仕事は片付けられるという含意があるということもあります。
スモールステップで少しずつ進むのがコツです。入試問題でも小問に沿って進んでいくと大きな問題も解けるということに似ています。余談ですが、私が入試科目とプログラミングを問わず教える仕事をするときには、いかに小問を刻んでいくかということを大切にしています。適切に小問を刻んで区切ることができれば、それだけで解決することも多いです。
最初はとにかく動けばよいという感覚で試行錯誤することになりますが、動くことを確認できたらきれいなコードにリファクタリングするようにすると、実は近道になります。
私の個人的な経験の紹介
私自身の実例をいくつかお伝えします。
まず、2000年から2010年頃にかけて、ホームページ(ウェブサイト)を作りたいと思いました。正しさ=求める動作は、インターネット上で内容を見ることができるということです。現在なら各種SNSやWordPressを使うでしょうが、当時はHTMLとCSSを新たに学びました。
次に、動的なサイトを作りたくなって、Perlを学ぶとともに、開発環境としてLinux(Ubuntu)を使い始めました。Linuxを使うことには、比較的古いPCでも無料のOSで快適にウェブブラウズや文書作成をしたいという目的もありました。それまで使っていたWindowsからLinuxにいきなり全面的に切り替えるのは困難だったため、併用しながら少しずつ置き換えていきました。最初はLinuxの世界に圧倒されましたが、ウェブブラウズさえできればいいのだと目的をはっきりさせると、案外簡単にできました。当時よりも現在のほうが環境が整っていますし、Linuxに挑戦してみることをみなさまにもお勧めします。
それから、数学の教材を作るためにTeXを使い始めました。それまではWordのフィールドコードで数式を入力していたのですが、特に分数などを表示するのが面倒だったので、分数が登場する計算問題のプリントをTeXで作ることを当面の目標に据えました。最終的にはTeXとemathでグラフや図形も自由に描けるようになりました。
比較的最近のこととしては、Pythonで給与計算などの業務効率化をしました。これもExcel等でやっていた業務を少しずつPythonに置き換えていきました。
何をどのように学ぶかを計画する
正しさ=求める動作をはっきりさせたとしても、何をどのように学んでいくかは迷います。次々と新しい技術が登場することもあって全部を学ぶことは到底できませんが、古い技術にしがみついて非効率になるのも避けたいです。損得で考えるなら学習コストを固定費と見立てて損益分岐点を考えることになるでしょうが、将来的な投資という意味合いや好みや楽しさも考慮します。個人的には、LinuxやSQLあたりは長年の検証を経て安心感があるとともに陳腐化しにくいので将来を見据えた学習の投資をする価値があり、好みにも合致していて楽しいと感じます。
専門分野を持っている人がプログラミング学習をすることに意義がありますし、逆にエンジニアが特定のビジネス領域のことを知るのも同じように意義があります。この記事の最初のほうで述べたプログラミングの2つの特徴からそう言えます。わかりやすさも正しさも特定のビジネス領域の知識と大いに関係しますので。
人月の神話やブルックスの法則はコミュニケーションコストの大きさを示唆しています。自由な文章から判例を検索できる判例探索サービスを作りましたのように一人で全部完結させるとコミュニケーションコストはゼロです。
もっとも、一人でできることなどたかが知れているので、何らかの形での協力関係を築くことは必須です。フリーソフトウェアやOSSがそのための一つの形かもしれません。
具体的な学習法
何のために何を学ぶかをおよそ決めた後は実践あるのみです。定まったカリキュラムがあるわけではなく自分の実現したいことを中心に学ぶことになりますが、あまりにも断片的な事柄をインターネットで検索しても道に迷って時間を浪費しがちです。
そこで、どこかの時点で公式ドキュメントをざっと一通り読むことを私はお勧めします。わからないことがあっても深く気にせず、公式ドキュメントのどのあたりにどのような内容が書いてあったのかをだいたい把握しておくと、後が楽になります。私は、割と早い段階でLaravelの公式ドキュメントInstallation – Laravel 10.x – The PHP Framework For Web Artisansを一読したことが、そのときにはすっきり理解できなくても、後で大いに役立ったと感じております。
網羅的にまんべんなく学習するという意味では、資格試験を活用するのも吉です。資格試験は自分の知識に抜け落ちがないかの確認にもってこいです。日時を決めて受験を申し込むと勉強する気分が高まります。
本を読むことも、情報が古いかもしれないという欠点はありますが、安定的な知識を網羅できるという点で有効です。PCの画面にばかり向かっていると目が疲れるので、休憩を兼ねて本を読むこともできます。
もちろん、わからないことや気になったことをインターネットで調べることも日常的に行っています。日々新しい技術や概念が登場しますから、それを調べて学習できる生活の余裕があるということが一番大切かもしれません。
6.落ち穂拾い
UNIX哲学の一つに、設定やフィルタにテキストを用いるという原則があります。バイナリではなくテキストを扱うということは、わかりやすさの点から極めて重大な点です。
それに比べると、CUIかGUIかという点は、ケースバイケースかなと思います。テキストを扱うCUIのほうがわかりやすい場面もあれば、見た目で直感的に操作できるGUIのほうがわかりやすい場面もあります。一定の知識や技術のある人が繰り返し作業をするときはCUIが適しているとは言えそうです。
AWSの操作をするとして、慣れないうちはGUIで操作するのが簡単だけれども、慣れてきたらIaC(Infrastructure as Code)という点からもCUIベースに移行したほうがよいでしょう。
WordPressのブロックエディタは、従前の手法と比べるとGUI的な要素が強くなっており、わかりやすいと感じるかわかりにくいと感じるかは人それぞれでしょう。DRY原則に準拠していて素早い変化や修正に開かれていますから、フロントエンドから入った人がブロックエディタを極めるというのは一つの道なのかなと思います。
最後に大事なこととして、透明性が挙げられます。透明性はわかりやすさの前提条件ですし、透明性を高めて多様な観点から結果の正しさを観測することも頑健性につながります。
7.参考文献
本記事ではページ数を示して直接引用することはしませんでしたが、以下の文献で提示されていたアイデアを咀嚼して再構成しました。興味のある人はぜひ直接読んでみてください。
総合的なコーディング原則本
リーダブルコード : より良いコードを書くためのシンプルで実践的なテクニック 作 者: 出版社: オライリー・ジャパン 発売日: 2012年10月05日 |
コーディング原則本として真っ先に挙げられるのが『リーダブルコード』でしょう。おもしろい絵と具体例が豊富で読みやすいので、最初に読む本としてお勧めします。
プリンシプルオブプログラミング : 3年目までに身につけたい一生役立つ101の原理原則 作 者: 出版社: 秀和システム 発売日: 2016年06月08日 |
こちらの『プリンシプルオブプログラミング』も有名ですね。興味深い原則や法則を紹介してくれる本です。
プログラマが知るべき97のこと 作 者: 出版社: オライリー・ジャパン 発売日: 2011年03月04日 |
『プログラマが知るべき97のこと』は、いろいろな人の意見や考えが寄せ集められており、インターネット上で全文を無料で読めますから、気軽に読めます。
ルールズ・オブ・プログラミング : より良いコードを書くための21のルール 作 者: 出版社: オライリー・ジャパン 発売日: 2023年09月15日 |
『ルールズ・オブ・プログラミング』は新しめの本です。C++で書かれているゲームのコードが例に取られているので、読みやすいと感じる人もいれば読みにくいと感じる人もいるでしょう。
古典
人月の神話 作 者: 出版社: 丸善出版 発売日: 2017年08月16日 |
『人月の神話』は古典的な部類ですね。歴史的な読み物と思っていただいてもよいかもしれません。プロジェクトマネジメント寄りです。
UNIXという考え方 : その設計思想と哲学 作 者: 出版社: オーム社 発売日: 2001年07月30日 |
『UNIXという考え方』も古典的です。技術寄りです。
フリーソフトウェアと自由な社会 : Richard M.Stallmanエッセイ集 作 者: 出版社: アスキー 発売日: 2003年09月04日 |
『フリーソフトウェアと自由な社会』は、フリーソフトウェアやオープンソースを考える書です。
各論
リファクタリング : 既存のコードを安全に改善する 作 者: 出版社: オーム社 発売日: 2019年12月20日 |
『リファクタリング』というタイトルの通り、リファクタリングについて第一に読むべき本です。
テスト駆動開発 作 者: 出版社: オーム社 発売日: 2017年11月10日 |
『テスト駆動開発』という書名にもなっている概念が斬新です。
エリック・エヴァンスのドメイン駆動設計 : ソフトウェア開発の実践 : ソフトウェアの核心にある複雑さに立ち向かう 作 者: 出版社: 翔泳社 発売日: 2019年12月16日 |
『エリック・エヴァンスのドメイン駆動設計』はかなり読みにくいのですが、大事なことが書かれているような気がします。