保守運用コストを軽減。開発手法「デザインパターン」の利用例をご紹介
 
Webサイト・システムを作って満足していませんか?
Webサイト・システムは作って終わりではなく、作ってからがスタートです。
公開後も、バグ対応や機能開発・関連システムとの連携対応など繰り返し保守運用を行うことが必要となります。
特に企業の基幹となる業務を管理する「基幹システム」では、10年、20年、さらに長期に渡って保守開発を続けることも珍しくありません。
公開後もバグが発生しにくいつくりになっているWebサイト・システムの状態を「保守性が高い」状態であると言います。
長期にわたる保守を見据え初期開発の時点から保守性を高めないと、Webサイト・システムの品質を保つことが難しくなります。
例えば「スパゲッティコード」と呼ばれる煩雑で読みにくいソースコードや、影響調査が困難なソースコード、改修の影響が広範囲に広がってしまうソースコードを書いてしまうと、保守開発の際に新たなバグが発生するリスクが高くなってしまいます。
保守性が低いことはすなわち、事前の影響調査やテストなどに多くの工数を費やすことにつながる、ということです。低コスト・高品質の保守開発を実現するためには、保守性の高いシステムを開発する必要があります。
Webサイト・システムの保守運用を容易にし保守性が高い状態とするためには様々な手段があり、その一つに設計ノウハウを再利用しやすい形にパターン化する、デザインパターンという手段があります。
この記事では保守運用の一例として、デザインパターンの説明や使用例などを紹介していきます。
この記事の執筆者
東京のWeb制作会社 株式会社サービシンク エンジニア
このコラムでは、制作実績でご紹介できないようなWeb技術の活用例をご紹介し、「サービシンクは何を得意としているの?」 「サービシンクに依頼すると何をしてくれるの?」という疑問を解決いたします。
詳細のサービス内容は下記のリンクからご確認ください。
サービス|ホームページ制作・Web制作会社 サービシンク(東京)
 
 
目次
 
保守性の高いWebサイト・システムを作るには
そもそも保守運用とは?という方は下記のブログも是非ご覧ください。
【保守運用とは?】Webサービスの成果を維持・向上させる方法
保守運用をしていくためには、「保守性の高いコード」を書いていくことが必要です。
「保守性の高いコード」は例えば下記のような特徴を持っています。
- 可読性が高い
- 変更に強い
上記のような保守性の高いコードを書くために重要となるポイントをご紹介します。
 
可読性の高いコードを書く
下記を心がけることで、可読性の高いコーディングとすることができます。
- 適切なメソッド名や変数名にする
曖昧な名前や極端に長い名前を避け、名前をみて内容が予測できることが理想です。また、プロジェクト内での命名規則がある場合は規則に従い、英語あるいはローマ字など適切に命名しましょう - 適切なコメントを記述する
ソースコードをそのまま日本語にしたようなコメントではなく、処理の概要や、補足をするコメントにする必要があります - マジックナンバーを埋め込まない
マジックナンバーとは、ソースコード内で直に記述された数値で、その意味や意図が記述した本人以外には自明でないものを指します
マジックナンバーのような記述の仕方はなるべく避け、定数や列挙型などの機能を用いて、コード中には定数名などの形で値を参照するようにしましょう - わかりやすいロジックを心がける
保守開発の際にソースコードのロジックを読み解くことが多いため、if文のネストが多すぎる、goto文で制御があちこちに飛ぶ、といったロジックが分かりにくくなるような書き方は避けましょう。
また、コーディング規約に従いながら、コードを書く必要があります。
変更に強い設計にする
変更に伴う影響範囲を限定しやすくするための設計手法を取り入れると、変更に強い設計にすることができます。
設計手法には、「データ中心アプローチ」「プロセス中心アプローチ」「オブジェクト指向アプローチ」といった種類があります。
「データ中心アプローチ」とは業務で使われるデータを明確化し、それに従ってシステム機能を設計する考え方です。
「プロセス中心アプローチ」とは業務手順やデータの流れに注目し機能要件を定めていくシステム設計の考え方でデータ中心アプローチの対義語として用いられます。
「オブジェクト指向アプローチ」に関してはデザインパターンの考え方を取り入れることで、変更に強い設計とすることができます。
ここではオブジェクト指向のデザインパターンについて紹介していきます。
デザインパターンに触れる前にオブジェクト指向について紹介します。
オブジェクト指向アプローチ、オブジェクト指向プログラミング(Object Oriented Programming)とは、プログラミングのアプローチ方法で、直訳すると「モノ指向」「モノ中心」になります。
ソフトウェアの保守や再利用をしやすくすることを目的にした技術です。
 
