【プログラミング】プログラミング上達の近道は、アルゴリズムの構築能力を磨くこと

f:id:orchid-bell:20181210230131j:plain
Designed by Creativeart

 プログラムの勉強を始めてみると分かりますが、入門書である程度勉強すれば、動くものは意外と簡単に作れるようになります。
でも、それと不具合の少ないプログラムとか、メンテナンスしやすいプログラムなど、実用に耐えられる品質のプログラムを作れるかは全くの別問題です。

今回はそのようなプロとしての品質確保をどのように考えるかという、少し上級者向けの内容を書いてみたいと思います。

 

プログラミング言語自体より、プログラミング言語を通してアルゴリズム構築能力を磨く意識を持つことが大事

アルゴリズムとは、プログラムの処理順序や計算方式のことです。「段取り」と言い換えても良いと思います。
つまり、こういう順番で処理すれば正確にミスなくプログラムが動くとか、効率が良いとか、そういうことをプログラミング的に考える力を磨くことが大事です。

これがなぜ大事かというと、プログラミング言語は、あなたが考えたアルゴリズムを言葉で表現してくれるだけのものだからです。

例えば、分かりやすい文章を書ける人と書けない人をイメージしていただけると分かりやすいと思います。
自分の考えを要点をまとめて伝えたり、反対に冗長で分かりにくい考え方をしてしまうのが「アルゴリズム」です。それを言葉にするために使う日本語が「プログラミング言語」です。

同じ日本語でも、誰が書くかによって差が出るように、プログラミング言語もどうやって考えるかによってプログラミングに差が出てきます。

プログラミング言語を学ぶとは、日本語や英語のような言葉を学ぶこと。アルゴリズムを学ぶとは、分かりやすいプログラミングをするための考え方を学ぶことだと覚えておいてください。

 

コツは人の処理限界を超えないこと

さて、それではアルゴリズムを作る上でのポイントを解説していきます。

結論から言いますと、そのコツは「人の処理限界を超えないレベルにまで作業を細分化する」ということになります。

詳しく説明します。

箱の中にリンゴとミカンがあって、これを仕分けしてそれぞれの数を数えるアルゴリズムを考えてみます。

こんな風に考える人が多いんじゃないかと思います。

パターン1: ステップを区切る

  1. 2つ箱を用意して、リンゴとミカンを分ける
  2. 箱の中身をそれぞれ数える

【プログラム的な表現】
foreach(果物 : 果物の箱){
  if(果物 = リンゴ) リンゴの箱に入れる
  if(果物 = ミカン) ミカンの箱に入れる
}
リンゴの箱をカウント
ミカンの箱をカウント

もう1パターン考えてみます。

パターン2: 1ステップでやる

  1. リンゴとミカンを仕分けつつ、数を数える

【プログラム的な表現】
foreach(果物 : 果物の箱){
  if(果物 = リンゴ){
    リンゴの箱に入れる
    リンゴ++
  if(果物 = ミカン){
    ミカンの箱に入れる
    ミカン++
  }
}

パターン1は分ける、数えるという動作が分かれていて考えやすいと思います。パターン2は、分けながら数えるという複合的なワザを使っていて、少し考えないと何をやりたいか分かりにくいと思います。

このくらいならまだなんとかなりますが、例えばここに「腐ったミカンは取り除く」というような追加条件が加わったらどうでしょう?

パターン1: ステップを区切る

  1. 2つ箱を用意して、リンゴとミカンを分ける
  2. ミカン箱から腐ったミカンを除く
  3. それぞれの箱の中身を数える

パターン2: 1ステップでやる

  1. リンゴとミカンを仕分けるが、ミカンは腐っていたら別にして数を数える

パターン2の複雑度が一気に増しました。さらにもう1条件加わったら、文章としての表現も限界を超えそうですね。私のような凡人では1文に詰め込むのは3つ程度が限界です。

この例は果物を例にして考えているので、「いやいや、そんな風に考えないよ」と突っ込まれると思いますが、これが「文字列を改行コードで区切って行数を数える」のような表現に置き換わると、なぜか途端にパターン2のように考える人が増えます。

実際の開発では仕様が後から追加されることが多く、パターン2のような考え方でいると、条件が追加された際にあっという間に処理限界を超えて、わけがわからなくなってしまいます。

これってソフトウェアが見えない世界のものなので、現実のロジックとうまく照らし合わせて考えられないというか、プログラミングという行為を特別視して、自分の中で変に線引きしてしまっているのが原因なんじゃないかなと思ってます。

プログラミングの参考書は、ほとんどパターン1のような考え方を中心にサンプルコードを掲載しています。サンプルコードはプログラミング言語の表現を教えているだけでなく、そこにはアルゴリズムの本質的な考え方もそこには含まれていますので、そのあたりも意識して参考書を読んでみてください。


設計の考え方も同じ

今回は実際にコードを書く部分についてのアルゴリズムを書きましたが、設計においても考え方は同じです。

「1機能1クラス」とか「1機能1メソッド」という言葉を聞いたことがないでしょうか。要するに、複数の機能を同じ場所にいっぱい持たせるんじゃなくて、ちゃんと機能分解して管理しましょう、ということです。

ただし、コードと違い要素を少し大きくとらえる必要があるので、考え方の抽象度を少し上げて考える必要があります。

コードレベルでこの考え方ができるようになると、自然と設計にも応用できるようになると思います。

 

アルゴリズム構築力の鍛え方

では、どうやってこのアルゴリズム構築力を鍛えていくかという点について考えてみたいと思います。

一番効果的なのは、自分が書いたコードを優秀なエンジニアにコードレビューしてもらうことです。

プログラミングスクールに通っているのであれば、講師の人に積極的にお願いしてみましょう。独学であれば、ココナラのような個人のスキルを売り買いできるサイトを活用すると、質の高いレビューが受けられる可能性が高いです。

書籍で学ぶのであれば、「アルゴリズム図鑑 絵で見てわかる26のアルゴリズム(翔永社 石田 保輝 (著), 宮崎 修一 (著) )」がおすすめです。図解で分かりやすくアルゴリズムのエッセンスを学ぶことができます。