単一責任の原則 (Single Responsibility Principle: SRP)
単一責任の原則(Single Responsibility Principle: SRP)とは、ロバート・C・マーチンによって提唱されたSOLID原則の一つであり、「あるクラスはたった一つの変更理由のみを持つべき」という原則です。本記事では、SRPを実践する上級プログラマー向けに、PythonとTypeScriptによる具体例を用いてSRPが守られているケースとそうでないケースを解説します。
単一責任の原則(SRP)の本質
単一責任の原則を正しく理解するには、「責任」を「変更理由」と考えると良いでしょう。一つのクラスに複数の変更理由が存在すると、変更が加えられるたびに他の無関係な機能に予期せぬ影響を与えるリスクが増大します。
Pythonによる例
❌ SRPが守られていない例
class UserManager:
def create_user(self, user_data):
self.save_to_database(user_data)
def send_welcome_email(self, email):
print(f"Sending welcome email to {email}")
def save_to_database(self, data):
print(f"Saving {data} to database")
上記のクラスは、ユーザーの作成、データベースへの保存、メール送信と、複数の責任を持っているため変更が多方面に影響します。
✅ SRPが守られている例
class UserRepository:
def save(self, user_data):
print(f"Saving {user_data} to database")
class EmailService:
def send_welcome_email(self, email):
print(f"Sending welcome email to {email}")
class UserManager:
def __init__(self, repository: UserRepository, email_service: EmailService):
self.repository = repository
self.email_service = email_service
def register_user(self, user_data):
self.repository.save(user_data)
self.email_service.send_welcome_email(user_data['email'])
この例では、データベース操作、メール送信、それぞれの責務が明確にクラスごとに分離されています。
TypeScriptによる例
❌ SRPが守られていない例
class OrderProcessor {
processOrder(order: any) {
this.validateOrder(order);
this.saveOrder(order);
this.notifyCustomer(order.customerEmail);
}
validateOrder(order: any) {
console.log('Validating order');
}
saveOrder(order: any) {
console.log('Saving order to DB');
}
notifyCustomer(email: string) {
console.log(`Sending notification to ${email}`);
}
}
この例では、注文の検証、データベース保存、顧客通知が1つのクラス内に含まれており、変更に弱い構造です。
✅ SRPが守られている例
class OrderValidator {
validate(order: any) {
console.log('Validating order');
}
}
class OrderRepository {
save(order: any) {
console.log('Saving order to DB');
}
}
class NotificationService {
notify(email: string) {
console.log(`Sending notification to ${email}`);
}
}
class OrderProcessor {
constructor(
private validator: OrderValidator,
private repository: OrderRepository,
private notifier: NotificationService
) {}
process(order: any) {
this.validator.validate(order);
this.repository.save(order);
this.notifier.notify(order.customerEmail);
}
}
それぞれの責務を別クラスに分割し、変更があった際の影響範囲を限定しています。
まとめ
単一責任の原則は「変更理由を1つに絞ること」であり、変更の影響範囲を制御し、テストや保守のしやすさを高めます。上級プログラマーとしては、SRPを厳格に守るだけでなく、実際のプロジェクトの状況に応じて柔軟に適用する力も求められます。