デザインパターンとは
「デザインパターン」は、Wikipediaでは下記のように定義されています
ソフトウェア開発におけるデザインパターン(型紙または設計パターン、英: design pattern)とは、過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、名前をつけ、再利用しやすいように特定の規約に従ってカタログ化したものである。(Wikipediaより)
つまり、よく出会う問題に対してのGOODな設計パターン集のことです。
デザインパターンと言ってもいろいろありますが、最も有名なものはGoF(Gang of Four)のデザインパターンです。「生成」「構造」「振る舞い」の3つに分類された、23のパターンがあります。
GoFのデザインパターンについて、それぞれどのようなパターンかの概要をご紹介します。
 
オブジェクトの生成に関するパターン
- FactoryMethodパターン
- 処理の概要を抽象クラス、具体的な処理内容を具象クラスに記述するデザインパターン。
- オブジェクトを生成するクラスと、そのオブジェクトを使用するクラスに分けて実装します。
- オブジェクトを生成するクラスはfactoryと呼ばれます。
- Singletonパターン
- インスタンスが一個しか作成されないようなクラスを作成するデザインパターン。
- singletonとは一枚札のことです。一枚札とはトランプの一組に唯一のカードです。Singletonパターンとは、このような唯一の存在を保証するためのパターンです。
- Prototypeパターン
- あらかじめ用意しておいた「原型」からインスタンスを生成するようにするためのデザインパターン。
- インスタンスを作成する場合は既存のインスタンスをコピーします。既存のインスタンスがプロトタイプとなります。
- Builderパターン
- 同じ作成過程で異なる表現形式の結果を得るためのデザインパターン。
- 抽象クラスのメソッドを利用し、組み上げることで複雑なものを作成します。
- AbstractFactoryパターン
- インスタンスの生成を専門に行うクラスを用意することで、整合性を必要とされる一連のオブジェクト群を間違いなく生成するためのデザインパターン。
- 抽象クラスを柔軟に組み合わせて大きな構造を組み立てたい時に使われます。
オブジェクトの構造に関するパターン
- Adapterパターン
- 他のシステムのインターフェースと自システムの架け橋となるクラスを作成するデザインパターン。
- adaptという単語は「適合させる」という意味で、adapterとは「適合させるもの」という意味になります。Adapterパターンは、インタフェースに互換性の無いクラス同士を組み合わせることを目的としたパターンです。
- Bridgeパターン
- Bridge、その名の通り橋渡しをするデザインパターン。
- 機能を実装するクラスと機能を利用するクラスに分けられます。
- 機能を利用するクラスは実際の処理を機能を実装するクラスに委譲します。
- Compositeパターン
- 容器と中身を同一視し、再帰的な構造を作るデザインパターン。
- 「容器と中身を同一視する」必要が生じる例として、ファイルシステムなどが挙げられます。 あるフォルダ以下のファイルやフォルダをすべて削除したい場合など、それがファイルなのかフォルダなのかを意識せずに、同じように削除できるパターンです。
- Decoratorパターン
- Decorateとは、英語で「装飾者」を意味する言葉で、飾り枠と中身を同一視することで、より柔軟な機能拡張方法を提供するデザインパターン。
- ある要素に対して飾り付けする処理を複数実装する場合に利用します。
- Facadeパターン
- 既存のクラスを複数組み合わせて使う手順を、「窓口」となるクラスを作ってシンプルに利用できるようにするデザインパターン。
- 機能を利用する側に複雑な処理を見せたくない場合に利用します。
- Flyweightパターン
- インスタンスを共有することでリソースを無駄なく使うことに焦点を当てたデザインパターン。
- オブジェクトが作成済みなら再びオブジェクトが生成されないようにし、実現するためのfactoryクラスを作成します。
- Proxyパターン
- 要求を代理人オブジェクトが受け取って処理するデザインパターン。
- 重い処理を行うクラスが存在し、そのクラスの代役を作ることが可能な場合に利用します。
オブジェクトの振る舞いに関するパターン
- Iteratorパターン
- 複数の要素を順番に取り出すためのクラスを作成するデザインパターン。
- Iteratorとは「繰り返す」という意味を持つ英単語で、「反復子」などと呼ばれます。
- TemplateMethodパターン
- 共通する処理を定義したスーパークラスをそれぞれのサブクラスが継承し、継承元から与えられたそれぞれの機能を実装し、さらに独自の処理を実装するデザインパターン。
- 抽象クラスがテンプレートとなります。
- Strategyパターン
- 問題を処理するロジック(戦略)について抽象クラスと具象クラスに分けるデザインパターン。
- Strategy とは英語で「戦略」を意味する言葉です。Strategyパターンを利用することで、戦略の切り替えや追加が簡単に行えるようになります。
- Visitorパターン
- Compositeパターン等で作成したデータ構造に対して処理を行うクラスを実装するデザインパターン。
- オブジェクトに動的に機能を追加するために利用します。
- ChainOfResponsibilityパターン
- Chain of Responsibility は、「責任の鎖」と訳すことができます。「責任」を負ったものが、「鎖」状につながれた状態をイメージさせるデザインパターン。
- 問題を処理するロジックに独立性を持たせたい場合に利用できます。
- Mediatorパターン
- 多数のオブジェクトの間の調整を行いながら処理をすすめる必要がある場合に利用すると威力を発揮するデザインパターン。
- 具体的な処理を複数のクラスの処理が複雑に絡み合う場合に利用します。
- Observerパターン
- 状態を観察するクラスと、状態の変化に合わせて処理を行うクラスに分け、観察するクラスは状態の変化の検知後、処理を行うクラスのメソッドを実行するデザインパターン。
- 状態の変化に合わせて処理を行う必要がある場合に利用します。
- Mementoパターン
- インスタンスのあるときの状態をスナップショットとして保存しておくことで、 その時のインスタンスの状態を復元することを可能にするものデザインパターン。
- Stateパターン
- オブジェクト指向設計では、モノをクラスとして表現することが多くあります。モノではなく、「状態」をクラスとして表現するデザインパターン。
- 状態に応じて複雑なロジックを実装する場合に利用します。
- Commandパターン
- 複数の命令毎にクラス化し、それらの命令クラスを束ねる抽象クラスも作成し、命令を利用するクラスは、その抽象クラスを利用するデザインパターン。
- 命令の具象クラスは、対象物を表すクラスに対して処理を行います。
- Interpreterパターン
- 「解析した結果」得られた手順に則った処理を実現するために最適なデザインパターン。
- 何らかのフォーマットで書かれたファイルの中身を、解析した結果に則って何らかの処理を行いたい場合に利用します。
 
