BOOK Preview

Code Complete 第2版 上・下
― 完全なプログラミングを目指して

第6章 クラスの作成

マイクロソフトプレスの書籍紹介ページ
書籍情報のページ
2005/04/26


6.5 言語固有の問題

 プログラミング言語によって、クラスへの取り組み方はおもしろいほど異なっている。例として、メンバルーチンをオーバーライドして、派生クラスでポリモーフィズムを実現する方法について考えてみよう。Javaでは、すべてのルーチンが既定でオーバーライドされる。ルーチンが派生クラスでオーバーライドされるのを防ぐには、ルーチンをfinalで宣言しなければならない。C++では、ルーチンは既定でオーバーライドされない。ルーチンをオーバーライド可能にするには、基底クラスでルーチンをvirtualで宣言しなければならない。Visual Basicでは、基底クラスでルーチンをOverridableで宣言し、派生クラスでOverrideキーワードを使用しなければならない。

 ここで、言語によって大きく異なる機能のうち、クラスに関連する部分を挙げてみよう。

  • 継承ツリーでオーバーライドされたコンストラクタとデストラクタの振る舞い

  • 例外処理の条件下にあるコンストラクタとデストラクタの振る舞い

  • 既定のコンストラクタ(引数を持たないコンストラクタ)の重要性

  • デストラクタまたはファイナライザが呼び出されるタイミング

  • 代入演算子や等価演算子など、言語のビルトイン演算子をオーバーライドする方法

  • オブジェクトの生成と破棄、またはオブジェクトの宣言とオブジェクトがスコープを外れたときのメモリの処理方法

 これらについて説明するのはまたの機会にして、章末の「6.7 参考資料」で言語関連の参考書を紹介しておく。

6.6 クラスを超えて:パッケージ

 本書の執筆時点では、クラスはプログラマがモジュール化を実現するための最も効果的な手段である。しかし、モジュール化は壮大なテーマであり、クラスの枠にとどまらない。数十年に及ぶソフトウェア開発の進化の歴史は、プログラマが対処しなければならない集合体をごつごつしたものからなめらかなものへ少しずつ進化させた歴史と言ってもよいだろう。最初の集合体はステートメントで、当時のマシン命令からすれば、大きな前進であるように思われた。次にサブルーチンが、その次にクラスが登場した。

参照
クラスとパッケージの対比については、第5章の「5.2.3 設計のレベル」を参照。

 オブジェクトをグループにまとめる良いツールがあったなら、抽象化やカプセル化の目標を達成しやすかったことは明らかである。Adaはパッケージの概念を10年以上も前にサポートしていた。現在では、Javaがパッケージをサポートしている。パッケージを直接サポートしていない言語でプログラミングを行っている場合は、自分専用の手軽なパッケージを作成して、次を含むプログラミング標準に基づいて適用すればよい。

  • パッケージに含まれるパブリックなクラスとプライベートなクラスを区別する命名規則

  • どのクラスがどのパッケージに属しているのかを識別する命名規則、コード構成規則(プロジェクト構造)、またはその両方

  • 他のパッケージを使用できるパッケージと、その使用法が継承、包含、または両方のいずれであるかを定義する規則

 これらの打開策は、言語の中でのプログラミングと言語の中へのプログラミングの良い例である。この区別については、下巻第34章の「34.4 言語の中へのプログラミング」を参照すること。

参照
チェックリスト6-1はクラスの品質について検討するためのチェックリストである。クラスを作成する手順に関するチェックリストについては、「第9章擬似コードによるプログラミング」を参照。

チェックリスト6-1 クラスの品質

