今回のテーマは「デザインパターン」です。デザインパターンとはクラス設計における定石集で、全部で23パターンあり、それぞれに特徴があります。中でもよく利用されるのはTemplate MethodパターンとStateパターンですが、SingletonパターンやCompositeパターンなどもよく利用されます。今回はTemplate MethodパターンとStateパターンについて、前回解説した例題とクラス図を使用して解説します。 クラスⅠ製品は承認又は認証不要であるため、設計施設の登録は不要。 経過措置対象品目(旧法において設計開発管理の適用を受けていない医療 機器)であっても、当該品目の設計を行う施設の登録は必要。 … 実際の仕事現場では、資格を持たない機械設計者が多く活躍しています。資格がなくても機械設計はできるのです。設計知識を積極的に学ぶ機会を設けるために資格取得を目指すことは良いことですが、資格取得が目的になってしまうと本末転倒になることもあります。 インターフェースを利用することにより、メソッドの処理内容が異なるプログラムを交換可能な作りにできます(インターフェースを使った交換可能な作りは、次回以降のデザインパターンの中で説明します)。この文章をクラス設計します。クラス設計は、まず文章からクラス候補となる名詞を拾っていきます。「A社」「社員」「鈴木」「佐藤」「高橋」がクラス候補になりそうです。インターフェースを使用すればクラスを交換できる作りになるため、is-a関係よりhas-a関係、言い換えると継承より処理の委譲ができる包含が汎用性、拡張性の高い疎結合な作りになります。継承と包含のどちらでも良い場合は包含をお勧めします。「A社には社員として鈴木さん、佐藤さん、高橋さんがいます。3人は朝起きてから身支度をして、通勤電車に乗り、現場で仕事をします」まず、継承(is-a関係)で考えてみましょう。「ハンドルは車の一種である」。文章として違和感があるので、どうやら現実世界のモノの関係に沿っていないようですね。次にクラス間の関連性について解説します。クラスの関連性とは、文字通り「クラスとクラスがどのような関係性を持っているか」ということです。次回はTemplate Methodパターンなど、デザインパターンについて解説します。メソッド候補である「身支度をする」「通勤電車に乗る」「現場で仕事をする」の動詞もクラス図に反映します。いかがでしたか。今回はクラスの属性と操作やクラス間の関連性(is-a関係とhas-a関係)をもとに、オブジェクト指向でのクラス設計について解説しました。しかし、それが得策ではないのは、実際の業務では仕様変更や機能追加、障害対応などが頻繁に発生するためです。クラス設計を行わずにクラス1つで全ての処理を行おうとした場合(クラスが1つというのは極端な例ですが)、当然ながらクラスのソースコード量は肥大化し、if文などの条件分岐もコードのあちこちに現れ、非常に可読性が落ち、結果として修正工数が膨らむという事態になります。会社員クラスなら属性は「社員名」「社員番号」「所属」など、操作は「出社する」「退社する」「仕事をする」などです。一方のhas-aは「A has a B.」、つまり「AはBを含む」という包含関係を指します。「身支度」「通勤電車」「現場」「仕事」も名詞ですが、これらは「身支度をする」「通勤電車に乗る」「現場で仕事をする」というように、どちらかというと動詞になりそうです。クラス間の関係性は大きく「is-a関係」と「has-a関係」の2つに分けることができます。クラス設計ではクラス間が疎結合で依存性のない関係性を目指しますが、依存性のない、つまり汎用性、拡張性の高い疎結合な作りはis-a関係よりhas-a関係になります。包含は継承のように親クラスの機能をそのまま利用はできませんが、包含したクラスに処理を委譲することで機能を使う(処理を任せる)ことができます。では、車クラスとハンドルクラス、タイヤクラスは継承(is-a関係)と包含(has-a関係)のどちらでしょうか。したがって、クラス設計をしっかりと行い、クラス間の結合度を下げたり、プログラムの再利用性を高めたりしてプログラムを修正しやすく、またバグの原因も特定しやすくするべきです。さて、これで一応クラス図は完成しましたが、これを何も考えずにコーディングすると、まず「鈴木」「佐藤」「高橋」の各クラスはそれぞれ「身支度をする」メソッドを呼び、次に「通勤電車に乗る」メソッドを呼び、最後に「現場で仕事をする」メソッドを呼ぶ作りになります。ちなみに、この問題はデザインパターンのTemplate Methodパターンで解決します。デザインパターンとは「定石となる手法をパターン化したもの」です。先人たちの知恵ですね。例えば、車クラスとカローラクラス、プリウスクラスがあるとします。この3つのクラスは継承(is-a関係)にすべきでしょうか。包含(has-a関係)にすべきでしょうか。クラスの属性と操作の話に戻りますが、例えば車クラスについて考えてみます。車が持つ属性は「色」「乗車定員」「排気量」など、操作は「前に進む」「止まる」「クラクションを鳴らす」などが考えられます。継承は親クラスの機能をそのまま使えるようになるため非常に便利です。例題のように「class A extends B」とした場合、子クラスであるAは親クラスであるBのフィールド(変数)とメソッドにアクセスできるようになります。継承は非常に便利ですが、それ故に欠点があります。親クラスと子クラスの間にはインターフェースを挟むことができず、密結合な関係になってしまうことです。親クラスを修正すると、その影響が子クラスにも及ぶことになり、親クラスと子クラスが一心同体のような作りになってしまいます。属性とはクラスのインスタンスが持つデータ定義のことです。クラスのフィールド、つまり変数にあたります。操作とはクラスのインスタンスの振る舞い(機能)のことです。クラスのメソッドにあたります。この次々にメソッドを呼ぶ一連の処理を各クラスに任せるのは冗長な感じを受けます。一連の処理の流れをどこかに任せられればコードがすっきりしますよね。また、包含するのはクラスではなく、包含するクラスが実装するインターフェースにすることで疎結合の作りにできます。インターフェースはメソッドの定義だけなので、ロジックはインターフェースを実装したクラスに書くことになります。さて、ここまでの解説でクラス設計がある程度理解できたと思いますので、今度は例題でクラス設計に挑戦してみましょう。なお、A社は会社の一種ですが、例題文には会社という言葉は登場しませんでした。そこで「会社」もクラスとして登場させ、A社と継承関係にします。インターフェースは、下の例のようにロジックを記載しません。メソッドを定義するだけです。では「社員」と「鈴木」「佐藤」「高橋」はどうでしょう。「鈴木は社員(の一種)です」「佐藤は社員です」。したがって、継承関係です。今回のテーマは「クラス設計」です。クラス設計とは、設計書などに記載されている要件からクラス候補を抜き出し、クラスの属性と操作を決めて、クラス間の関連性を設計することを指します。ちなみに、継承より包含の方が疎結合になるからといって、やみくもに包含にすれば良いという訳ではありません。継承(is-a関係)は「AはBの一種である」ですから、当てはめると「カローラは車の一種である」「プリウスは車の一種である」。言葉として成り立ちますよね。したがって、車クラスとカローラクラス、プリウスクラスは継承関係となります。クラスを作った担当者がチームにいれば工数が膨らむ程度で済みますが、担当者がチームから離れた場合、引き継いだ社員がソースコードを正しく理解できずに、バグを埋め込んだまま納品してしまう可能性もあります。このように、オブジェクト指向は現実世界のモノの関係に沿ってクラス設計をします。「オブジェクト指向」という名前だけ聞くと何やら難しい気がしますが、私たちが普段見ている世の中の作りそのままなので、むしろオブジェクト指向は取っつきやすい考え方です。メソッドは動詞を拾っていくので、「身支度をする」「通勤電車に乗る」「現場で仕事をする」はメソッド候補になります。次に包含(has-a関係)で考えてみます。「AはBを含んでいる」ですから、当てはめると「車はハンドルを含んでいる(持っている)」「車はタイヤを含んでいる(持っている)」。こちらは文章としてしっくりくるので、包含(has-a関係)ですね。まず、「A社」「社員」「鈴木」「佐藤」「高橋」の5つの名詞をクラス設計していきましょう。前述したように言葉にすれば分かりますね。「A社は社員を含んでいます(社員がいます)」。したがって、包含関係となります。is-aは「A is a B.」、つまり「AはBの一種でAクラスからBクラスを派生する」というクラス間の継承関係を指します。ちなみに、クラス設計をしなくてもプログラムは動きます。例えばクラスを1つだけ用意し、処理の全てをそのクラスに書いても期待する動きをします。 日本で取得できる資格の概要をほとんど網羅。国家資格、公的資格、民間資格の資格の種類のほか、独立できる資格、情報処理の資格、福祉系の資格、地球を守る資格などの資格の分野で取りたい資格をすぐに見つけることができます。資格をとってライバルたちに差をつけよう! Javaの資格は数多く存在するが、ここではOracle社が提供している資格についてを紹介する。Javaの資格で有名なのは、Oracle社が提供している資格だ。 建物が地震などの災害で倒壊するのを防ぐために欠かせない仕事が「構造設計」です。これは、建物の見た目ではなく、中身をデザインする仕事です。ここでは、構造設計がどのような仕事なのか、そして構造設計者となるために必要な資格等をご紹介します。 ★「設計早期クラス 無料特別公開セミナー」動画配信します! 詳細はこちら ⇒ ★受講生の皆様へ 最終講義では平行定規を使用しますが、第1~4回は不要です。 どうぞよろしくお願いいたします。 ★定員に … Stateパターンによって「鈴木さんはフェーズによって仕事の内容が変わる」という要件は満たしましたが、これは「スナップショット的な考え」でしかありません。スナップショット的な考えとは、「時間的な断面を切り取った状態の考え」、つまり「今回の要件を満たせばOK」という考えです。「A社には社員として鈴木さん、佐藤さん、高橋さんがいます。3人は朝起きてから身支度をして、通勤電車に乗り、現場で仕事をします」これでも要件を満たして動作しますが、if文を使うとフェーズの条件が増えた場合に、if文の分岐も増やさないといけません。実行すると、コンソールには期待通り、以下のように表示されました。上のサンプルのように、処理の内容は違っても処理の流れは一緒のような状況はプログラミングで割と起こるかと思います。何も考えないで作ると同じような処理の流れのロジックがあちこちに登場する冗長なプログラミングになりますが、Template Methodパターンを適用すると親クラスに処理の流れを記したテンプレートメソッドを用意し、そのテンプレートメソッドからは次々にメソッドが呼ばれていくため(テンプレートメソッドから呼ばれるメソッドをフックメソッドという)、サブクラスはフックメソッドをオーバーライド実装するだけとなります。オーバーライドとは、親クラスで定義しているメソッドをサブクラスで再定義(上書き)することを言います。親クラスで定義しているメソッドの振る舞いをサブクラスでは異なる振る舞いにしたい場合に使用します。親クラスで定義しているメソッドが抽象メソッドの場合は、強制的にサブクラスでオーバライド実装することになります。ちなみに、社員が増えた場合は他のプログラムには一切手を付けることなく、抽象クラスである社員クラスを継承したクラスを追加するだけです。フェーズが増えて仕事内容が増えた場合は、フェーズインターフェースを実装したクラスを追加するだけです。こちらも他のプログラムの修正は一切不要です。プログラムに手を入れるということは、そのクラスを再テストしなくてはいけなくなるため、非常に効率が悪いです。効率が悪いだけならまだしも、正しく動いているものを修正することでバグを生み出してしまうなど、if文の分岐は数が多いと可読性が低下します。Stateパターンとは、文字通りモノについての「状態」をクラスで表現します。状態によって振る舞い(処理)が異なることがあります。例えば、挨拶は時間帯によって変わります。朝であれば「おはよう」ですが、昼は「こんにちは」になり、夜は「こんばんは」になります。鈴木クラスからフェーズインターフェースには菱形のない実線だけで線を引いていますが、前回解説した包含は菱形の付いている実線で表します。包含は集約とも言い、「全体と部分」の意味を持つ場合に用いため、今回の「鈴木」と「フェーズ」は関係があるという意味の「関連」にします。関連は実線だけで表します。いかがでしたか。今回はデザインパターンの中でもよく使われている基本的なTemplate MethodパターンとStateパターンについて解説しました。こちらも実行して、期待通りの結果になるかコンソールを確認してみましょう。あとは、鈴木クラスの「現場で仕事をする」メソッドが状態(フェーズ)の違いで異なる振る舞いをしてくれるかですね。一日の行動()メソッドがテンプレートメソッドです。テンプレートの文字通り、処理の流れのひな型を定義するので、サブクラスは処理の流れを考える必要はなく、メソッドの振る舞いを実装するだけになりました。何も考えないとクラス図はそのままで、鈴木クラスの「現場で仕事をする」メソッドにif文でフェーズを分岐するプログラムを作ることを考えるでしょう。このクラス図は「「鈴木」「佐藤」「高橋」の各クラスがそれぞれ「身支度をする」メソッドを呼び、次に「通勤電車に乗る」メソッドを呼び、最後に「現場で仕事をする」メソッドを呼ぶ作りになっています。それでは試してみましょう。例題ではフェーズの状態によって仕事の内容が変わるので、仕事内容の変化はif文ではなく「フェーズ」というインターフェースを用意します。フェーズインターフェースには「仕事をする」宣言を定義し、交換可能な作りにします。一度、ここまでで期待通りに動作するかテストクラスを作って確認してみましょう。その前に、日本語で書いたクラスを論理モデルから物理モデルに進めて英語に直します。ちなみに、状態によって振る舞いが変わる場合はStateパターンですが、この「状態によって振る舞いが変わる」が例題の「フェーズによって仕事の内容が変わる」に当てはまり、Stateパターンの「状態」が例題の「フェーズ」に当てはまるわけです。挨拶は「おはよう」で固定されているわけではなく、状態(この場合は時間帯が状態といえます)によって振る舞いが異なります。このような場合にStateパターンを適用すると個々のクラスで状態を表現するため、分岐が消えてシンプルな作りになります。上手いこと「現場で仕事をする」メソッドの振る舞いが変わりましたね。各クラスはそれぞれ身支度の仕方や通勤電車の種類、仕事の内容は違いますが(例えば「鈴木」クラスの「身支度をする」メソッドは「洗面所で顔を洗う」、「通勤電車に乗る」メソッドは「京急線を使う」だが、「佐藤」クラスの「身支度をする」メソッドは「シャワーを浴びる」、「通勤電車に乗る」メソッドは「山手線を使う」など)、各メソッドの振る舞い(内容)は違っても「身支度をする」メソッドを呼んで「通勤電車に乗る」メソッドを呼び、最後に「現場で仕事をする」メソッドを呼ぶ、処理の流れ(順番)は一緒です。プログラムで言うとインスタンス変数ではなく、メソッド内で定義するローカル変数で対象のクラスを表します。依存はクラス間の点線で表します。ちなみに、継承、集約、関連以外に「依存」というものもあります。依存は関連よりもクラス間の依存度が低く、協調の長さが短い場合に用います。それではダメで、あくまで全体、このプロジェクトの機能はどうなっていくのだろうと、もっと大局的に見ていかなければなりません。したがって、クラス図は最初に挙げた鈴木クラスからフェーズインターフェースに関連を持ったクラス図ではなく、どの社員も仕事内容が切り替わるように、社員クラスからフェーズインターフェースに関連を持つ以下のクラス図の方が優れた設計と言えます。鈴木クラスの「現場で仕事をする」メソッドは、次のようになります。仕事内容の変化はif文ではなく、受け取ったインスタンスによって異なる振る舞いをする、まさにポリモーフィズムで変えています。クラス図で表すと下図のようになります。クラス設計にしても、確かに「鈴木はフェーズによって仕事の内容が変わる」という今回の要件は満たしましたが、「仕様変更や次のフェーズでは佐藤クラスや高橋クラスにも同様にフェーズによって仕事の内容が変わるという要望が発生するかもしれない」と察知しないといけません。これは、デザインパターンの処理の流れが一緒で振る舞いだけが異なる場合に有効なTemplate Methodパターンが適用できそうです。Template Methodパターンとは、親クラスで処理の流れ(アルゴリズム)を実装し、処理の流れで順次呼ばれるメソッドを抽象メソッド(定義だけでサブクラスに処理を強制的に実装させるためのメソッド)として宣言します。親クラスで宣言した抽象メソッドの具体的な処理はサブクラスで実装します。フェーズインターフェースを実装したクラスは、状態(フェーズ)ごとの具体的な振る舞い(仕事内容)を記述します。Template Methodパターンを適用すると、サブクラスはメソッドを順番に呼ぶ必要はありません。順番に呼ぶ責務は親クラスになります。そのような要望があった時に都度クラスやプログラムを変更していたのでは工数が掛かって仕方がないので、フェーズによって鈴木クラスの仕事内容が切り替わるのなら「今のうちに他のクラスも同様に切り替わる作りにしよう」と考えましょう。「このうち鈴木さんはフェーズによって仕事の内容が変わります。設計フェーズでは設計書の作成、プログラムフェーズではプログラムの作成、テストフェーズではテスト計画書の作成をします」追加された例題をもう一度よく読んでみます。「鈴木さんはフェーズによって仕事の内容が変わります。設計フェーズでは……」となっています。冒頭で幾つかよく使用されるデザインパターンを挙げましたが、このケースではその中で状態によって振る舞いが変わる場合はStateパターンが適用できそうです。今回のテーマは「デザインパターン」です。デザインパターンとはクラス設計における定石集で、全部で23パターンあり、それぞれに特徴があります。中でもよく利用されるのはTemplate MethodパターンとStateパターンですが、SingletonパターンやCompositeパターンなどもよく利用されます。今回はTemplate MethodパターンとStateパターンについて、前回解説した例題とクラス図を使用して解説します。