プログラミング入門書にビット演算、while文、継承、index付きforループの解説は本当に必要なのか?


世の中に出版されているプログラミング入門書は数多くありますが、そのほとんどにおいて

  • ビット演算
  • while文
  • 継承
  • index付きforループ

について最初のほうの章(基本的な文法の章)で解説されています。

しかし

はたしてこの4つに対する解説って必要なのか?

と思いました。入門書ってだいたい同じ構成で、「基礎」と言われているようなものを網羅した構成になってますけど、「その知識本当に必要とされるの?」ということに関する視点が欠けているのではないかと感じます。

「ま、世の参考書ってだいたいこの項目が基礎編で解説されてるからそのまま解説かけばいいか」って思考停止をしているような。

さて、では私が「不要じゃねこれ?」と思った項目について考察していきましょう。

ビット演算

3年ほどコードを書きましたが経験上、一度もプロダクトコードで使っていません。
そもそも、この演算方法は「ビット演算に関する知識を開発者に強制する」ので多分コードレビューで真っ先に突っ込まれるポイントです。

論理演算子の組み合わせのみで条件文を作るようにしたほうが直感的で読みやすいコードができます。

while文

while文でやりたいことはほぼすべてfor文で書けます。

実用上も、whileを使うコードはほぼ見なくなってきており、初学者にこれを紙面を割いてまで教えるメリットを感じません。

無限ループの危険があり(for文でも無限ループは絶対起こらないとは言えないですが)、やはりコードレビューで真っ先に突っ込まれるポイントだと思います。

継承

実用上、template methodパターン以外使いません。

(初心者にはややこしいですが)適切な継承には、リスコフの置換原則が適用されなければなりません。

リスコフの置換原則とは、「サブクラスとスーパークラスは本質的に同一のもの」でなければならないことを意味します。

経験上、「今作ろうとしているクラスが、本質的に継承元親クラスと同一か?」ということを見極めるのは非常に難しいと思っています。

継承の濫用はコードレビューで真っ先に突っ込まれるポイントです。

クラスにある特定の機能が欲しいからと言って、「よーし差分プログラミングだ!」といって継承を使うべきではありません。(「機能の横恋慕」というアンチパターンです)

ダメなパターンを一つ紹介しましょう。

まず、「鳥」というクラスがあったとしましょう。


public class Bird {
  
  public void eat(Eatable food){
    System.out.println("Eat something");
  }

  public void fly(){
    System.out.println("I can Fly");
  }
}

「鳥」というクラスには「食べる」というメソッドがありますから、これを使いたいので、「人」というクラスを、「鳥」というクラスを継承して作りましょう。


public class Human extends Bird{
  
  @Override
  public void fly() {
     throw new AssertionError("I cannot fly...");
  }

}

確かに、Humanクラスにeatメソッドを再定義しなくても、Humanクラスにeatメソッドを持たせることができました。

しかし、人は飛べませんから、Humanインスタンスのfly()を呼ぶとエラーになります。

この例では、直感的にも人は鳥から派生していませんし、鳥であれば動いたメソッドが人だと動かなくなっています。これはリスコフの置換原則を無視した、誤った継承の例です。

機能単位の使い回しには、継承の代わりに委譲を使うべきです。継承の解説に紙面を割くなら委譲(と、可能ならば適切なモジュール分割)に紙面を割くべきだと思います。

リスコフの置換原則に関しては、このブログを参考にさせていただきました。

index付きforループ

「index付きforループ」という呼び方が正しいのかはわかりませんが、


for(int i=0;i<10;i++){
  System.out.println(i);
}

こういう原始的なforループです。

Swift3.0ではこのスタイルの書き方は廃止(今でもこの書き方をするとXCodeに警告が出ます。)、他のモダンな言語でもほぼすべての言語がforin文(forEach文)か、streamでループを回す書き方をサポートしています。

そして、「繰り返し」の操作はこのfor in文かstreamでほぼカバーできますし、現代の主流になっていますから、こちらを最初から覚えたほうが良いです。

そういえば、Javaの入門書で配列に関して懇切丁寧に解説しているものもありますが個人的には不要だと思います。(理由は簡単で、実用上ほぼすべてListで代用するからで、最初からListのメソッドを使い方を覚えたほうが効率的だからです。)

まとめ

プログラミングをする上で、知識というのは絶対に必要です。

ですが、同時に「知識を詰め込む作業」というのは、結構なストレスを伴います。

しかもその詰め込まれる内容の中には、上述したように実践上不要なものが多分に含まれているとしたら?

初心者の方がこの「知識詰め込み作業」で消耗して、本来楽しい「自分の作りたいものをつくる」ことを体験する前に挫折してしまうとしたら、それは不幸なことではないでしょうか。

必要最低限の知識だけ詰め込んで、後は少しでも早く実践させる。その中で初心者自身が「これは必要だ」と思った知識を拾っていく。かつ、自分が作ったものがきちんと動いて成功体験が積める。

プログラミングに関するイメージ的な敷居が下がっている中、そのような入門書が必要なのではないかと思います。