新入社員にむけてのオブジェクト指向入門〜その1：オブジェクト指向とは何か〜

# 概要
新卒さん向けに、オブジェクト指向についての解説をするための投稿です。
何回かに分けて投稿をします。
第一回目は、そもそもオブジェクト指向とは何かということの説明をします。

第一回目：オブジェクト指向とは何か←今ココ
[第二回目：カプセル化](https://qiita.com/oda-kazuki/items/663f87cac4d051ab27c0)

## 対象読者
【初心者向け】 ☆★☆☆☆ 【上級者向け】
オブジェクト指向について、なんとなく研修やら技術書やらで読んだり聞いたりしたことのある人を対象にしてます。

# はじめに〜オブジェクト指向、誤解してない？〜
システムを作る選択肢として、今でもオブジェクト指向を採用するというのは主要な流れのひとつです。
もちろん、それが選択肢の全てではありませんが、JavaやPHP、C#、Swift、Go言語などでシステムを構築するときには、基礎知識としてオブジェクト指向はついて回ります。

ただ、一部の入門書や研修では、オブジェクト指向について正しく教えているとは思えないというのが正直な感想です。たとえば、単純に以下の認識でいる場合、もしかしたらオブジェクト指向について誤解しているかもしれません。

* **何かをクラスとメソッドで表現するのがオブジェクト指向**  
→ 確かにそうではあるのですが、正確ではない可能性があります
* **privateメソッドなどで一部メソッドをカプセル化したりするのがオブジェクト指向**  
→ 重要な要素ですが、本質はそこではありません。
* **継承やインタフェースを使うのがオブジェクト指向**  
→ 同じく重要ではあっても、やはり本質はそこではありません。
* **GetterやSetterを使うのがオブジェクト指向**  
→ ちょっと毒されてるかもしれない

# オブジェクト指向とは
では、早速ですがオブジェクト指向とはなんなのかの回答をします。そのために、一度Wikiから抜粋します。

> オブジェクト指向は、プログラミング・パラダイムとして誕生した知識体系である。そのデータ（変数またはプロパティ）とコード（関数またはメソッド）のセットを基本要素にして物事を解析する考え方が、1980年代から大きく注目され始めた事で、ソフトウェア工学のあらゆる局面にobject-orientedを接頭辞にした分野が立ち上げられた。大まかな特徴としては、情報資源と処理手順を別々にして分析ないし設計を行っていた従来の標準的な手法に対し、オブジェクト指向と名が付く分野ではこの双方をひとまとめにして物事の解析と組み立てを行う点が共通している。
[オブジェクト指向 - Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91)

ここで、大事な部分を箇条書きにして抜粋します。

* プログラミング・パラダイムとして誕生した知識体系
* そのデータ（変数またはプロパティ）とコード（関数またはメソッド）のセットを基本要素にして物事を解析する考え方
* (情報資源と処理手順の)双方をひとまとめにして物事の解析と組み立てを行う

この「プログラミング・パラダイム」とはなんでしょうか。それも同様に抜粋します。

> プログラミングパラダイムは、プログラマにプログラムの見方を与えるものと言える。たとえば、オブジェクト指向プログラミングにおいて、プログラムとはオブジェクトをつくりそれを管理するものである。
[プログラミングパラダイム](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%91%E3%83%A9%E3%83%80%E3%82%A4%E3%83%A0)

要は **プログラミングをする際の考え方や枠組み** だと思っておけば良いかと思います。

また、そもそもとして「オブジェクト」とはなんでしょう？
それも、同じようにWikiから抜粋しましょう。

> オブジェクト（英: object）はオブジェクト指向プログラミングにおいて、プログラム上の手続きの対象を抽象化する概念である。
[オブジェクト (プログラミング)](https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0))

整理すると、オブジェクト指向とは以下のものだと言えます。

**オブジェクト指向とは、手続きの対象を抽象化し、そのデータ（変数またはプロパティ）とコード（関数またはメソッド）のセットを基本要素にして物事の解析と組み立てを行うプログラミング・パラダイムとして誕生した知識体系**

またちょっとわかりづらいことを書いてますが、要するに「**対象のデータと、そのデータの加工をメソッド化したクラスを使ってシステムを構築する手法**」と思ってもらえると、誤解はないかと思います。

## オブジェクト指向は「整理術」

極論をいうと、オブジェクト指向とは単なる「**整理術**」にほかなりません。**対象を抽象化し、データやメソッドをクラスとして整理するためのやり方**、それこそがオブジェクト指向です。このことを実感できれば、オブジェクト指向というと難しくとっつきにくいと思えるかもしれませんが、単なる整理術だと思えば敷居は下がるのではないでしょうか。