デザインパターンの使用例
GoFのデザインパターンは具体的にどのように使われるのでしょうか。
23種あるGoFのデザインパターンすべての使用例をご紹介すると長くなってしまうため、その中から「TemplateMethodパターン」を取り上げ実例を交えながらご紹介します。
TemplateMethodパターンの使用例
異なる色のペンや、筆・マーカーなどを用いても同じ形式にする「テンプレート」になぞらえて、スーパークラスで処理の枠組みを決め、サブクラスで具体的な内容を定めるデザインパターンをTemplateMethodパターンと呼びます。
TemplateMethodのクラス図
- AbstractClassで抽象メソッドの宣言、TemplateMethodの実装
- ConcreteClassで抽象メソッドの実装
実際のコード
TemplateMethodパターン適用前
「コーヒーを作る」<?php class Coffee { public function makeCoffee() { echo 'コーヒーを作る。\n'; } public function boilWater() { echo'お湯を沸かす。\n'; } public function brew() { echo 'コーヒー豆を挽き、ドリップする。\n'; } public function pourInCup() { echo 'カップに注ぐ。\n'; } public function addContents() { echo '砂糖とミルクを足す。\n'; } public function makeDrink() { $this->makeCoffee(); $this->boilWater(); $this->brew(); $this->pourInCup(); $this->addContents(); } }
「紅茶を作る」
<?php class Tea { public function makeTea() { echo "紅茶を作る。\n"; } public function boilWater() { echo "お湯を沸かす。\n"; } public function brew() { echo "ティーバッグを浸す。\n"; } public function pourInCup() { echo "カップに注ぐ。\n"; } public function addContents() { echo "レモンを足す。\n"; } public function makeDrink() { $this->makeTea(); $this->boilWater(); $this->brew(); $this->pourInCup(); $this->addContents(); } }
見比べてみると同じ項目「お湯を沸かす」「カップに注ぐ」があります。これら重複する項目を共通化し、テンプレートとするのがTemplateMethodパターンです。
TemplateMethodパターンで書くと下記のようになります。
TemplateMethodパターン適用後
AbstractClass(抽象クラス)
// CaffeineDrink.php <?php abstract class CaffeineDrink { /** * 各クラスの共通の処理 * * @param string $drink_name */ public function drinkDetail(string $drink_name) { echo "【" . $drink_name . "を作る】\n"; } public function boilWater() { echo "お湯を沸かす\n"; } public function pourInCup() { echo "カップに注ぐ\n"; } /** * 各クラスによって異なる処理。抽象クラスとして定義 * 中身はサブクラスで実装 */ abstract protected function brew(); abstract protected function addContents(); /** * TemplateMethod */ public function makeDrink($drink_name) { //一連の動作を定義 $this->drinkDetail($drink_name); $this->boilWater(); $this->brew(); $this->pourInCup(); $this->addContents(); } }
ConcreteClass(具象クラス)
// makedrink.php <?php require_once 'CaffeineDrink.php'; class Coffee extends CaffeineDrink { /** * それぞれのクラス独自の処理のみを実装する */ protected function brew() { echo "コーヒー豆を挽き、ドリップする\n"; } protected function addContents() { echo "砂糖とミルクを足す\n"; } } class Tea extends CaffeineDrink { /** * それぞれのクラス独自の処理のみを実装する */ protected function brew() { echo "ティーバッグを浸す\n"; } protected function addContents() { echo "レモンを足す\n"; } }
実行結果
// client.php <?php require_once 'makedrink.php'; $coffee = new Coffee(); $coffee->makeDrink('コーヒー'); $tea = new Tea(); $tea->makeDrink('紅茶'); ------------------------------ 【コーヒーを作る】 お湯を沸かす コーヒー豆を挽き、ドリップする カップに注ぐ 砂糖とミルクを足す 【紅茶を作る】 お湯を沸かす ティーバックを浸す カップに注ぐ レモンを足す
重複する項目を「抽象クラス」として共通化することにより、「具象クラス」で呼び出す処理のみを行えばよくなり、コードを簡略化することができました。
また、もしこの実装に共通化した親クラスを利用できる「ココアを作る」を足すとなった場合でも、ココアのための独自の処理を「抽象クラス」に追加し「具象クラス」で呼び出すコードを書けばよいため、あとから入った変更であってもコードを複雑にせず、簡潔に追加することが可能です。
 
