|
||||
週刊オブジェクト倶楽部 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の原則) |
||||
つづき |