導入
プロジェクトの成長と共に、コードベースの複雑さも増していく。特にオブジェクト指向設計は、その柔軟性と再利用性から、多くの現場で採用されている。しかし、実際の業務では、設計の初期段階での選択が後々の保守性や拡張性に大きな影響を及ぼす。今回は、架空のプロジェクトを通じて、上級レベルのTypeScriptを用いたオブジェクト指向設計の実践を見ていく。
教科書レベルの解説(オブジェクト指向設計)
重要な概念の整理
オブジェクト指向設計は、クラスとオブジェクトの概念を基にしており、以下の4つの基本原則から成り立っています。
- カプセル化: データとその操作を一つの単位としてまとめること。
- 継承: 既存のクラスを基に新しいクラスを作成すること。
- ポリモーフィズム: 同じインターフェースを持ちながら異なる実装を持つこと。
- 抽象化: 複雑なシステムを簡潔に表現すること。
これらの原則を理解し、適切に適用することで、可読性やメンテナンス性の高いコードを作成できる。
コード例(TypeScript)
class User {
constructor(private name: string, private age: number) {}
getName(): string {
return this.name;
}
getAge(): number {
return this.age;
}
}
class Admin extends User {
constructor(name: string, age: number, private permissions: string[]) {
super(name, age);
}
getPermissions(): string[] {
return this.permissions;
}
}
const admin = new Admin("Alice", 30, ["read", "write", "delete"]);
console.log(admin.getName()); // Alice
console.log(admin.getPermissions()); // ["read", "write", "delete"]
コードの行ごとの解説
- 1行目: Userクラスを定義。名前と年齢をプライベートなプロパティとして持つ。
- 2行目: コンストラクタでプロパティを初期化。
- 3行目: 名前を取得するメソッド。
- 4行目: 年齢を取得するメソッド。
- 6行目: AdminクラスをUserクラスから継承。
- 7行目: 管理者特有の権限を持つプロパティを追加。
- 9行目: Adminクラスのコンストラクタで親クラスのコンストラクタを呼び出す。
- 10行目: 権限を取得するメソッド。
- 12行目: Adminクラスのインスタンスを作成。
- 13行目: 名前をコンソールに出力。
- 14行目: 権限をコンソールに出力。
ケーススタディ編
架空のプロジェクトとして、企業内のユーザー管理システムを考える。このシステムでは、一般ユーザーと管理者が存在し、それぞれ異なる機能を持つ。最初はシンプルな設計で始めるが、要件が増えるにつれて、拡張性や保守性が求められるようになる。
例えば、最初はユーザーの追加や削除が必要なだけだったが、後にユーザーの役割や権限を管理する機能が追加される。ここで重要なのは、初期設計での継承を利用することで、Adminクラスを簡単に拡張できる点だ。管理者専用のメソッドを追加する際にも、既存のUserクラスを変更する必要がないため、影響を最小限に抑えられる。
しかし、落とし穴も存在する。Adminクラスに特有のロジックが増えてくると、クラスが肥大化し、単一責任の原則に反する恐れがある。これを避けるために、責任を分担する別のクラスを作成し、Adminクラスのメソッドを呼び出す形にすることが望ましい。
まとめ
- オブジェクト指向設計は、現場での要件に応じて柔軟に適用することが求められる。
- クラスの設計は、将来の拡張や変更を見据えて行うことが重要だ。
- 責任の分担を意識し、クラスの肥大化を防ぐ工夫が必要である。