C#
 Computer >> コンピューター >  >> プログラミング >> C#

C#でオープン・クローズドの原則(OCP)を実装する方法


クラス、モジュール、関数といったソフトウェアの構成要素は、「拡張に対して開かれており(Open for Extension)、修正に対して閉じられている(Closed for Modification)」べきです。これが、SOLID設計原則のひとつであるオープン・クローズドの原則(OCP:Open Closed Principle)の核心的な考え方です。

オープン・クローズドの原則とは

定義: オープン・クローズドの原則とは、既存のコードへの変更を最小限に抑えながら、新しい機能を追加できるようにコードを設計・記述すべきという原則です。つまり、できる限り既存コードをそのまま維持しつつ、新機能を「新しいクラス」として追加していけるような設計が求められます。

具体例で理解するOCP

OCP適用前のコード

まずは、原則に従っていないコードを見てみましょう。

using System;
using System.Net.Mail;
namespace SolidPrinciples.Open.Closed.Principle.Before
{
    public class Rectangle
    {
        public int Width { get; set; }
        public int Height { get; set; }
    }
    public class CombinedAreaCalculator
    {
        public double Area(object[] shapes)
        {
            double area = 0;
            foreach (var shape in shapes)
            {
                if (shape is Rectangle)
                {
                    Rectangle rectangle = (Rectangle)shape;
                    area += rectangle.Width * rectangle.Height;
                }
            }
            return area;
        }
    }
    public class Circle
    {
        public double Radius { get; set; }
    }
    public class CombinedAreaCalculatorChange
    {
        public double Area(object[] shapes)
        {
            double area = 0;
            foreach (var shape in shapes)
            {
                if (shape is Rectangle)
                {
                    Rectangle rectangle = (Rectangle)shape;
                    area += rectangle.Width * rectangle.Height;
                }
                if (shape is Circle)
                {
                    Circle circle = (Circle)shape;
                    area += (circle.Radius * circle.Radius) * Math.PI;
                }
            }
            return area;
        }
    }
}

このコードには明確な問題点があります。CombinedAreaCalculatoris演算子で型を判定し、図形ごとに分岐処理を書いて面積を計算しています。この状態でTriangleなどの新しい図形を追加しようとすると、CombinedAreaCalculatorChangeのようにif文を増やして既存のメソッドを修正する必要が生じます。これは「修正に対して開いた状態」であり、OCPに違反している典型的な例です。

OCP適用後のコード

続いて、オープン・クローズドの原則を適用してリファクタリングしたコードです。

namespace SolidPrinciples.Open.Closed.Principle.After
{
    public abstract class Shape
    {
        public abstract double Area();
    }
    public class Rectangle : Shape
    {
        public int Width { get; set; }
        public int Height { get; set; }
        public override double Area()
        {
            return Width * Height;
        }
    }
    public class Circle : Shape
    {
        public double Radius { get; set; }
        public override double Area()
        {
            return Radius * Radius * Math.PI;
        }
    }
    public class CombinedAreaCalculator
    {
        public double Area(Shape[] shapes)
        {
            double area = 0;
            foreach (var shape in shapes)
            {
                area += shape.Area();
            }
            return area;
        }
    }
}

改善のポイントは以下の3点です。

  • 抽象基底クラスShapeの導入: 面積を返す抽象メソッドArea()を持つShapeクラスを定義し、共通の契約を作ります。
  • 各図形が自身の計算ロジックを持つ: RectangleCircleShapeを継承し、それぞれのArea()メソッドをオーバーライドします。
  • 計算クラスの汎用化: CombinedAreaCalculatorShape型の配列を受け取り、多態性(ポリモーフィズム)によってshape.Area()を呼び出すだけでよくなります。

この設計により、今後Triangleなど新しい図形が必要になった場合でも、Shapeを継承した新しいクラスを追加するだけで対応できます。既存のCombinedAreaCalculatorを一切修正する必要がないため、拡張に対して開かれ、修正に対して閉じられた理想的な状態を実現できています。


  1. Java 9でJavaFXを使ってJShellをプログラムから実装する方法

    JShellは、サンプル式を対話的に実行できるツールです。通常はコマンドラインから利用しますが、JavaFXアプリケーションの中でプログラム的にJShellを実装することも可能です。その場合、Javaプログラムに以下のパッケージをインポートする必要があります。import jdk.jshell.JShell; import jdk.jshell.SnippetEvent; import jdk.jshell.VarSnippet;これらのクラスの役割は次のとおりです。JShell:評価エンジンの本体。式や文を評価(eval)するためのAPIを提供します。SnippetEvent:評価結果として

  2. Tkinterを使って外部プログラムを開く方法を解説

    アプリケーションを開発していると、外部のプログラムやアプリケーションと連携する必要が出てくることがあります。システム上のアプリケーションやプログラムを操作するには、Pythonのosモジュールを利用します。この記事では、osモジュールを使って外部プログラムと連携し、ファイルを開く方法を詳しく解説します。まず、filedialogライブラリを使用して、ユーザーが選択したファイルを開くための関数を定義します。次に、選択されたファイルのパスを画面に表示し、osモジュールを使ってそのファイルを実行します。コード例# 必要なライブラリをインポート from tkinter import * from t