Skip to content.

Sections
Personal tools
You are here: Home » 技術文書 » オブジェクト指向 » ソフトウエア原則 » ソフトウェア原則[1]

Document Actions
ソフトウェア原則[1] - OCP(Open-Close Principle)
週刊オブジェクト倶楽部 2003-01号の書評『オブジェクト指向入門』の中で、OCP"Open-Close Principle"として、

    「ソフトウェアモジュールは、変更に対して閉じており、拡張に対して開いているべき」

を紹介しました。第1回目は、このOCP からです。次のC言語コードを見てどう思いますか?

[コード1]
  typedef struct { int x, y; } Point;
  typedef struct { Point p1, p2; } Line;
  typedef enum { LINE, POINT } Kind;
  typedef union { Point* point; Line* line; } ShapeUnion; 
  
  typedef struct {
      Kind kind;
      ShapeUnion of;
  } Shape;
  
  void draw(Shape* shape) {
      switch(shape->kind) {
      case LINE:
        /* draw line (shape->of->line.p1  ---- shape->of->line.p2) */
        break;
      case POINT:
        /*  draw point (shape->of->point)*/
        break;
      }
  }
  
これは、私が15年前に書いたコードです。なかなかイケてるでしょ? でも、Kindとして新たにCIRCLEを追加したとき、このdraw関数を修正し、 case CIRCLEを追加しなければならいのです。

では、どうするの?C++では、

[コード2]
  class Shape {
  public:
      virtual void draw() = 0;
  };
  
  class Point : public Shape {
      int x, y;
  public:
      void draw() { /* draw point (x,y) */   }
  };
  
  class Line : public Shape {
      Point p1, p2;
  public:
      void draw() { /* draw line p1-p2 */ }
  }; 
  
と書くことができます。このようにすると、Circleの追加は、「既存のプログ ラムを全く変更せずに」(再コンパイルさえも!)できるのです。これが、 CloseしているプログラムをOpenにするというオブジェクト指向プログラミング の1つの真骨頂なのです。修正の論理を、追加の論理に変換している、といえます。

ちなみに、オブジェクト指向プログラミングでは、構造化プログラミングで gotoが悪だったように、switch分岐は悪と言われています。 (2箇所以上同じ分岐がある場合)。

後日談。

現在では、『リファクタリング』という再設計技術が注目されるようになり、 コード1をコード2に再設計することを、Replace Conditional With Polymorphism (多態による条件分岐の置き換え)と呼んでいます。また、switch文が必ずしも 悪という訳ではなく、同じパターンのswitchが繰り返されることが悪だ、と いう解釈になっています。(Once and Only Onceの原則)

つづき



この記事への評価にご協力をお願いします。

良かった 普通 イマイチ