오늘은 작업한 스크립트의 리펙토리를 진행중이다.
객체지향 설계 원칙의 이해: 단일 책임, 개방/폐쇄, 리스코프 치환 원칙
1. 단일 책임 원칙 (Single Responsibility Principle, SRP)
- 정의: 한 클래스는 하나의 책임만 가져야 한다는 원칙입니다. 즉, 클래스가 변경되어야 하는 이유는 단 하나여야 합니다.
- 목적: 이 원칙은 클래스의 복잡성을 줄이고, 유지보수를 용이하게 하며, 테스트를 간편하게 만들기 위해 사용됩니다.
- 적용 방법: 클래스가 여러 기능을 갖고 있다면, 각 기능을 개별 클래스로 분리하여 각 클래스가 하나의 책임만을 지도록 합니다.
- 예시: 사용자 인터페이스 처리, 비즈니스 로직 처리, 데이터베이스 연동 처리 등 각각의 기능을 별도의 클래스로 분리할 수 있습니다.
1-1기존의 클래스 (SRP 위반)
public class UserSettings {
public User user;
public void ChangeUserName(string newName) {
user.Name = newName;
// 유저 이름 변경 로직
}
public void SaveSettings() {
// 설정 저장 로직
}
}
클래스는 사용자 이름 변경과 설정 저장 두 가지 책임을 가지고 있다.
1-2리팩토링 후 (SRP 적용)
public class UserSettings {
public User user;
public void SaveSettings() {
// 설정 저장 로직
}
}
public class UserNameChanger {
public User user;
public void ChangeUserName(string newName) {
user.Name = newName;
// 유저 이름 변경 로직
}
}
UserSettings 클래스는 설정 저장만, UserNameChanger 클래스는 사용자 이름 변경만 책임
2. 개방/폐쇄 원칙 (Open/Closed Principle, OCP)
- 정의: 소프트웨어 개체(클래스, 모듈, 함수 등)는 확장에 대해 열려 있어야 하지만, 변경에 대해서는 닫혀 있어야 한다는 원칙입니다.
- 목적: 이 원칙은 기존의 코드를 변경하지 않고도 시스템의 기능을 확장할 수 있도록 도와줍니다.
- 적용 방법: 추상화와 다형성을 활용하여 새로운 기능을 기존 코드에 추가할 수 있도록 설계합니다. 인터페이스나 추상 클래스를 사용하여 확장성을 제공합니다.
- 예시: 새로운 로그인 방식을 추가할 때, 기존 로그인 클래스를 수정하지 않고, 로그인 인터페이스를 구현하는 새 클래스를 추가합니다.
2-1기존의 클래스 (OCP 위반)
public class Logger {
public void Log(string message) {
Console.WriteLine(message);
}
}
새로운 로깅 방식(예: 파일 로깅)을 추가하려면 Logger 클래스를 수정
2-2리팩토링 후 (OCP 적용)
public class Bird {
public virtual void Fly() {
// 날아가는 로직
}
}
public class Penguin : Bird {
public override void Fly() {
throw new NotSupportedException("펭귄은 날 수 없습니다");
}
}
로깅 방식을 추가하려면 ILogger 인터페이스를 구현하는 새 클래스를 추가하면됨
3. 리스코프 치환 원칙 (Liskov Substitution Principle, LSP)
- 정의: 프로그램에서 부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 대체(치환)할 수 있어야 한다는 원칙입니다.
- 목적: 이 원칙은 상속을 통해 클래스의 확장성을 높이면서도 안정성을 유지하도록 도와줍니다.
- 적용 방법: 자식 클래스는 부모 클래스의 기능을 확장만 할 뿐, 기존 기능을 변경하지 않아야 합니다. 이를 위해 오버라이딩된 메소드는 부모 클래스의 기능을 손상시키지 않아야 합니다.
- 예시: Bird 클래스가 fly 메소드를 갖고 있을 때, 이를 상속받는 Penguin 클래스에서 fly 메소드를 오버라이딩하여 비행 불가능 상태를 반환하지 않고, 대신 다른 방식으로 확장합니다.
3-1기존의 클래스 (LSP 위반)
public class Bird {
public virtual void Fly() {
// 날아가는 로직
}
}
public class Penguin : Bird {
public override void Fly() {
throw new NotSupportedException("펭귄은 날 수 없습니다");
}
}
Bird 클래스의 Fly 메소드를 Penguin에서 오버라이딩하여 기능을 변경
3-2리팩토링 후 (LSP 적용)
public abstract class Bird {
public abstract void Move();
}
public class FlyingBird : Bird {
public override void Move() {
// 날아가는 로직
}
}
public class Penguin : Bird {
public override void Move() {
// 걷는 로직
}
}
Bird 클래스는 Move 메소드를 갖고, 날 수 있는 새와 그렇지 않은 새는 각각 FlyingBird와 Penguin 클래스로 구현
'TIL' 카테고리의 다른 글
01.30 (TIL-Unity) (0) | 2024.01.30 |
---|---|
01.29 (TIL-Unity) (0) | 2024.01.29 |
01.25 (TIL-Unity) (0) | 2024.01.25 |
01.24 (TIL-Unity) (0) | 2024.01.24 |
01.23 (TIL-Unity) (0) | 2024.01.23 |