オブジェクト指向プログラミングを行おう

プログラミング
スポンサーリンク

はじめに

こんにちは。なたでです。

 

みなさん、オブジェクト指向をご存知ですか。

学生の時の授業でJavaを勉強して以来、プライベートではオブジェクト指向を心がけるようにしています。しかし、実際にデザインパターンなどを本を使って真剣に勉強したわけではない上、すでにオブジェクト指向で作られたライブラリの延長線での設計を行っているだけで、一から真剣に作ったことがあるのか、正しく設計ができるのかと言われると、自信をもってYesとは言えません。というわけで最近は、仕事でも通用するようにプロとしてオブジェクト指向の勉強を行なっています。

そこで今回は、これまで勉強した内容を踏まえて設計方法をまとめていきたいと思います。

なお本記事は、オブジェクト指向の言語やライブラリを使用したことがある、デザインパターンという単語は聞いたことがあるが勉強はしたことがないという人をターゲットとしています。

本の紹介

気になった本を買って勉強中です。まだ完全に読破しておりませんが、上の「オブジェクト指向のこころ」は良書となっております。

オブジェクト指向の入門用として購入
オブジェクト指向の実戦用として購入

オブジェクト指向を考える

設計を始める前に

オブジェクト指向の設計をいざ始めようとする前に、事前に知っておいたほうよい知識があります。

  • UML図
  • デザインパターン

※これ以外のことも覚えた方がいいとは思いますが、現状2点とします。まだ私自身も学習中であり今後増えていく可能性があります。

UML図

オブジェクト指向の設計を行う場合、理解しやすいように図を使って設計を行うことがあります。そこでUML図が重要になります。

UML図は、Unified Modeling Languageの頭文字であり、統一モデリング言語と呼ばれておりISOで標準化されています。つまりUML図を使うことで、共通した意思疎通が行うことができるのです。

自分一人しか使うことがないのであれば、適当な図でもよいかもしれません。ただ、せっかく図を書くなら洗練された機能を持つ、みんなが読めるUML図の方が断然良いのです。

UML図の例

UML図は、いろいろな図があり、構造図と振る舞い図の2種類に分けられます。今回はその中でも、「オブジェクト指向のこころ」の中で少しでも触れていた図を紹介します。太字になっている部分はさらに私なりに重要だと思っている図となります。

  • 構造図
    • クラス図
      • 設計工程で利用する図。仕様の説明に適する。
    • 配置図
      • 配備工程で利用する図。モジュールの配備位置を規定する。
  • 振る舞い図
    • ユースケース図
      • 分析工程で利用する図。概念を考える前の要求の説明に適する。
    • アクティビティ図
      • 分析工程での利用、実装説明に適する。フローチャートに似た図であり、フローチャートより高機能。
    • シーケンス図
      • 相互作用図の一種で最も有名な図。特定のオブジェクトのやり取りの洗い出しに利用する。機器間の通信の流れなどもこのシーケンス図を使うことが適する。
    • ステートマシン図
      • オブジェクトに状態を持たせて動作を変えたり、振る舞いの洗い出しで利用する図。状態遷移図とよばれる。
UML図を描くツールについて

図を作る際は、PlantUMLというツールを使うことをおすすめします。PlantUMLはソースコードのようなテキストを記載することで、図を作成できるツールです。そのため修正をした際に、差分の比較が行えやすいといったメリットがありますし、データ量も小さいためソースコード管理ツールで管理もしやすいです。

PlantUMLは、Visual Studio Code、WordPress、Redmine、Word用のプラグインなどが存在するため、どのような環境でも作成/利用することができます。

UML図の正確性について

UML図は正しい書き方が決まっていますが、正確に正しい書き方をする必要があるかというと、そんなに気にする必要はありません。ただ、誤った認識を相手に与えてしまわないような書き方をしないようには、注意が必要です。このことは、私の考えではなく「オブジェクト指向のこころ」にも記載されています。

UML図を書くツールが用意できない場合に、エクセルなどで書かなければいけない場合もあるかもしれません。そういう場合は、上記のことをふまえて、伝わるように書きましょう。

デザインパターン

デザインパターンとは、オブジェクト指向でクラスを扱った設計のうち、定石なパターンに名前をつけたものです。

おそらく皆さんは何かをプログラムするにあたって、特定の同じような作りをすることがあるかと思います。それらの多くには名前がついており、この名前とそのパターンを覚えるということが、オブジェクト指向の設計の前準備となるわけです。

なぜ、すでに自分がそのような作り方を知っているのにも関わらず、誰かが名前をつけたパターンを覚え直す必要があるのか疑問に思う方もいるかと思います。私も以前はそのような考えであったため、わざわざ覚えることもないのだろうと思っておりました。しかし、実はデザインパターンを覚えるという目的は、『設計手法を知る』という目的ではないのです。

