初学者の成長を助ける7つの習慣
前書き
目的
本記事では、プログラミング初学者の方々が効率良く成長するために有効な7つの習慣について記述します。「このツールを使いましょう」とか、「このショートカットキーを使いましょう」とか、そういった具体的な仕事術に関するノウハウではなく、あくまでも日々の習慣や意識について記述します。また、「アウトプットをしましょう」とか、「カンファレンスに参加しましょう」とか、そういった勉強法やモチベ術に関する習慣の話でもなく、あくまで日々の業務や勉強の中でディスプレイに向かい続ける中で、 どのような意識で日々のプログラミングを行うか にフォーカスした習慣について記述します。便宜上、「XXXX をしましょう」や「XXXX すべきです」のような記述をしていますが、本記事における内容は全て筆者の個人の意見です。
想定読者
業務や勉強において、自分のコードで何かを作り始めたプログラマーを想定しています。前述の通り、勉強の方法ではなく、日々の業務や勉強の中で実際にコードを書く際の習慣について記述します。
背景
成長を目指すにあたっての最強の戦術は有識者に聞き続けることです。私はいくつかの企業で後輩のプログラマーの教育を行い、個人事業でもプログラミング教育に関する仕事を行ってきましたが、「いつでも相談してね」とか「10分悩んだら聞くようにね」とかいった言葉をかけても、ほとんどの初学者の方は数日ほど経つと質問の回数が減っていき、成長の速度も低下していきます。「何度も時間を取らせて申し訳ない」とか、「何度も質問すると無能だと思われそうで怖い」とか、「自分で解決してみたい」とか、人に聞けなくなる原因は様々だと思いますが、とにかく会社の上司であろうが、お金を払っているメンターであろうが、多くの人々はそれを最大限に利用しようとはせず、どうしても無理な場合や納期上の問題がある場合でなければ、自分の力で問題解決しながら成長することを選択するようです。リモート教育が増え続けている昨今においては更に顕著な傾向ではないかと思います。本記事で紹介するのは、そんな自分の力で成長したいプログラマーにとって有効な習慣です。
7つの習慣
1. エディターに向き合う時間を増やす
これはプライベートもエディターを開いてプログラミングに向き合う時間を増やせという話ではありません。勿論、エディターのコンフィグと向き合う時間を増やせという話でもありません。普段のプログラミング業務やプログラミング勉強の時間の割合として、エディターを開いている時間を多く確保するように意識するということです。成長が止まっている多く初学者の方々に共通しているのは、プログラミング業務時間内においてエディターを開いている時間が極端に少ないということです。成長が止まっている方の多くは、調べ物をしている時間が長すぎるのです。そもそもエディターでプロジェクトを開く前にググることから始めている人も多いです。実装したい要件に対する直球な解決法を求めて多くの時間を使ってしまうのは避けましょう。漠然とした検索ワードによりコピペで動く魔法のような解決法を探すよりも、息詰まるまでは自分のコードで実装してみましょう。
業務や勉強の内容にもよりますが、まずは目安として75%以上の時間をエディターと向き合うように意識してみてください。例えばあなたの業務時間からコミュニケーションやドキュメント作成やミーティング等の時間を除いたプログラミング業務時間が4時間である場合、3時間はエディター(あるいはターミナル)に向かうように意識してみましょう。実装の要件に対して初手検索を選択するのも悪くはありませんが、魔法の解決法が見つかりそうになければ、早々に切り上げてエディターに向かいましょう。「いや、初学者の引き出しじゃ調べんと分からんよ」という声が聞こえてきますが、以降の習慣がその声に対する答えになります。
2. 日本語で実装する
私が初学者の方とペアプログラミングをする時によくやってもらっているのは、日本語の擬似コードから実装することです。具体的にどんなコードを書くのかは見て頂いた方が早いでしょう。ここでは FizzBuzz 問題という、1からnまでの数字を順に出力する中で、3の倍数なら "Fizz"、5の倍数なら "Buzz"、3と5の公倍数なら "FizzBuzz" と出力するプログラムを書くケースを想定します。
for ループ {
if 3と5の公倍数なら {
"FizzBuzz"と出力
}
else if 3の倍数なら {
"Fizz"と出力
}
else if 5の倍数なら {
"Buzz"と出力
}
else {
数字を出力
}
}
プログラミング言語と日本語が入り混じった中途半端なコードになりましたが、まずはこのように「ループには for
を使う」とか、「条件分岐には if
や else if
を使う」とか、そういった確かな知識だけをプログラミング言語として記述し、その他は全て日本語で記述します。if
すら忘れてしまったならば「もし」と書けば良いのです。このようなコードを書くことで、for (int i = 1; i <= 100; i ++)
のような初学者には暗号あるいはお決まりごとに見えてしまう覚え辛い構文や、倍数であるかを判定するには i % 3 == 0
のように剰余演算子を用いることや、公倍数であるかを判定するためには (i % 3 == 0) && (i % 5 == 0)
のように論理積演算子を用いること等、本来完成形のプログラムで考慮すべきプログラミング特有の問題の多くを排除し、要件とアルゴリズムについてだけ集中することができます。 ここまで書ければ残りを埋めていくだけなので、検索の仕方も漠然としたものにはなりませんし、「やりたいこと」が目の前に常に具体的に存在する状態でプログラミングを進めていくことができます。
多くの実装要件において、漠然としたワードで検索してアルゴリズムまで丸ごと答えが返ってくることは少ないです。今回の例では「C言語 FizzBuzz」でググれば一発で答えは返ってきますが、実際のプロダクトや業務特有の問題であれば難しくなってくるでしょう。対して、アルゴリズム内の各箇所にて行う作用に関しては簡単に答えが見つかることが多いです。「C言語 for」と「C言語 倍数」といった具体的な作用に対する検索を繰り返して擬似コードを埋めていくことは比較的容易であるはずです。この時点で問題は細分化されているのです。 まずは日本語でも良いので、要件をアルゴリズムで明確にすることから挑戦してみましょう。
3. まず手持ちのカードで実装する
プログラミングに関する実務教育においてヒントを与える時、「あなたの手持ちの技術で解決できますよ」と言うことは多いです。実際、プログラミング業務における大半の実装は初学者の方でも手持ちのカードで勝負できるものです。初学者の方が陥りがちな思考として「この問題は手持ちのカードでは解決できないのでは...?」というものがあります。経験を積んでいくうちに「こういう時はこのカードを切れば良い」という感性が備わってくるものですが、経験が浅いうちは手元に解決のためのカードがあっても何故か目に入らないことが多いです。何かしら自分の知らない魔法の手段が存在していて、上級者にしか解けない問題だと思い込んでしまうのです。
例えば、フライパンを知らなければ「パンはパンでも...」のなぞなぞは解けません。クイズにおいて「そもそも俺はこの答えを知ってるんか...?」ということが頭によぎると、解く気力や思考力が著しく落ちます。しかし、プログラミングにおいてはクイズと違って「そもそも答えを知らない」という問題は滅多に出ません。初学者に与えられた課題や業務であれば特にその傾向は強いと思います。プログラミング業務の大半は、順次・分岐・反復の基本や、論理演算子の使い方や、関数の作り方、その言語やフレームワーク等の基礎的な扱い方を知っていれば解決できるものです。そして、物作りを始めるに至った初学者の方々の多くはそれを有しているでしょう。
まずはどんなにダサいコードになっても良いので、漠然としたワードによる検索を始めてしまう前に、手持ちの知識でコードを書き上げられないか挑戦してみましょう。ライブラリの使い方であれば、そのライブラリを使って自分が求めるユースケースと似たことを実現した人の記事をいきなり探しに行くのではなく、まずは公式の最新のドキュメントを翻訳ツールを使っても良いのでちゃんと読みましょう。ここまでの3つの習慣に共通して言えるのは、漠然とした要件を検索によってまとめて解決しようとするのではなく、自分の言葉と、自分の手持ちの技術を使ってエディターと向き合えば、問題は細分化されてトレーニングにもなる ということです。エディターに向かい、日本語を使ってアルゴリズムを明確にして問題を細分化し、自分の手持ちのカードで実装を仕上げる、といった習慣を身に付ければ、プログラミングの基礎能力は上がっていきますし、結果として検索する技術も身に付いてきます。自分で考えて自分で実装してみる経験を繰り返すことが、あなたの技術を高めるのです。
4. 最小の検証環境を作る
ここまでは関数やメソッド単体の実装や、簡易的なワンショットのスクリプトの実装、独立した機能の実装等を想定してきましたが、実際の業務では既存のプロジェクトの規模が大きく複雑化しており、自分の書いたコードが意図した通りの挙動にならない時に、自分のコードが悪いのか既存のコードと干渉しているのか判別が付き辛いことがあります。そういった場合に、初学者の方々に挑戦してみてほしいのは、最小の検証環境を作るということです。例えば HTML, CSS, JavaScript 周りの問題なのであれば、最小の index.html を作ってブラウザーで開いてコードを付け足していくことで、今取り組みたい問題だけに特化した検証環境を作ると良いでしょう。
<!DOCTYPE html>
<html>
<head>
</head>
<body>
</body>
</html>
Ruby on Rails であれば rails new
、Next.js であれば yarn create next-app
等、その環境のまっさらなプロジェクトを作って、必要なライブラリだけを導入して他から干渉されない限りなく純粋な環境で自分のコードを検証できるフットワークの軽さはプログラマーにとって非常に重要な素質です。 既存のプロジェクト上で複雑なまま格闘するのではなく、最小の構成でまず確実に動くシンプルなプロジェクトが手元にある状態で、既存のプロジェクトと比較しながら問題解決に取り組むとすんなり解決することは多いです。「rails new
の数だけ人は成長する」という有名な言葉がありますが(嘘です)、使い捨てしてきたプロジェクトの数だけプログラマーは強くなれます。 検証した最小のプロジェクトは GitHub に push しておけば、そのうち役に立つかもしれません。一見遠回りで面倒な作業ですが、慣れてくると rails new
して目的の Gem を Gemfile に追加して使い方の検証をするぐらいなら5分も経たずにできるようになります。最小の検証環境をパパッと作成することに慣れておきましょう。
5. テストを書く
私は初学者ほどテストを書くべきだと思っています。テストの効用について語り出すと止まらなくなるので、ここでは語弊を恐れずに乱暴に言いますが、テスト書くと生産性が上がって最強になれます(嘘です)。業界で有名なあの人は書いてます、あの人も書いてます。まあ、書かないよりは書いた方が基本的に良いことは言うまでもありませんが、テストを書かない中級者以上のプログラマーは意外と多いのです。テストを書かない理由の多くは「(早く)書けないから」です。書かないと一生書けないので一生テストの恩恵を受けることができません。テストを書けない人を採用しない職場も多いです。それは大変勿体ないので初学者のうちからテストコード(っぽいもの)を書く習慣を付けておきましょう。
テストの作法がどうとか、context
による構造がどうとか、有効なマッチャーを提供するライブラリがどうとか、そういうのは全部どうでもいいので、「入力に対して期待する出力を定義する」というコードを書く習慣を身に付けましょう。最初のうちはメソッドに対する単体テストだけで充分です。rspec であれば eq
マッチャーだけ書ければ充分です。正常系だけでも充分です。閾値チェックも必要ありません。例えば入力値を2倍して返す my_method
があるならこれだけで充分です。
it { expect(my_method(1)).to eq 2 }
it { expect(my_method(2)).to eq 4 }
何ならテストフレームワークも使わなくて良いです。テストを消すのはもったいないですが、最初のうちはコードに直接書いて後から消しても良いでしょう。とにかく自分のコードをコードを用いてテストする習慣が身に付けば何でも良いです。
raise unless my_method(1) == 2
raise unless my_method(2) == 4
ブレイクポイントを付けて対話式でコードを実行できる環境があるなら、最悪それでも良いでしょう。JavaScript であれば開発ツールのコンソール等から実行しても良いでしょう。ただし、このようにメソッドの戻り値を目視チェックするのではなく、
[1] pry(main)> my_method(1)
=> 2
[2] pry(main)> my_method(2)
=> 4
このように期待する戻り値を明示的に自分で書いて結果をチェックするようにすることをお勧めします。
[1] pry(main)> my_method(1) == 2
=> true
[2] pry(main)> my_method(2) == 4
=> true
これだけでも、「ブラウザー上で動いているっぽいからこのメソッドも正しく動いているんだろう」という曖昧な雰囲気テストからは脱却することができます。最初は書きやすいものだけで良いので、どこかで自分の作った関数やメソッドを使い捨てのコードでテストすることを意識して、慣れてきたらその技術で最も普及しているテストフレームワークの最も基礎的な機能だけを使った簡易的なテストをプロジェクトに残すように意識して、それも慣れてきたらリストを返したりデータベース変更等の副作用があったりするメソッドにもテストを書くようにステップアップしていくと良いでしょう。「書けそうならちょっと時間を割いて書いてみる」といった取り組みを続けていくと、そのうち書くコードもテストしやすい良いコードになり、テストコードによる品質保証やドキュメント化が期待でき、生産性の向上も期待でき、テストを書けないプログラマーとの差が広がっていきます。「書けそうなら書いてみる」 の一歩を踏み出すだけで、今後テストスキルの経験値が少しずつ貯まっていくようになります。一歩も踏み出さなければテストスキルのレベルは1のままです。少しずつでも始めていきましょう。
6. 命名とコメントを重視する
プログラミングで一番大事なのは命名です。名前が良ければコードが読みやすくなるのは勿論、名前で嘘を付かないコードを書いていれば自然とコードの中身が良くなっていきます。最初のうちは、名前で嘘を付かない ということを最重視しましょう。例えば、最近私がコードレビューで変更を要求したのは Ruby on Rails の以下のようなコードです。
def set_user
@user = User.find(params[:id])
@profile = @user.profile
end
Controller で URL のクエリパラメーターから User
のインスタンスを引っ張って @user
というインスタンス変数にセットし、恐らくプロフィールに @user.profile
と毎回アクセスするのは冗長だと思って @profile
というインスタンス変数にも @user.profile
をセットしたのだと想像できます。ただ、これではメソッド名が嘘になってしまいます。set_user
という名前で @profile
というインスタンス変数の状態が変わるのは想像しにくいです。もし、@profile
にもセットしたいのであれば、このメソッドの名前は set_user_and_profile
にするか、別途 set_profile
メソッドを作った方が良いでしょう。まあこの例は大した副作用ではないので言うほど問題はありませんが、普段から「名前で嘘を付かない」という鉄の意志を持っておくことは重要です。
ここまでは意識1つで多くの初学者さんが改善できることですが、実際のプログラミングでは命名に妥協することがほとんどです。単純に命名が思い浮かばなかったり、英語に変換できない日本特有の概念を英語で命名する必要があったり、直訳すると何十文字にもなるほど長い名前になってしまったり等です。そういった場合に、仮の名前を付けるなり、ローマ字で命名するなり、略語を作るなりして「気持ち悪いなぁ...」と思いながら妥協するものですが、この時にコメントをする習慣を持ちましょう。基本的に私は、コメントに書いてあることは正しいかどうかテストコードで検証できないので特別な理由がなければ書かない派閥の人間ですが、命名に妥協するのは「特別な理由」だと捉えています。仮の名前を付けたのであれば TODO コメントを残しておかないと一生そのままになるかもしれません。略語を作成したら次にプロジェクトに入ってきた人が混乱するかもしれません。
# TODO: 仮の名前。
def process
# 名前を付け難い複雑難解な処理
end
# 「スーパーサイヤ人ゴッドスーパーサイヤ人」の略
t.boolean ssjgssj, default: false, null: false
命名の妥協の補助コメントはダサく見えてしまうかもしれませんが、このダサさが未来の自分も未来のプロジェクトメンバーも救います。まずは名前で嘘を付かないことを最優先に、そして名前に妥協した場合はコメントを打つことを意識しましょう。
7. 基礎より実践を重視する
最近は業務中の勉強が認められている企業も増えているように感じますが、業務のレベルについていけないと感じ始めた初学者の方がよくハマる罠に、「基礎を体系的に学び始める」というものがあります。ソフトウェア開発の世界は果てしないので、自分の技術力が上がれば上がるほど自分の技術力が低く見えてきてしまうものです。自分が普段メンテナンスしているプロダクトのほとんどを正確に理解できていないことに焦りを感じてきます。そこで「このままじゃダメだ」と感じる熱心な初学者さんほど、基礎を体系的に学び始める傾向にあると感じています。しかし、これは逃げです。実務が高度になればなるほど、「自分には基礎が足りていない」と感じるもので、それはある意味で事実だと思いますが、多くの場合その道を選択した方の成長スピードは止まってしまう傾向にあります。特にプログラミング言語やフレームワークの基礎を体系的に学ぼうとすると「今さほど重要でない知識」の習得にリソースを割いてしまうことが多いです。HTML の基礎から始めようとして全てのタグを覚えようとしたり、そのプログラミング言語の組み込み関数を全て覚えようとしたり、書籍を買ってきて一語一句全てに目を通しながら写経をしたり等、実際の業務中に得られる経験値に対して圧倒的に効率の悪い勉強法を選んでしまい、更に成長を停滞させてしまう結果を招く様子を私は何度も見てきました。
こういった勉強法の全てが悪だとは言いませんが、「業務のレベルに追い付きたい」というモチベーションで学習するのであれば、業務で使っているプロダクトを使って勉強するか、実プロダクトに似た簡易プロジェクトを自分の手で作ってみる等といった、業務に直結する勉強をした方が多くの場合は効果的です。 私も体系的学習厨なので気持ちはよくわかります。しかし、まだ業務で実際に動いているプロダクトを目にできない未経験の初学者さんにとって喉から手が出るほど欲しい「実際に動いているプロダクト」が目の前にあることは大きなアドバンテージなのです。業務クリティカルな勉強は業務で触るプロダクトをベースに行うのが一番です。テストコードを足してみたり、リファクタリングしてみたり、ローカル環境で意図的にぶっ壊してみたりといった実際にエディターの前で行える実践的で業務クリティカルな勉強法を試してみてください。
後書き
冒頭にも書きましたが、本記事における内容は全て筆者の個人の意見です。ただ、本記事に書いたことは教育に関する仕事を続けてきた上で、初学者の成長に大きく貢献すると感じている習慣です。某自己啓発書に合わせて無理矢理7つを捻り出したわけではなく、全ての習慣が非常に効果的だと感じています。長らく就職難が続いており、就職できてもリモートでしか教育を受けられない悩みを持つ方も多く、成長速度について焦りやすい環境になってしまっていると感じたのでこの記事を書きました。多くの初学者の方々の成長に本記事が貢献できることを祈ります。
Discussion
これに関してはホントにホントに大賛成です。
フロントエンドのプログラマであればjsfiddleなどのサービスを使ってサクッと検証できますね。