2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

絵だけで分かった気になるオブジェクト指向プログラミングの成長

Last updated at Posted at 2020-12-25

雰囲気オブジェクト指向プログラミングシリーズです。

オブジェクト指向プログラミングの成長は、コードの変化もさることながら、コードへの認識が変わることも重要に感じています。そこで、認識の変化を分かりやすくするため、あえてコードなしで、絵だけで視覚化して、成長段階を説明してみたいと思います。

この過程はあくまでも私の経験ベースによるものなので人によっては違うかもしれません。

1. 継承

image.png

#4472c4
#ed7d31 拡張

継承を覚えた瞬間のイメージですね。
クラスに何かを加えてクラスを大きくしてるイメージです。

2. 処理を分割しただけの委譲

image.png

#5b9bd5 処理全体
#ed7d31 処理の一部を委譲したクラス

大きな処理の一部を、クラスに切り出してるだけですね。切り出したクラスも含めて処理全体と認識してる段階です。
「継承よりも委譲がいい」と言われてコードを見ても、それが当たり前に見えて良くわからない。
委譲というイメージが湧いていません。

3. 処理を分割しただけ ver Web MVC

image.png

#5b9bd5 Controller
#ed7d31 Service的なモノ
#ffc000 DB(ORM)

責務的なイメージが最初に沸いたのは、レイヤー構造だったので、馴染みのあるWeb MVCとしてみました。
Controllerという処理をただ分割していました。

3. オブジェクトの役割(責務)に気付く

image.png

#4472c4 Controller
#ed7d31 Service
#ffc000 DB(ORM)

Controllerの役割から、オブジェクトの役割に気付き始めます。

コードへの認識が大きく変わります!

  • Controllerは、Hogeサービスに、処理を依頼する。
  • Controllerは、Hogeサービスの結果によって、プログラムの流れをハンドリグする。
  • Hogeサービスは、その処理を実行する実際のサービス。

みたいな感じです。

3. 2. オブジェクトの役割に気付いたけど、レイヤ汚染

image.png

#4472c4 Controller
#ed7d31 Service
#ffc000 DB(ORM)

少し脱線。レイヤー構造の役割に気付くことで、レイヤーの違反が気になるようになります。

  • FormオブジェクトをServiceに渡してしまう。
  • SessionオブジェクトをServiceに渡してしまう。

悩みましたが、腑に落ちる方法で解決出来るようになったのは、かなり後でした。
良い解決策をお探しの方は「クリーンアーキテクチャ」等を読むと良いかもしれません。

4. 共通化のせいで"処理で分割"に戻る

image.png

#4472c4 Controller
#ed7d31 個別っぽいSevice
#5b9bd5 共通Service
#ffc000 DB(ORM)

処理の共通化を強く考えはじめます。

SOLID原則等も何となく知り、「単一の責務」は分かるのですが、ピンと来ません。
共通処理という一つの責務?みたいに、まとめてしまうコードになりました。

5. InterfaceでDIしたけど何の意味があるかわからない

image.png

#4472c4 Controller
#ed7d31 個別っぽいSevice
#70ad47 Interface
#5b9bd5 共通ServiceImpl
#ffc000 DB(ORM)

DIを知ったきっかけで、Interfaceを利用し始めます。
実装クラスの前に無駄にメソッドだけが定義されたクラスが挟まる。というイメージしか持てません。

テストのし易さで無理やり納得してました。

6. Interfaceも相互作用のオブジェクトだと認識する

image.png

#4472c4 Controller
#ed7d31 個別っぽいSevice
#70ad47 Interface
#5b9bd5 共通ServiceImpl
#ffc000 DB(ORM)

利用側の視点が持てると、Interfaceもオブジェクトの一つだと認識できるようになります。

コードへの認識が大きく変わります!

ドメイン駆動設計の「Repository」の典型的なDIPパターンでイメージを掴む方も多いですかね。
私は「インタフェース指向設計」というマイナーで少し古い本で理解しました。

7. 全体の流れを意識出来ようになる

image.png

#ed7d31 UseCase
#70ad47 共通デカいInterface
#AACCCC 流れとして再認識してみる
#fbe5d6 処理の流れを組む様々なオブジェクト群が必要

絵はふわっとしてるので、次も一緒に見たいほうがいいかも。

ユースケースシナリオ等の要求仕様や、処理の全体の流れを意識したコードになります。
全体の流れを意識しつつ、オブジェクトを組み合わせていくというイメージが持ち始めます。
このイメージがあると、共通処理でまとめて無理やり分割してたことが、クラスの歪みの原因だと気づきます。

オブジェクト指向分析/設計系の知識も必要になります。まんまの「ユースケース駆動開発実践ガイド」がお勧めです。「オブジェクトデザイン」のステレオタイプもおすすめです。

8. 責務を意識したクラス分解(オブジェクト指向設計)

image.png

#ed7d31 UseCase
#fbe5d6 処理の流れを組む様々なオブジェクト群が必要
#70ad47 Interfaceを利用したオブジェクト
#5b9bd5 独立した小さなオブジェクト
#a260bf 本当に必要だった共通オブジェクト

オブジェクトの責務を意識した「小さく独立したクラスの重要性」のイメージを持つと、オブジェクトを組み合わせつつ全体の流れを作るという設計ができるようになります。

表現のためにクラス構造を変えるという手法も必要になり、DIPやポリモーフィズム等のオブジェクト指向設計を自然に活用したクラス分割が始まります。前段階の7に至る時点で、実はこのイメージも必要な気がします。

8. 2. 並び変えただけ

image.png

#ed7d31 UseCase
#CCAd81 処理の流れを叶えるための様々なオブジェクト群
#70ad47 Interfaceを利用したオブジェクト
#5b9bd5 独立した小さなオブジェクト
#a260bf 本当に必要だった共通オブジェクト

流れっぽく並べ替えただけです。

9. Web MVCを再統合して

image.png

#4472c4 Controller
#ed7d31 UseCase
#70ad47 Interfaceを利用したオブジェクト
#5b9bd5 独立した小さなオブジェクト
#a260bf 本当に必要だった共通オブジェクト
#ffc000 DB(ORM)

せっかくの絵なのでWeb MVCと統合して、それっぽくしてみました。
このレイヤ分解が正解という意図はなし。

10 おまけ 実はコードの構成は変わってない

image.png

image.png

レイヤ視点でのコード構造的には実は何も変わっていません。
まさに、認識によってコードの見え方が変わっているだけなのです。

おわり

プログラミングのコードは、ぱっと見で構造的に理解しても、認識の違いによって大きく意図が変わってしまうことが多々あります。デザインパターンなどまさにそれですね。
逆手に取ってフィットアンドギャップに利用したのがドメイン駆動設計だと考えると、それが面白い試みだなと気づかされます。
ただ、この認識の違いこそが、オブジェクト指向プログラミングの学習の難しさに繋がっているのかなと思い付き、記事を書いてみました。

イメージだけにイメージが伝わると幸いです。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?