본문 바로가기
TIL

01.26 (TIL-Unity)

by 오랑이귀엽다 2024. 1. 26.

오늘은 작업한 스크립트의 리펙토리를 진행중이다.

 

객체지향 설계 원칙의 이해: 단일 책임, 개방/폐쇄, 리스코프 치환 원칙

 

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 메소드를 갖고, 날 수 있는 새와 그렇지 않은 새는 각각 FlyingBirdPenguin 클래스로 구현

'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