BoostStudy / design-patterns

디자인 패턴의 아름다움 스터디 저장소
6 stars 0 forks source link

CHAPTER 3 설계 원칙 #3

Closed lee-ji-hoon closed 6 months ago

lee-ji-hoon commented 7 months ago

기말고사 이슈로 12월 말 진행 + 직장인 이슈로 1월중순...

생각해보기

1. 클래스 설계 외에 단일 책임 원칙을 적용할 수 있는 설계에는 어떤 것들이 있는가?

2. 확장할 때는 개방, 수정할 때는 폐쇄되어야 하는 이유가 무엇인가?

3. 리스코프 치환 원리의 중요성은 무엇인가?

4. AtomicIntegor 클래스에서 getAndIncrement 함수는 단일 책임 원칙과 인터페이스 분리 원칙을 준수했는가?

5. Notification 클래스에서 구현이 아닌 인터페이스 기반과 의존성 주입은 서로 유사하다. 그렇다면 이 두 가지의 차이점은?

6. 개발 과정에서 바퀴를 다시 발명하는 행위에 대해 어떻게 생각하는지

7. 코드의 논리의 중복, 기능적 중복, 코드 실행의 중복 외 또 어떤 형태의 코드 중복이 있을까? 그 코드 중복은 DRY 원칙을 위배하는가?

lee-ji-hoon commented 6 months ago

생각해보기

1. 클래스 설계 외에 단일 책임 원칙을 적용할 수 있는 설계에는 어떤 것들이 있는가?

SOLID는 객체지향에서 사용되는 원칙중 하나라서 함수도 단일책임원칙을 지켜야만 하나? 라는 생각이 있었는데, SOLID는 객체지향에서 사용하는 원칙일 뿐 객체에서만 SOLID를 지켜야한다. 라고 잘못 생각하고 있었던거 같네

2. 확장할 때는 개방, 수정할 때는 폐쇄되어야 하는 이유가 무엇인가?

이건 거의 책에서 나온 내용으로 정리가 될거 같네

3. 리스코프 치환 원리의 중요성은 무엇인가?

상속을 할 때 부모가 사용되는 곳에서 자식으로 변경이 가능해야 하는데 이때 계약 위반?(null 발생인데 NPE터지게 한다는지) 이런거 까지 고려해야하는지는 몰랐네.

4. AtomicIntegor 클래스에서 getAndIncrement 함수는 단일 책임 원칙과 인터페이스 분리 원칙을 준수했는가?

둘 다 됐다고 생각하는데 인터페이스 분리 원칙만 살짝 애매하다고 생각

5. Notification 클래스에서 구현이 아닌 인터페이스 기반과 의존성 주입은 서로 유사하다. 그렇다면 이 두 가지의 차이점은?

우리가 주로 인터페이스 기반 + 의존성 주입을 같이 사용하고 있어서 차이점을 의식하기가 힘들었던 거 같은데 내 생각에는 위와 같은 차이가 있을 거 같네

6. 개발 과정에서 바퀴를 다시 발명하는 행위에 대해 어떻게 생각하는지

개인적인 생각만 말하자면 비효율적이다.

7. 코드의 논리의 중복, 기능적 중복, 코드 실행의 중복 외 또 어떤 형태의 코드 중복이 있을까? 그 코드 중복은 DRY 원칙을 위배하는가?

코드 중복 자체는 저거 말고는 구조 중복? 같은 느낌 밖에 생각이 안나는데 이건 DRY 원칙 위배는 아닌거 같다.

읽으면서 와닿았던 것들

단일책임

  1. 클래스에 private한 메서드가 많으면 private 메서드를 아예 새로운 클래스로 분리하고, 더 많은 클래스에서 사용할 수 있도록 public 메서드로 설정하여 코드의 재사용성을 향상시켜야 한다.

  2. Manager, Context처럼 일반적인 단어가 아니면 클래스의 이름을 정의하기 어려울 경우 클래스의 책임 정의가 충분히 명확하지 않음을 의미할 수도 있다.

개방폐쇄

  1. 테스트 코드가 추가가 되는가? 아니면 변경이 되는가.
ldh019 commented 6 months ago

