本稿はかなり読み物的な記事になります。
端的に情報を得たい方には向いていませんのでご了承ください。
前書き
新卒は困惑した。必ず、近日中にQiita記事を投稿せねばならぬことになった(実際そこまでは言われていない)。
新卒には技術があんまりわからぬ。学生時代は文系大学で歴史を学び、Pi〇ivで絵やら小説やらをこねくり回して過ごしてきた。プログラム的なものは入社するまでほとんど触ったことがなかった。
けれども何かしら進歩していることを見せねばならぬという気持ちだけは人一倍強くあった。
という経緯から、
当初ソースコードが文字の羅列にしか見えなかった過去の私がちょっとだけコードを読めるようになったきっかけについて書いてみることにしました。
初心者が初心者に贈るゴリゴリの初心者向け記事です。
この記事が参考になるかもしれない人
・プログラミングをちょっと勉強したけど、実際に動いているコードを見ても全体の繋がりがわからなくて苦しんでいる初心者
・文系脳すぎて算数・数学を用いた例えがあんまりピンとこない初心者
・未経験文系出身エンジニアの頭の中を知りたい諸先輩方
初見のソースコード読めない問題
社会人生活も8ヶ月目に入り、少しずつ現場で動いているコードに触れる機会が増えてきました。小さな作業を少しずつ任せていただく中で、毎回と言っていいほど当たっていた壁があります。
「初見のソースコードが読めない」
具体的に言うと、どこから読解したらいいのかわからず、従ってコードの流れを掴めない問題がありました。
読解の五大基本道具の説明
先に、本稿のメインキャスト「変数」「定数」「関数」「戻り値」「引数」について説明しておきます。
わかる方は飛ばしてください。
変数と定数
変数・定数については様々なサイトや参考書で解説されていますが、私の理解は以下の通りです。
| 単語 | 解釈 |
|---|---|
| 変数 | 中身を入れ替えてもいい箱(使いまわしを想定している) |
| 定数 | 中身を入れ替えられない箱(使いまわしを想定していない) |
「数」と名乗っているので字面に惑わされやすい文系には紛らわしかったのですが、こいつらは箱です。中に何かをしまっておけます。IT業界で、単一の値を表しそうにない雰囲気の「数」の字を見かけたら「箱」の機能があることを疑ってください。
単なる箱を置いておいても中身がよくわからないので、わかりやすい名前を付けてあることが一般的です。
//日直(日毎に変わるとわかっているので変数で宣言)
let classDuty = '太郎';
//成人年齢(基本変化しないので定数で宣言)
const legalAdult = 18;
このように書いておくと、後からclassDutyの話をすれば「ああ、太郎さんの話ね」とわかりますし、毎回18歳であることを確認せずとも"legalAdult"とだけ書けば18歳のことを指していると伝わるようになります。
変数定数の箱に「何か」をしまうことを「代入」といいます。
単一の値でなくても、〇〇 = △△と書けば大体なんでも変数定数の中に格納することができます。変数定数は四次元ポケットくらいでっかい箱で、めっちゃ長い小説も、めっちゃ複雑な計算式も代入できます。
関数と戻り値
さて、これとは別に「関数」「戻り値」「引数」が存在します。こちらも私の理解を書いておきます。
| 単語 | 解釈 |
|---|---|
| 関数 | 考え事、特に外から見えなくていい作業 |
| 戻り値 | 考え事の答え、作業の結果 |
| 引数 | 考え事(作業)の際に必要な材料 |
関数も「数」が付いているので、イメージは箱です。中にひとつの結論・結果を出すためのややこしい考え事(演算)やその材料をまとめて放り込んでおくものです。
イメージ的にはホームベーカリー。小麦粉などの材料(引数)を放り込んでから熱々トースト(戻り値)が出てくるまでにやってる「何か」が関数です。
関数が具体的に何をやっているのかは、必要がなければ、特に知らなくても実際の活動に支障は出ません。ただ、「関数が何のための演算をしていて、戻り値として何が返ってくるか」は把握しておく必要があります。
以降、千と千尋の神隠しのストーリーを参考に例を示していきます。
// 某魔女が名前を奪う関数(本当なら関数名は動詞が望ましい)
function yubaba(realName) {
const nameCut = Math.floor(Math.random() * realName.length);
const newName = realName[nameCut]; //名前から適当に1字抜き出す(今回は千)
return newName;
}
const realName = "荻野千尋"; //元の名前
const myName = yubaba(realName); //「贅沢な名だね」攻撃で名前が「千」になる
console.log(myName);// 彼女の名前は「千」です
上は湯婆婆が、主人公から名前を奪う過程を適当に関数にしたものです。
定数realNameに格納された値「荻野千尋」を関数yubaba()が受け取ります。関数yubaba()は名前を奪うために演算をして、最終的に「千」という新しい名前を返します。
この「千」が関数の返す戻り値です。
yubaba(realName)の戻り値をmyNameにしまっているため、console.log(myName)を実行すると「千」の一文字だけが返ってきます。
引数
このとき、関数の後ろについている()に変数定数なり単体の値なりを入れることで関数に情報を渡すことが出来ます。この()内に入れた何かを「引数」と言います。「数」が付いているのでこれも箱です。
こっちが渡してやらなきゃいけないのに、なぜコンピュータが自力で取ってこれるかのように「引」の字を使ってるのか、なんてツッコミを入れてはいけません。
プログラミング用語の主格は大抵の場合人間じゃなくてコンピュータです。
function yubaba(realName) // ⇦このrealNameは仮引数
const realName = "荻野千尋";
const myName = yubaba(realName); // ⇦このrealNameは実引数
引数には「実引数」と「仮引数」の2種類があります。
実引数に渡した値がそのまま仮引数にパスされるというイメージです。
| 単語 | 解釈 |
|---|---|
| 実引数 | 渡される値そのもの |
| 仮引数 | 関数定義の際に用意しておくカテゴリ名 |
そのため、function yubaba()の()内の仮引数はrealNameで無くても構いません。function yubaba(caughtName)でもこのコードは動作します。
逆に、実引数はちゃんとそれそのものの値を渡してあげないと読み取れません。
ソースコード? 贅沢な名だね。 お前の名は「戻り値のバケツリレー」だよ
変数や定数を使う理由について、「コードを見やすくするため」と説明するサイトをしばしば見かけます。これは正しいのですが、プログラムの流れを追う上で変数定数にはもっと重要な役目があります。
変数や定数を使うのは、「関数の計算結果となる戻り値をわかりやすく運搬するため」です。
変数定数にわかりやすい名前を付けるのもこのためです。
ある関数の戻り値がどの変数定数に格納され、どの関数に渡ってどのように変換されていくのか、という一連の流れを追うことでコードの流れを掴むことができます。
関数rememberName()は、ハクが自身の名前を思い出す過程を関数化したものです。
(公式で提示されていない漢字表記を使っています)
function yubaba(realName) {
const nameCut = Math.floor(Math.random() * realName.length);
const newName = realName[nameCut];
return newName;
}
const realName = "饒速水琥珀主"; //ハクの本名
const myName = yubaba(realName); //myNameに「珀」が格納される
//本当の名前を思い出す処理
//聞いた名前、いまの自分の名前、忘れた本当の名前を比較している
function rememberName(heardName, currentName, forgetName) {
const memoryKeys = heardName.split('');
const isMatch = memoryKeys.some((key) =>
currentName.includes(key) && forgetName.includes(key)
);
if(isMatch){
return forgetName;
} else {
return currentName;
}
}
//名前を思い出すきっかけ
const trueName = rememberName("琥珀川", myName, realName)
//名前を思い出した!
console.log(trueName)
rememberName()は渡された3つの実引数を材料に演算を行っています。
・"琥珀川"(キーワード、仮引数hearNameで取得)
・myName(関数yubaba()の戻り値"珀"、仮引数currentNameで取得)
・realName("饒速水琥珀主"、仮引数forgetNameで取得)
このプログラムでは、realNameの箱に入った文字列「饒速水琥珀主」が、関数yubaba()によって「珀」に変換されてmyNameに格納され、それがrememberName()に渡されて「饒速水琥珀主」に変換され、trueNameに格納されています。
このように変数定数の値の変化を追うことで、「名前を奪われた後、また戻ってきた」というプログラムの流れを追っていくことができます。
ソースコードは基本的にこうした処理の繰り返しで、
変数定数の値を確認 ⇒ 行先の関数を確認 ⇒ 戻り値と戻り値が格納された変数定数を確認 ⇒ 行き先の関数を確認(以降繰り返し)
という順番で読んでいくことができます。
まずは定数変数を探してから、その変数定数がどのように変換されてどこへ行くのか、という行き先を辿る動きがコード読解の基本になるでしょう。
おまけ:VScodeの便利機能
⇧
VScode上で変数名等をダブルクリックすると、このように同じキーワードがマークアップされるので流れを追うときに便利です。
⇧
カーソルを合わせてしばらく待つとこんな感じの説明文も出てきます。
ちょっと見えにくいですが、ここではrememberName()にカーソルを合わせています。
最後に
今時小学生でもプログラミングをやっていますし、正味AIにコードを丸ごと放り込めば読んで解説してくれるのでこんな記事が役に立つのかは疑問ですが、私はこれに気が付いてから本番のコードを読むのが結構楽になりました。どなたかの参考になれば嬉しく思います。

