はじめに
今回の講義では「初学者がコードを書くときのコツ」について皆さんと一緒に考えていきたいと思います。
以降書いていることは私個人の意見なので、これってどういうことですか?とか、私はこう思います!といった感じでどんどん質問や意見交換をして、双方向のやりとりを通してお互い理解が深まればいいなと思っています。
※以下、シンプルなじゃんけんアプリを例として講義を進行していきます!
#目次
1.コツその1 -「コードを書いて実装したいこと」を言語化する!-
2.コツその2 -エラー文を恐れない!-
3.コツその3 -コードの見た目をキレイにする!-
4.コツその4 -処理の流れを掴む!-
5.まとめ
#1. コツその1
「コードを書いて実装したいこと」を言語化する!
解説
実装したいことを細分化してひとつひとつの処理を言語化することはコードを書く上でめちゃくちゃ大事だと思います!
言語化のやり方としては、「○○を××する」、「△△が□□のときに※※する」のようにできる限りシンプルな一文で処理の内容を表現できるといいかなと思います。
私の場合ですがこの時点では処理の順番はあまり気にしません。まずは思いつく限り言語化しましょう。
演習
以下のようなじゃんけんアプリを作るとしたときの処理の言語化にチャレンジしよう!
#2. コツその2
エラー文を恐れない!
解説
エラー文は最善のアドバイスだと私は考えています。
基本英語ということもありエラー文を理解することは難しいと思ってしまいますが、ちゃんと紐解けば効率的にコーディングを進めることができます。
ではエラーに遭遇したとき、具体的にどうすればいいのか考えていきましょう。
まず大事なのはエラー文に何が書かれてあるのかを理解することです。
もしエラー文が複数行で現れた場合、そのエラーが何者なのかを書いている一文を特定することも大切です。
例えば以下のエラー文を見ていきます。
これは「comHand」という変数が二重定義されてしまってるよ!というエラーです。
ある程度コードが書ける方や英語が得意な方はこれを見ただけですぐどういうエラーか察しがつくかと思います。
もしエラー文を見ても何が起きているのかわからない場合はググりましょう。
エラーを解決するためにググるときのやり方は主に2つあると考えています。
- エラー文をコピペしてググる
- キーワードでググる
エラー文のコピペは文法エラーやスペルミスなどシンプルなエラーの場合は有効だと思いますが、複雑なエラーになると自分のケースに当てはまらないことがしばしばあります。その場合はキーワード検索をしましょう。
【ちなみに】
キーワード検索のコツは「具体と抽象のバランスを意識すること」です。
例えば初学者向けjQueryの本を探したいとします。
そのとき、「本」で検索してもjQueryの本が検索結果に出る確率はめちゃめちゃ低いですよね?
この場合は具体性が足りてないと言えます。
逆に「学校でプログラミングを学び始めて3ヶ月の私がjQueryをマスターするための本」で検索してもキーワードがごちゃごちゃしていて本当に知りたいことに辿りつきにくいです。
この場合は抽象性が足りていないですね。
じゃあどうすればいいのかというと、この例で言えば「jQuery 入門 本」とかで検索するといいのかなと思います。
何を知りたいのかという興味の対象は具体的に(「jQuery 本」)、どんな目的や場合かという自分の状況は抽象的に(「入門」)キーワードに落とし込むと大体うまくいきます。
演習
以下のようなエラーが発生しました。このエラーを解決しよう!
できた方はキーワード検索でもエラーを解決できるかチャレンジしてみよう!
Uncaught ReferenceError: $ is not defined
ソースコード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>サンプルコード</title>
</head>
<body>
<h1>じゃんけんアプリ</h1>
<p>あなたが出す手を選んでください</p>
<button id="gu-btn">グー</button>
<button id="choki-btn">チョキ</button>
<button id="pa-btn">パー</button>
<p id="comHand"></p>
<p id="result"></p>
<script>
let comHand;
let result;
$('#gu-btn').on('click', () => {
const randomNumber = Math.floor(Math.random() * 3);
switch (randomNumber) {
case 0:
comHand = 'グー';
result = 'あいこ';
break;
case 1:
comHand = 'チョキ';
result = '勝ち!'
break;
case 2:
comHand = 'パー';
result = '負け...';
break;
}
$('#comHand').text(`相手:${comHand}`);
$('#result').text(`結果:${result}`);
});
$('#choki-btn').on('click', () => {
const randomNumber = Math.floor(Math.random() * 3);
switch (randomNumber) {
case 0:
comHand = 'グー';
result = '負け...';
break;
case 1:
comHand = 'チョキ';
result = 'あいこ'
break;
case 2:
comHand = 'パー';
result = '勝ち!';
break;
}
$('#comHand').text(`相手:${comHand}`);
$('#result').text(`結果:${result}`);
});
$('#pa-btn').on('click', () => {
const randomNumber = Math.floor(Math.random() * 3);
switch (randomNumber) {
case 0:
comHand = 'グー';
result = '勝ち!';
break;
case 1:
comHand = 'チョキ';
result = '負け...'
break;
case 2:
comHand = 'パー';
result = 'あいこ';
break;
}
$('#comHand').text(`相手:${comHand}`);
$('#result').text(`結果:${result}`);
});
</script>
</body>
</html>
#3. コツその3
コードの見た目をキレイにする!
解説
コードを書く上ではどこにどんな処理を書いているのかをしっかり把握していることが大事です。
そのためにもコードのレイアウトを整えましょう。
ここでいう「レイアウトを整える」とは、一定のルールにしたがってコードを整理することを指します。
一定のルールは皆さん自身で決めていいと思いますが、例えば「子要素は親要素に対して1つインデントを設ける」とか「役割ごとに空行を設ける」、「いい感じに半角スペースを入れて見やすくする」などです。
タグのID名や変数名もめちゃめちゃ大事です。
例えば送信ボタンのIDをつけるとき、<button id="a">
としてしまっては後でこれを参照するとき「aってどんなタグだったっけ...?」となってしまいます。
この場合、<button id="submit">
などにすれば送信ボタンのIDであることが一発でわかるので可読性が爆上がりですね!
つまりパッと見てどこでどんな処理をしているか一目でわかるコードが書けると完璧です!
【ちなみに】
コードを書く上で重要な力は「技術力」とか「頭の良さ」とかではなく「注意力」だと私は考えています。
ちゃんとコードを書いたはずなのにエラーが出て、何時間も考えた挙句原因はただのスペルミスだった...といった経験皆さんあると思います。
このようなスペルミスとかカッコ・引用符の閉じ忘れなどのケアレスミス的なエラーはまったく生産性がないので極力減らすべきです。
そのためには「注意力(ケアレスミスを未然に防ぐための力)」を研ぎ澄ますことが本当に大事です。
注意力を最大限に発揮するためには上で書いたレイアウトを整えるとか、一回頭をリセットしてコード全体を俯瞰してみるといったことも大切ですが、私の中ではコツもいくつかあります。ちょっとだけ紹介します。
- 変数名はコピペする
- 関数を書く際はまず体裁を整える(カッコを書いたら必ず閉じカッコも書くなど)
- エディタの検索・置換機能を活用する
- エディタの拡張機能を取り入れる
- やりたいことを整理する
要はあらゆる工夫をして効率よく(手間を省いて)コードを書きましょうねということです!
演習
以下のソースコードを整えてみよう!
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>サンプルコード</title>
</head>
<body>
<h1>じゃんけんアプリ</h1><p>あなたが出す手を選んでください</p>
<button id="g">グー</button>
<button id="c">チョキ</button>
<button id="p">パー</button>
<p id="comHand"></p>
<p id="result"></p>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
let comHand;
let result;
$('#g').on('click', () => {
const randomNumber = Math.floor(Math.random() * 3);
switch (randomNumber) {
case 0:
comHand = 'グー';
result = 'あいこ';
break;
case 1:
comHand = 'チョキ';
result = '勝ち!'
break;
case 2:
comHand = 'パー';
result = '負け...';
break;
}
$('#comHand').text(`相手:${comHand}`);
$('#result').text(`結果:${result}`);
});
$('#c').on('click', function() {
const randomNumber = Math.floor(Math.random() * 3);
switch (randomNumber) {
case 0:
comHand = 'グー';
result = '負け...';
break;
case 1:
comHand = 'チョキ';
result = 'あいこ'
break;
case 2:
comHand = 'パー';
result = '勝ち!';
break;
}
$('#comHand').text(`相手:${comHand}`);
$('#result').text(`結果:${result}`);
});
$('#p').on('click', () => {
const randomNumber = Math.floor(Math.random() * 3);
if (randomNumber ===0){
comHand = 'グー';
result = '勝ち!';
} else if (randomNumber=== 1) {
comHand = 'チョキ';
result = '負け...';
} else if (randomNumber===2){
comHand = 'パー';
result = 'あいこ';
}
$('#comHand').text(`相手:${comHand}`);
$('#result').text(`結果:${result}`);
});
</script>
</body>
</html>
#4. コツその4
処理の流れを掴む!
解説
コードを書くときのあるあるつみポイントとして、処理をどこにどの順番で書けばいいのか問題があると思います。
言い換えれば「コツその1『コードを書いて実装したいこと』を言語化する」で洗い出した様々な処理をどう組み立てるべきか?でしょうか。
まず前提としてプログラムは上から順番に実行されます。
なのでメイン処理の中で使いたい変数や関数があるならメイン処理の前に定義しておかなければなりません。
例として足し算の結果をコンソールに出力するプログラムを考えましょう。
以下のコードは正しい例です。
function sum(a, b) { // 引数aとbを足し算する関数sumを定義
return a + b
}
console.log(sum(1, 2)); // 関数を呼び出し処理を実行
一方、以下のコードはエラーとなります。
console.log(sum(1, 2)); // 関数を呼び出し処理を実行
function sum(a, b) { // 引数aとbを足し算する関数sumを定義
return a + b
}
理由はシンプルで、わたしたちが定義したオリジナルの関数を使う場合はいきなり関数を呼び出そうとすると「お前誰やねん!」となりエラーが出るからです。ちゃんと挨拶してから仕事してくださいということですね。
このように上から順番に自然な流れで定義や処理を配置することが原則なのですが...
それはあくまでこれらの定義や処理が時系列的に同列の場合のみ成立します。
理論上同時に(並列に)実行される定義や処理に対して通用する原則なのです。
逆に言えば、時系列的なズレは上から順番に実行するという原則より優先されます。
具体例を見ていきましょう。
function sum(a, b) { // 関数の定義
return a + b
}
$('#submit').on('click', function() {
console.log(sum(1, 2)); // 関数の呼び出し
});
これは定義→呼び出しという順番で関数を取り扱っているためちゃんと動作します。
では以下のプログラムはどうでしょう?
$('#submit').on('click', function() {
console.log(sum(1, 2)); // 関数の呼び出し
});
function sum(a, b) { // 関数の定義
return a + b
}
関数の定義よりも関数の呼び出しの方が上に書かれていますよね?
これだと一見エラーになるんじゃないかと思うのですが、実はこれでもうまく動きます。
なぜなら、この例における関数の定義と実行は時系列的に同列ではないからです。
もう少し詳しく見ていきます。
htmlのscriptタグの直下に書いた処理は、scriptタグが解析された直後に実行されるという決まりがあります。
なのでidがsubmitであるDOMをクリックしたとき〜の処理と、sumっていう関数を定義しますよ〜の処理が実行されます。
ここでよく考えていただきたいのですが、○○したとき〜のような処理(イベントハンドラ)は当然○○しないとその中身が実行されないですよね?
つまり関数を呼び出しているconsole.log(sum(1, 2));
という処理はscriptタグが解析された直後に実行されるのではなくidがsubmitであるDOMをクリックしたときに実行されるということです。この違いを理解することが大事です。
とはいえわざわざ「イベントハンドラ内で関数呼び出し→関数の定義」の順番で書かなきゃいけないという決まりはないので、まずは「定義→呼び出し」など「この順番で処理が実行されるのが自然な流れだよね」というイメージを掴んで、あとはその通りに書いていくのがいいと思います。
【ちなみに】
処理が実行されるタイミング問題は突き詰めるとかなり奥が深いです。
なぜならasync, awaitなどの非同期処理と呼ばれるものが大きな壁として現れるからです。
これらが初めて出てきたのはajaxを使った外部APIとのやり取りの講義だったと思いますが、このようなAPI通信の場合リクエストを送ってからレスポンスが返ってくるまで少し時間がかかります。つまり時系列的なズレが生じるわけですね。
なので「APIとやり取りするぜ!」という処理と「APIが返してきたレスポンスをコンソールに表示するぜ!」という処理が並列に書かれていたとすると、APIからレスポンスが帰ってくる前に「APIが返してきたレスポンスをコンソールに表示するぜ!」が実行される可能性があります。こうなるとレスポンスは何もないのにレスポンスが返ってきてる前提で処理が進んでいくわけですから、結果として意図しない挙動になるのは明らかです。
つまり「ちゃんとAPIからレスポンスをもらってから以下の処理を実行しましょうね!」という感じで時系列的ズレを補正する必要が出てきます。それがasync, awaitなどの非同期処理です(間違ってたらすみません、私はそういう認識です)。
私もまだ勉強中なので、非同期処理を完全に理解した方いらっしゃいましたらぜひ教えてください。
###演習
以下のコードを実行したとき、ボタンを何度押しても相手の手と結果がundefinedしか返ってきません。
コンソールにもエラーは出ていません。
正しい処理の流れを把握して、どこをどうすればじゃんけんアプリとして正しく動作するか考えましょう!
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>サンプルコード</title>
</head>
<body>
<h1>じゃんけんアプリ</h1>
<p>あなたが出す手を選んでください</p>
<button id="gu-btn">グー</button>
<button id="choki-btn">チョキ</button>
<button id="pa-btn">パー</button>
<p id="comHand"></p>
<p id="result"></p>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
let comHand;
let result;
$('#gu-btn').on('click', () => {
const randomNumber = Math.floor(Math.random() * 3);
switch (randomNumber) {
case 0:
comHand = 'グー';
result = 'あいこ';
break;
case 1:
comHand = 'チョキ';
result = '勝ち!'
break;
case 2:
comHand = 'パー';
result = '負け...';
break;
}
});
$('#choki-btn').on('click', () => {
const randomNumber = Math.floor(Math.random() * 3);
switch (randomNumber) {
case 0:
comHand = 'グー';
result = '負け...';
break;
case 1:
comHand = 'チョキ';
result = 'あいこ'
break;
case 2:
comHand = 'パー';
result = '勝ち!';
break;
}
});
$('#pa-btn').on('click', () => {
const randomNumber = Math.floor(Math.random() * 3);
switch (randomNumber) {
case 0:
comHand = 'グー';
result = '勝ち!';
break;
case 1:
comHand = 'チョキ';
result = '負け...'
break;
case 2:
comHand = 'パー';
result = 'あいこ';
break;
}
});
$('#comHand').text(`相手:${comHand}`);
$('#result').text(`結果:${result}`);
</script>
</body>
</html>
#5. まとめ
- 「コードを書いて実装したいこと」を言語化する!
- エラー文を恐れない!
- コードの見た目はキレイにする!
- 処理の流れを掴む!
あれこれと偉そうなことを書きましたが、結局はコードを書きまくることがプログラミングのスキルを高める最短にして最良の方法だと思います!
この勉強会が皆さんのこれからに少しでも役立てば幸いです!ありがとうございました!