デザインパターンのメリット・デメリット
実例でご紹介したように、デザインパターンの手法を取り入れることには以下のようなメリットがあります。
- 保守性を高めることができる
- ソフトウェアの変更が簡潔にできるようになる
- コードの内容が理解しやすくなる
- チーム・開発者同士のコミュニケーションが円滑になり、時間的コストを減らすことができる
反対に、デザインパターンの手法を取り入れることのデメリットは
- デザインパターンを理解していない開発者だと対応ができない
- 複雑ではない開発には向かない
(上記で挙げたTemplateMethodパターンでいうと、共通処理が「お湯を沸かす」しかないコーヒーとカップラーメンに適応した時、ほとんど共通化できないのに親クラスが無駄に1つ増えてしまいます。
デザインパターンは例えば検索項目が多いWebサイトや機能の多いシステムなど、ある程度複雑な場合などに適用するのが良いでしょう。)
 
開発段階から公開後の運用を見据えることで運用コスト・負担の軽減を
ご紹介した「デザインパターン」のような開発手法を取り入れることで、Webサイト・システムの保守運用の運用コスト軽減・負担軽減につなげることができます。これらのメリットは開発に携わるエンジニアにはもちろん有効ですが、依頼する制作会社がこのような手法を取り入れているかどうかで担当者さまの負担軽減にもつながるでしょう。
公開前から保守運用に有効な技術・観点を重視した開発をすることで、公開後もスピード感を持ってお客様に納品をすることができ、運用コストが過剰にかさむことを防ぐことができます。これらの技術や観点を持って運用時を見通した開発ができることが、サービシンクが保守運用サービスに自信を持つ理由の一つです。
大型システムの開発から6年以上にわたり開発保守をお任せ頂いているプロジェクトの実績もあり、大手不動産会社をはじめとした企業様とご一緒した経験からの知見も豊富です。
これまで費用が安くシステム開発に不慣れな制作会社に発注したために、1から要件定義をやり直したり、公開後の制作会社との調整で疲弊してしまった経験があるご担当者様も中にはいるのではないでしょうか。
Webサイト・システムの依頼をする際には、公開だけをゴールにせず、開発時から保守運用を重視した開発ができる制作会社への依頼をしてみませんか。その際にはぜひサービシンクをご検討ください。
Webサイト・システムの
お悩みがある方は
お気軽にご相談ください
出張またはWeb会議にて、貴社Webサイトの改善すべき点や
ご相談事項に無料で回答いたします。