プログラミングのための考え方について

# はじめに
プログラミングは難しいとよく聞きます。
私も仕事でプログラミングをしていて難しいと思うことは少なくありません。
しかし、それはプログラミング言語を操り想定通りに動くプログラムに仕上げることが難しい、想定される動きが想像できなくて難しいというものです。
実際のところ、プログラミングのための考え方の基本は極めて簡単です。
それを少し紹介したいと思います。

本記事は私の経験から初学者や経験の浅いプログラマーが明らかに考え方を理解できていないと感じたことを記すものです。
記事の内容は必要に応じて加筆修正を行います。
また、話の内容がプログラミングにおける何と結びつくのかを示すために、プログラミングで頻出する単語をいくつか使用します。
単語の意味は解説しませんので、必要に応じて各自で調べるようにお願いいたします。
プログラマーに限ったことではありませんが、自分で調べ自分なりの解答を出せる能力は極めて重要です。

# プログラミングとは
そもそも、プログラミングとは何でしょうか。
簡潔に言うなれば、プログラミングとは問題を解決するための手順を明文化する行為です。
私たちが文章を書く行為と変わりありません。
それが普段読み書きする日本語や英語といった自然言語と異なるプログラミング用の言語になるだけです。

ここではあえてプログラミング言語ではなく、プログラミング用の言語と書きました。
プログラミングというのは直接プログラムを作るための工程（製造やコーディング）のみを指すわけではありません。
一般にコーディングのことをプログラミングと呼ぶことが多いのですが、実際はプログラムの設計段階で使用される専用の言語もあり、それらを使用することもプログラミングと呼びます。

# プログラミングのための考え方
さっそくプログラミングのための考え方を紹介しましょう。
大きく分けて考え方は次の3段階に分かれます。

1. 問題を分類する
2. 分類した問題を理解できる単位まで分割する
3. 分割した問題を機能的に意味のある問題にまとめる

実際はこの1〜3を繰り返し行います。
なぜこのように考えるのかという理由ですが、大きな問題は小さな問題が集まってできているからです。
例えば、環境問題を解決するして、私たちが環境問題を一度に解決する手段が思いつくでしょうか。
そんな手段は思いつきませんよね。
そもそも環境問題とは何かを考えると、水質汚染、大気汚染と様々なものがあります。
では、水質汚染を解決するためにはどうすればいいのか。
生活排水や工場排水を出さない、出すにしても綺麗にしてから排出する。
といったように問題を分類し、問題を小さくしていきます。
そうすることで、問題を解決するための手段を明確にするのです。

環境問題というとプログラミングをイメージしづらいので、ここからは簡単な通販サイトを例に説明していきます。
話を簡単にするために、個人を特定し配達先の住所を指定する等は考えないものとします。

## 問題を分類する
最初に問題を分類します。
どのような基準で分類するのかというのが一番難しいところです。
問題によって最適な分類方法が異なっているためです。
しかし分類しないことには始まりません。思い切って分類しましょう。
よくある分類として、アプリケーションであればディスプレイに表示される画面や機能で分類します。
通販サイトを画面で分類するのであれば、次のように分けることが可能です。

* 商品の一覧を表示する画面
* 選択した商品の詳細情報を表示する画面
* 商品を注文する画面
* 商品を注文した結果を表示する画面

他にも画面はあるでしょうから、他の画面についても同様です。
機能で分類する場合は次のように分けられるでしょう。

* ユーザの操作を受け付ける機能
* ユーザの操作をチェックする機能
* ユーザの操作を元にDBを操作する機能

抽象的に書きましたが、他にも多くの機能が存在します。

上記の例では画面と機能で分類しました。
どちらの分類でも間違いではありません。
ひとまず、ここから先は画面で分類したとして話を進めます。
このあとの工程で分類をさらに細かくします。

## 分類した問題を理解できる単位まで分割する
次に、分類したそれぞれをさらに細かく分割します。

商品の一覧を表示する画面では、商品の情報を表示することはもちろん、画面に表示するための商品の情報を取得する必要があります。
少なくとも、次の3種類の機能が必要です。

* 商品の一覧を表示する機能
* 商品の情報を取得する機能
* 商品の詳細情報を表示する画面に移動する機能

商品の一覧を表示する機能は画面に表示するための機能なので、表示する情報が必要です。
商品の詳細情報を表示する画面に移動する機能についても、どの商品なのかが分からないと何もできません。
となると、この3機能の中で重要になるのは商品の情報を取得する機能です。
それでは商品の情報はどこから取得するのでしょうか。
通常、このような情報はDBから取得します。
ということは、商品の情報を取得する機能はDBを操作する機能と考えられます。
言い換えれば、DBを操作する機能には、商品の情報を取得する機能が必要ということです。
ここまでで、商品の一覧を表示する画面では「何をする必要があるのか」が分かりました。