抽象データ型
プログラムに含まれるクラスをADTとして考え、その見地からインターフェイスを評価したか。
抽象化
クラスに基本目標があるか。
クラスに良い名前が付き、その名前がクラスの基本目標を説明しているか。
クラスのインターフェイスは一貫性のある抽象化を実現しているか。
クラスのインターフェイスはクラスの使用法を明確に示しているか。
クラスのインターフェイスは、そのサービスの実装方法について考えなくてもよいほど抽象化されているか。クラスをブラックボックスとして扱うことができるか。
他のクラスがそのクラスの内部データに干渉する必要がないほど、クラスのサービスの完成度は高いか。
関係のない情報をクラスの外へ移動したか。
クラスをコンポーネントのクラスに再分割することを検討し、それをできるだけ細かく分けてみたか。
クラスを修正するときにクラスのインターフェイスの整合性を維持しているか。
カプセル化
クラスのメンバへのアクセスを最小限に抑えているか。
クラスのメンバデータの公開を避けているか。
プログラミング言語が許可する範囲内で、クラスの実装の詳細を他のクラスから隠ぺいしているか。
派生クラスを含むクラスのユーザーについて憶測していないか。
クラスが他のクラスに依存していないか。疎結合か。
継承
継承を「is a」関係のモデリングにのみ使用しているか。つまり、派生クラスがリスコフの置換原則に準拠しているか。
クラスの説明文に継承方法を記載しているか。
派生クラスでオーバーライド不可能なルーチンを「オーバーライド」していないか。
共通のインターフェイス、データ、振る舞いを継承ツリーのできるだけ上のレベルに移動したか。
継承ツリーは浅めにしているか。
基底クラスのすべてのメンバデータをprotectedではなくprivateで宣言しているか。
その他の実装問題
クラスに含まれているメンバデータの数は約7個またはそれ以下である
か。
クラスから他のクラスへの直接的または間接的なルーチン呼び出しを最小限に抑えているか。
クラスが絶対に必要な範囲内で他のクラスと協力しているか。
すべてのメンバデータをコンストラクタで初期化しているか。
シャローコピーを作成する明確な理由がない限り、クラスがシャローコピーではなくディープコピーを使用する設計になっているか。
言語固有の問題
特定のプログラミング言語について、クラスに関連する言語固有の問題を調査したか。

6.7 参考資料

クラス全般

  • 『Object-Oriented Software Construction, 2nd edition』
    (Bertrand Meyer著、Prentice Hall、1997年)
    『オブジェクト指向入門』
    (初版の翻訳、アスキー、1990年、二木厚吉監訳、酒匂寛、酒匂順子訳)
    ADTを徹底的に解説し、それらがいかにしてクラスの基礎を形成するのかを説明している。第14章〜第16章では、継承について詳しく述べている。第15章では、多重継承を使用する理由を挙げている。

  • 『Object-Oriented Design Heuristics』
    (Arthur J. Riel著、Addison-Wesley、1996年)
    クラスレベルを中心に、プログラムの設計を改善するための提案を数多く盛り込んでいる。あまりにも深いテーマ(「すねに傷を持つものはうかつなことを言うなかれ」という話)に思えて、数年前までは勧めていなかった。ただし、本の厚さはたった200ページほどである。Rielの文章は読みやすく、楽しめる。的を絞った実用的な内容になっている。

C++

Java

Visual Basic

 次に、Visual Basicのクラスを取り上げた良い参考書を紹介しよう。

6.8 まとめ

  • クラスインターフェイスは一貫性のある抽象化を実現しなければならない。このたった1つの原則に違反しただけで、多くの問題が生じる。

  • クラスインターフェイスは何か(システムインターフェイス、設計上の決断、または実装の詳細)を隠ぺいしなければならない。

  • 「is a」関係をモデリングする場合を除き、通常は継承よりも包含の方が望ましい。

  • 継承は便利なツールだが、複雑さを増大させる。このことは、ソフトウェアの鉄則である複雑さへの対処を妨げる。

  • クラスは複雑さに対処するための第一のツールである。クラスの目標を達成するために必要なものと同じくらい、クラスの設計にも注意を払うこと。

 

 INDEX
  Code Complete 第2版 上・下
  第6章 クラスの作成
    1.6.1 クラスの基礎:抽象データ型(ADT)(1)
    2.6.1 クラスの基礎:抽象データ型(ADT)(2)
    3.6.2 良いクラスインターフェイス(1)
    4.6.2 良いクラスインターフェイス(2)
    5.6.3 設計と実装の問題(1)
    6.6.3 設計と実装の問題(2)
    7.6.4 クラスを作成する理由
  8.6.5 言語固有の問題/6.6 クラスを超えて:パッケージ/6.7 参考資料/6.8 まとめ
 
インデックス・ページヘ  「BOOK Preview」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間