システムアーキテクト 2025年 午前2 問02
問題文
オブジェクト指向設計における設計原則の説明のうち、開放閉鎖原則のものはどれか。
選択肢
ア:クラスにもたせる役割は一つだけにするべきであり、複数の役割が存在する場合にはクラスを分割する。
イ:クラスを利用するクライアントごとに異なるメソッドが必要な場合は、インタフェースを分ける。
ウ:上位のモジュールは、下位のモジュールに依存してはならない。
エ:モジュールは、機能の追加や変更が可能であって、その影響を他のモジュールに及ぼしてはならない。(正解)
開放閉鎖原則(オブジェクト指向設計)の説明【午前2 解説】
要点まとめ
- 結論:モジュールは拡張(新機能の追加)には開かれ、既存コードの修正で他の部分に副作用を与えない設計であるべきです。
- 根拠:開放閉鎖原則(Open/Closed Principle)は抽象化やポリモーフィズムで機能拡張を実現し、既存実装の修正を避けることを目指します。
- 差がつくポイント:OCPは「変更を禁止する」ではなく「拡張で対応する」点と、継承だけでなく委譲やパターンで実現する点を意識すると差が出ます。
正解の理由
正解: エ
エの文は「モジュールは、機能の追加や変更が可能であって、その影響を他のモジュールに及ぼしてはならない」というもので、まさに開放閉鎖原則(OCP:Open/Closed Principle)の定義を述べています。OCPは「拡張に対して開かれて(open)、変更に対して閉じている(closed)」ことを意味し、新しい振る舞いは既存モジュールを修正せずに追加できる設計を求めます。抽象化(インタフェースや抽象クラス)、ポリモーフィズム、デザインパターン(Strategy, Decorator, Factoryなど)によって実現されます。
エの文は「モジュールは、機能の追加や変更が可能であって、その影響を他のモジュールに及ぼしてはならない」というもので、まさに開放閉鎖原則(OCP:Open/Closed Principle)の定義を述べています。OCPは「拡張に対して開かれて(open)、変更に対して閉じている(closed)」ことを意味し、新しい振る舞いは既存モジュールを修正せずに追加できる設計を求めます。抽象化(インタフェースや抽象クラス)、ポリモーフィズム、デザインパターン(Strategy, Decorator, Factoryなど)によって実現されます。
よくある誤解(2〜3 行)
OCPは「絶対に変更してはならない」という意味ではなく、設計変更の影響を局所化することが目的です。
拡張手段を継承だけに限定して考えると保守性が落ち、委譲やパターン利用の観点を見落としがちです。
拡張手段を継承だけに限定して考えると保守性が落ち、委譲やパターン利用の観点を見落としがちです。
解法ステップ
- 問題文のキーワードを確認:「影響を他のモジュールに及ぼしてはならない」「追加や変更が可能」などを探す。
- 各選択肢をSOLIDや基本設計原則に照らしてマッピングする(SRP, ISP, DIP, OCP等)。
- 最もOCPの定義に合致する文言(拡張は可能、修正で影響を与えない)を選ぶ。
- 他の選択肢が別の原則を示す場合は消去法で除外する。
選択肢別の誤答解説
- ア: クラスにもたせる役割は一つだけにするべきであり、複数の役割が存在する場合にはクラスを分割する。
→ これは単一責任原則(SRP:Single Responsibility Principle)を説明しており、OCPではありません。 - イ: クラスを利用するクライアントごとに異なるメソッドが必要な場合は、インタフェースを分ける。
→ これはインタフェース分割原則(ISP:Interface Segregation Principle)に該当します。 - ウ: 上位のモジュールは、下位のモジュールに依存してはならない。
→ これは依存性逆転原則(DIP:Dependency Inversion Principle)の趣旨であり、OCPとは異なります。 - エ: モジュールは、機能の追加や変更が可能であって、その影響を他のモジュールに及ぼしてはならない。
→ これが開放閉鎖原則(OCP)の定義に一致するため正解です。
補足コラム(関連知識など)
開放閉鎖原則はSOLID原則の一つで、実装例としては抽象インタフェースを用意して具象クラスを追加することで既存コードを変更せず機能拡張します。代表的なデザインパターンはStrategy、Decorator、Factory Methodなどです。簡単なPython例:
from abc import ABC, abstractmethod
class Formatter(ABC):
@abstractmethod
def format(self, text: str) -> str:
pass
class PlainFormatter(Formatter):
def format(self, text: str) -> str:
return text
class HtmlFormatter(Formatter):
def format(self, text: str) -> str:
return f"<p>{text}</p>"
class Document:
def __init__(self, formatter: Formatter):
self.formatter = formatter
def render(self, text: str) -> str:
return self.formatter.format(text)
# 新しいフォーマッタを追加しても Document の実装は変更しない(OCP準拠)
この例では Document を変更せずに新しい Formatter を追加でき、OCPを満たします。
FAQ
Q: OCPとSRPはどう違いますか?
A: SRPは「クラスは一つの責務のみ」を指し、OCPは「拡張は可能で修正で他へ影響を与えない」設計を指します。焦点が異なります。
A: SRPは「クラスは一つの責務のみ」を指し、OCPは「拡張は可能で修正で他へ影響を与えない」設計を指します。焦点が異なります。
Q: 継承と委譲どちらがOCPに向いていますか?
A: ケースによりますが、委譲(コンポジション)とインタフェースによる抽象化は柔軟性が高く、OCPを守りやすいことが多いです。
A: ケースによりますが、委譲(コンポジション)とインタフェースによる抽象化は柔軟性が高く、OCPを守りやすいことが多いです。
関連キーワード: 開放閉鎖原則、OCP, SOLID, 単一責任原則、依存性逆転原則、インタフェース分割原則、デコレータ、ストラテジーパターン、抽象化、ポリモーフィズム

\ せっかくなら /
システムアーキテクトを
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