続いては、「どうやって機能を実現するのか」を知る必要があります。
DBを操作する機能であり、商品の情報を取得する機能なわけですから、商品の情報を取得する必要があります。
手順にすれば次のようになるでしょう。

1. DBを操作できる状態にする。（Openする）
2. DBから商品の情報を取得する。
3. DBを操作しないようにする。（Closeする）

目的は手順2にあります。手順1と3は手順2を実現するための準備と後片付けにあたります。
DBは通販サイトとは別のアプリケーションになるので、使うためのお作法というものがあり、それはDBが定めた方法に従う必要があります。
そのお作法が手順1と3になります。
商品の一覧を表示する画面で使用される機能なので、手順2では複数の商品の情報を取得する必要があります。
手順2で取得される商品の情報の中には、DBに登録された多くの商品情報から1種類の商品を特定するための情報が含まれます。（含まれていなければ商品を特定できません。）
それを使用すれば、選択した商品の詳細情報を表示する画面に移動する機能についても実現できそうです。
あとは、取得した情報を画面に表示する機能、選択した商品の詳細情報を表示する画面に移動する機能についても同様にして小さい手段にまで分割します。

細かい話は抜きにして、これで「どうやって機能を実現するのか」が分かりました。
ここまでで、商品の一覧を表示する画面についての分類、分割が終わりました。
次は、選択した商品の詳細情報を表示する画面について考えてみましょう。

商品の詳細情報を表示する画面には次の3種類の機能が必要でしょう。

* 商品の詳細情報を表示する機能
* 商品の詳細情報を取得する機能
* 商品を注文する画面に移動する機能

商品の一覧を表示する画面と同じような機能に分割できました。
実際、コーディングでは似たコードを書くことになるでしょう。
というわけで、この後の流れは商品一覧を表示する画面とほとんど同じです。
したがって、商品の詳細情報を表示する画面についてもここで分類、分割を終えたこととします。

他の画面についても同様の流れで分割を行います。
全ての画面において分類、分割を終えたところで次の工程に進みます。

## 分割した問題を機能的に意味のある問題にまとめる
最後に分割したものを再度まとめます。
この「まとめる」というのは、2つ以上ある同じものを1つにするという意味と、同じようなバラバラになった機能を1つの分類として扱うという意味です。
なぜかというと、同じものが2つ以上あると変更があるときに同じものすべてを修正しないといけなくなり手間がかかるためです。
また、同じような機能は1箇所にまとめておく方が分かりやすいという意図もあります。
スーパーに大きな商品棚が1つだけあって、全ての商品がバラバラに置かれている状況より、複数の商品棚に分類されて置かれている方が分かりやすいですよね。

これまでに説明した例ですと
商品の一覧を表示する画面の、商品の情報を取得する機能と
商品の詳細情報を表示する画面の、商品の詳細情報を取得する機能は
どちらもDBを操作する機能であり、商品の情報を取得するための機能です。
ということは、DBを操作する機能の中の、商品の情報を取得する機能としてまとめ、分類する方が整理しやすそうです。

画面はそれぞれ用途が異なるので先ほどの機能のようにまとめることはできませんが、共通するところがないわけではありません。
共通するところをまとめれば、無駄を減らすことができます。

ここまでで1サイクルです。
これを何度も繰り返し行い、プログラムを作成するわけです。
規模の小さなプログラムを組むときはコーディングしながら、頭の中でこの作業を行います。

# おわりに
プログラミングのための考え方というのは難しいものもありますが、根本的なところは日常生活で私たちが意識せず行なっている思考や行動をあえて意識して「分類され順序立てられた文章にする」行為に他なりません。
難しいと感じる原因は、普段意識していないことを意識しなければいけないことなんです。
プログラミングと聞くと特殊なことをしているようですが、実際はそれほど特殊なことではないのです。
（あえて意識することは特殊な行為かもしれませんが。）
コーディングは特殊な行為かもしれませんが、それも文章を書くことと根本的な違いはありません。
日本語か、英語か、それともプログラミング言語か、その程度の違いでしかありません。
プログラミングに取り組むということは、難しいことを簡単に考えるということです。
なので、複雑に捉える必要はないのです。
プログラミングとは、私たちが意識せず行なっている思考や行動をあえて意識して「分類され順序立てられた文章にする」行為なのですから。

# Appendix
プログラミングのための考え方をコーディングのレベルにまで落とし込むと、次のようになります。
（　）内にはコーディングにおいて対応する作業について記載しています。

1. 問題を分類し（クラスに分割）
2. 分類した問題を解決するための手段を細かく分割し（クラスに分割、メソッド・関数に分割）
3. 小さな問題に対して、何のために、何を、どうやって解決するのかということを明らかにし（メソッド・関数に分割）
4. 同じ解決手段はひとつにまとめることで無駄を省き（汎化、共通化）
5. 問題を解決するための手順を定め
6. 問題を解決する手順にしたがって解決手段を組み合わせる