デザインパターンを覚える目的は何でしょうか。これもUML図と同様に、意思疎通という目的が大きいです。また、名前をつけることで覚えた設計手法を頭の中で整理しやすいといったメリットもあります。

名前をつけて意思疎通することがそんなにも重要なのでしょうか。例えば、『「A」と書いてある画像を、マウスの左を1度押して、300ms以内に離し、500ms〜1秒にもう1度押して、300ms以内に離してください』といって伝わりますでしょうか。伝わるかもしれませんが『アイコン』や『ダブルクリック』という名前(概念)を知っていれば、『Aのアイコンをダブルクリック』だけで、操作を伝えることができます。これは単純な操作に名前がついた例ですが、もちろん長い手順に名前がついているものもあります。そういった場合に正しく説明することはできるでしょうか。ソフトウェアを設計するにあたって、他人にこのような設計はどうと説明する際に、概念に名前が付いていないと、伝えること自体が大変なのです。そんなときにデザインパターンを知っていれば、『これは〜パターンで設計します』と一言で済みます。

なぜパターンなのか?

ソフトウェアのデザインパターンを考えた人はGoFと呼ばれる4人組なのですが、彼らがパターンを生み出すにあたりChristopher Alexanderの功績が大きいとされています。Alexanderは、建築家なのですが「品質は客観的なものか?」という疑問をいだき、その答えを模索していました。建築物はそれぞれ形は全く同一ではないのにも関わらず、優れた設計手法があることに気がつき理解しました。そこで同じ問題を解決するために設計した構造物に目を向け、パターンという概念を作りました。その考えをソフトウェアに持っていくことで、品質の良い設計を行えるようにしたのです。

詳しい説明は「オブジェクト指向のこころ」を読むとよいです。

代表的なパターン

全てのパターンは覚える必要はありませんが代表的なパターンを紹介し、そのパターンの概要とメリットを記載したいと思います。

  • Facedeパターン(ファサードパターン)

いくつかまとまった順序で行う処理を、1つの関数から呼び出しをすることで、その呼出を1度だけ呼べば済むようになるといったパターン。

メリットとしては、中で何をやっているか知らなくても利用ができるようになることや、呼び出し側に影響を与えずに、中の処理を効率よく改善が行える。

  • Adapterパターン(アダプターパターン)

同一のインターフェイスXを持つオブジェクトを扱うシステムに、全く別のインターフェイスを持つ変更不可なオブジェクトYを使用したい場合に、そのインターフェイスXを持ち内部でオブジェクトYを操作するラッパー的なオブジェクトを作るといパターン。

メリットとしては、インターフェイスXしか扱えないオブジェクトAから、全く別のインターフェイスYをもったオブジェクトを、インターフェイスXで扱えるようになるため、オブジェクトAの修正を行わなくても、いろいろな機能を追加していける。

  • Strategyパターン(ストラテジーパターン)

とあるクラスXに対して、機能を拡張したい際に、クラスXを拡張してクラスYを作るという考えではなく、クラスX内に、クラスYを拡張させるための流動的要素を見つけ出し、その要素を切り出して変更できるようにする。このようにすることで、無駄なクラス拡張を防ぐというパターン。

メリットとしては、上記の説明にあるとおり、無駄なクラス拡張を防ぐことができる。

設計を始めてみる

オブジェクト指向を考えた設計をする場合は、次のようなステップで設計を行います。特に概念と仕様(クラス図)を考える部分が重要となります。

  1. 概念
    • 登場するオブジェクトを考えて、責任を考える
  2. 仕様
    • オブジェクトに対してインターフェイスを考える
  3. 実装
    • 内部の実装コードを考える

概念について

基本的なオブジェクトを考えます。オブジェクトは、何かの目的をもって存在し、責任を持つように設計します。責任を持つという観点から、要求定義の仕様を満たすだけではなく、責任という観点から予備的な設計を行うこと、仕様変更に耐えられる汎用的な設計が行えます。

注意点として、オブジェクトの設計時は、内部の設計は気にしなくてよいです。何を実行するのかに着目するというのが、新たなオブジェクト指向の考え方ということで本に紹介されています。

本には記載がされていませんでしたが、それらのオブジェクトがどのように振る舞うのか簡単なステートマシン図で説明するとよいと思われます。

仕様について

オブジェクトが持つインターフェース及び、オブジェクトの細分化、クラスの構造を考えます。クラス図を使り、設計を行います。

流動的要素の洗い出し

概念がねられた時点で、その機能や問題の中で流動的要素を見つけながら、再設計指定及びインターフェイスを考えていくとよいと思われます。流動的要素を見つけるために、「Coplineの共有性分析/可変性分析」を行って洗い出しをします。

クラス継承よりも集約

機能の仕様を考える際に、クラスの継承を利用することを考えたりすることもあるかもしれませんが、クラスの継承よりも、集約を意識した設計が重要です。

 

 

少し執筆が停滞してるので、中途半端ですがいったんここまでで投稿します。

コメント

タイトルとURLをコピーしました