![オブジェクト指向とは？.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441331/11052f24-1e5e-732c-bc0d-6beae85da241.png)


### 整理術ってほんとぉ？

こう書いても、単にぼく一個人がそう言ってるだけだと思うかもしれませんが、実際にオブジェクト指向が誕生する歴史を追っても実際に整理術として生まれたというのがわかります。

オブジェクト指向の歴史については、以下のQiitaの記事が非常に参考になります。
[新人プログラマに知っておいてもらいたい人類がオブジェクト指向を手に入れるまでの軌跡](https://qiita.com/hirokidaichi/items/591ad96ab12938878fe1)

長いですが、とてもためになる記事なので一度は読むことをおすすめします。
ここでは簡潔にまとめちゃいます。

* 昔、プログラミングは基本的なデータ型(数値)で管理され、メモリを直接いじり、gotoやjump命令のようにプログラムカウンタを直にコントロールする方法で書かれていた
* そのプログラムは可読性が低く、どんどん複雑化するシステム作成において足かせとなり、品質や予算超過として現れてそれ以上複雑なシステムは作れないのではないかとなった（ソフトウェア危機）
* それを解決するため、プログラムで**データをどう扱い、どのように処理を記述していくか**といったノウハウが確立していった
    * 構造化プログラミング
    * モジュラープログラミング
    * 抽象データ型
    * メッセージング
* それらを取り込んでまとめたものとしてオブジェクト指向が提案された

ここで留意したいのは、当然ながら**昔はオブジェクト指向なんてなかった**ということです。つまりそんなものなくてもシステム自体は作成することができます。実際、まだオブジェクト指向ができる前に人類はシステムを使って宇宙に進出したし、その頃から10MStepを超えるようなシステムも作成されていました。別に**システムはオブジェクト指向を必要としていない**のです。

では誰のためのものか？ 言うまでもなく、**人のためにオブジェクト指向は存在しています**。コードをあるルールにのっとって整理をし、体系化することで**データを抽象化することができ、関心事をその中に閉じ込めておく**ことで、その後メンテナンスをしやすくしているのです。

### 抽象化？関心事？
さて、先程からあまり耳慣れない言葉として「抽象化」と「関心事」というものがでてきていますが、この２つの概念は、**オブジェクト指向の真髄**でもあります。それぞれ説明します。

#### 関心事とは
簡単にいうと、**そのプログラムがなにに注目をしているのか**になります。ドメイン駆動では**ドメイン(領域)**という言い方をされることもあります（厳密にはドメインと関心事は違うけど、ここではだいたい同じものと思っておいて良いと思います）。勤怠システムを例をあげると、関心事は、文字通り「社員の勤怠・稼働の管理」になるでしょう。

そして、「社員の勤怠・稼働の管理」という関心事は機能によって分割することもできます。以下に例を上げると、

* 社員の出勤・退勤打刻機能
* 稼働集計機能
* 残業・休暇・休出等各種申請機能

などがあるかもしれません。

#### 関心事は更にどんどん分割できる

上記は、**機能**に注目をしました。だけど関心事は他にも以下のものに注目をすることができます。

* **用語**（上記の場合は「社員」「出勤」「退勤」「稼働」「残業」「休暇」「休出」など色々ありますね。上の例には出てませんが「部署」「グループ」などもあるかもしれません）
* **単位**（時間や日数、人数などがあるでしょう）
* **集合体**(社員一覧などがありそうです）
* **ユースケース**（社員が出勤する / 社員が退勤する / 管理者が集計をとる など)
* **状態**（出勤中 / 退勤 / 申請中 / 承諾 / 破棄 などの状態がありそうです）
* **処理・ふるまい・フロー**（リクエストのハンドリングや、DBからの取得といった内部処理も関心事として抽出できます）
* **業務要件・ルール**（「出勤は退勤より未来にはできない」といったルールも関心事になりえます）
* **取り扱うデータ** （出勤日時、退勤日時、申請書などがありそうですね）
* **外部システム** (そのシステムが連携する外部のAPIなど）

#### 抽象化とは
次に、抽象化についてです。こちらは、実は関心事で行っている内容とあんまり差はありません。なお、抽象化に表現することを**モデル化**といい、その言葉もちょくちょくIT技術書などには出てきます。
抽象化についてをWikiから抜粋します。

> 抽象化（ちゅうしょうか、英: Abstraction、独: Abstraktion）とは、思考における手法のひとつで、対象から注目すべき要素を重点的に抜き出して他は無視する方法である。
[抽象化 - Wikipedia](https://ja.wikipedia.org/wiki/%E6%8A%BD%E8%B1%A1%E5%8C%96)

つまりは、業務内容などの対象を**ある関心事だけに抜き出す作業**が抽象化です。抽象化は、対象が同じだったとしてもどこに注目するかによって、モデルとして表す形は異なってきます。

![抽象化とは.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441331/436e2b85-da1f-bb34-d856-9a32b8abd79c.png)

これは、オブジェクトを作成する上でとても重要な概念です。ただなんとなくデータをクラスにするのではなく、**ある関心事をモデルにあらわしているという意識は、それが正しくモデリングできているかどうかを自己分析する指標ともなります。**

## 関心の分離こそがオブジェクト指向の真髄
オブジェクト指向を勉強する中で、よく「**関心の分離**」という言葉を目にする機会があるかと思います。
この関心の分離については、別の機会に詳しく説明をしたいと思っていますが、簡単に説明すると「**関心事を、それ単体として独立して存在できる単位で、ひとつのクラス・またはパッケージの中に閉じ込めること**」だと今は思っておいてください。

**独立して存在できる単位**というのが重要です。独立とは、他への依存がないということを表します。
たとえば、勤怠システムで「社員」を扱おうと思った時、社員に関わる関心事を、独立できる単位で「社員クラス」にまとめてしまうというというイメージです。上の例でいうと、「社員番号」や「社員名」などのデータは、ひとつに纏めることができるでしょう。そして「社員番号」「社員名」ともに、勤怠や稼働の内容によって変更されることはありませんから、**「社員クラスはシステムの他の機能に依存しない」**ものといえそうです。

オブジェクト指向の書籍などでは、その書籍によっていろんな方法でオブジェクトについての説明をしています。また、オブジェクト指向をする上での原則というものも存在しています（それも今後説明する予定です）が、全ては「関心の分離」をするための説明・指針だといっても過言ではありません（ちょっと極論めいてはいますが）。そして、簡単そうに見えて一番むずかしいことでもあります。

## オブジェクト指向の恩恵
この整理術は、きちんと整理ができると以下の恩恵をうけることができます。

* **独立性が高くなる**  
データとふるまいを同じところに置くことで、特定のその中だけに関心事を閉じ込めることができ、他の機能から独立して動かすことができるようになります。
* **メンテナンスがしやすくなる**  
独立性が高くなることで、ある関心事のふるまいを修正する必要が生じた際、局所的な修正だけで済むようになります。結果的にメンテナンスがしやすくなります。
* **再利用をしやすくなる**  
独立性が保たれていることで、その関心事を扱う必要のある他のクラスからも呼び出すことができ、同じコードの重複を防ぐことができます。

それらの恩恵は、オブジェクト指向を知らない開発者でも多く受けていることでしょう。
たとえば特定の汎用的な関心事を機能全体に拡張したものが**ライブラリ**して数多く公開されており、ほぼ全ての開発者がその恩恵をうけています。またシステムの「作り方」そのものを汎用的な関心事として切り出されており、それらの**フレームワーク**を多くの開発者が利用しています。

更にオブジェクト指向はサーバー設計にも応用されています。
現在のほとんどのクラウドサービスが**マイクロサービス・アーキテクチャ**で構成されていますが、これはオブジェクト指向の考え方をサーバーにまで発展させたものです。

## 誤ったオブジェクト指向の弊害

ただ、今のシステムには「なんちゃってオブジェクト指向」が結構よく存在しています。
理由は**オブジェクト指向で作成し、維持するという難しさ**があります。また、オブジェクト指向について正しく理解をしていないと、抽象化（モデル化）する際に関心の分離ができておらず、結果いろんなクラスへの依存が高まって保守性が著しく落ちることになってしまいます。

一度そうなってしまったシステムは維持するのにとても工数がかかるようになります。何かを追加開発しようとしても、デグレードが発生していないか、常に全体の試験をする必要性が生じるからです。
それを防ぐため、**実装者は全員オブジェクト指向について正しい認識を持ち、関心の分離が不全となっていないか点検する**ことが重要です。

# まとめ
最後に、オブジェクト指向とは何かというのを簡単にまとめます。

* オブジェクト指向は、関心事（データ、ふるまい等)をクラスの中に閉じ込める整理術
* オブジェクト指向では関心事と抽象化が重要
* オブジェクト指向では様々な恩恵を受けることができるが、誤ったやり方をすると恩恵は得られず、かえってシステムの維持コストがかかるようになるため正しい認識が重要

次回は「カプセル化」について書こうかと思います。