1. 클래스 설계 외에 단일 책임 원칙을 적용할 수 있는 설계에는 어떤 것들이 있는가?

객체지향 프로그래밍에서 설계는 클래스 뿐만이 아니라 메서드, 모듈에도 항상 동일하게 적용되는 것 같다. 책임의 개념이나 규모가 다를 뿐 하나의 책임을 맡아야 한다는 맥락에선 동일하다. 클래스에서는 하나의 객체가 가져야 하는 책임을 설계한다면, 메서드에서는 한 개의 연산 묶음, 하나의 작업에 대한 책임을, 모듈에서는 하나의 큰 카테고리, 파트에 대한 책임을 가지도록 설계하는 것이 해당된다고 생각한다.

2. 확장할 때는 개방, 수정할 때는 폐쇄되어야 하는 이유가 무엇인가?

그렇게 해야 하는 이유는 유지보수를 위해 코드의 일관성을 유지하고, 다른 사람과의 협업 또는 기능 확장 및 수정에 있어 기존에 동작하는 기능들을 해치지 않기 위함이다.

3. 리스코프 치환 원리의 중요성은 무엇인가?

항상 예외는 존재하지만 리스코프 치환 원리를 중요하게 여기는 이유는 상속, 구현을 사용하면서 상속 관계에 대한 정의를 어기지 않기 위함이라고 생각한다. 부모 클래스의 역할을 이어가면서 추가적인 작업을 할 수 있는 존재이다.

4. AtomicInteger 클래스에서 getAndIncrement 함수는 단일 책임 원칙과 인터페이스 분리 원칙을 준수했는가?

두 원칙 모두 준수하지 못했다고 생각한다. SRP의 경우, 메서드의 규모를 어떻게 보느냐에 따라 준수했다고도 아니라고도 생각할 수 있을 것 같다. 작게 본다면 이름에서부터 get & increment 이지 않은가..?, 하지만 하나의 연산이라고 생각하면 가장 작은 최소의 단위이므로 충분히 잘 준수했다. 하지만 전자의 경우, 이 연산은 특수한 상황이므로 어겨야 하는것이 맞다고 생각한다. Atomic이라는 특성을 지켜야 하므로 당연히 get과 increment 동작을 같이할 수 밖에 없는 것이다. ISP의 경우, 조금 애매하다고 볼 수 있을것 같지만, 이 역시 Atomic이기 때문에 어겼다고 보더라도 어길수밖에 없다는 생각이다. Atomic은 하드웨어에 직접적으로 기반한 메모리 공간이자 변수이기 때문에 여러 계층으로 나눠서 인터페이스화 하여 일괄적으로 관리할 수 없다고 생각한다.

5. Notification 클래스에서 구현이 아닌 인터페이스 기반과 의존성 주입은 서로 유사하다. 그렇다면 이 두 가지의 차이점은?

인터페이스 기반 방법은 인스턴스가 가지고 있는 메서드의 실제 구현 내용을 모르는 것이고, 의존성 주입은 해당 인스턴스에 대한 직접적인 관리를 하지 않는것이 가장 큰 차이점인것 같다.

6. 개발 과정에서 바퀴를 다시 발명하는 행위에 대해 어떻게 생각하는지

바퀴는 모든 사람들이 보편적으로 사용하는 것이다. 다수의 사람들이 보편적으로 사용하는 것을 다시 발명하는 것은 실용성/효율성 측면에 있어서 쓸모 없는 짓이다. 하지만, 다시 발명하는 이유가 바퀴의 탄생 과정을 몸소 겪으면서 얻은 경험을 통한 새로운 발명을 위한 것이라면 가치있는 행위라고 생각한다.

7. 코드의 논리의 중복, 기능적 중복, 코드 실행의 중복 외 또 어떤 형태의 코드 중복이 있을까? 그 코드 중복은 DRY 원칙을 위배하는가?

어렵다. 저거말고 중복을 경험한 적이 없는 것 같다. 두 프로젝트에서 동일한 작업을 하는 모듈을 나누지 못해서 두개가 생긴 적이 있는데, 결국 코드 논리의 중복, 기능 중복, 실행 중복 모두 해당되는 예시인것 같다.