달력

3

« 2024/3 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

좋은 설계를 방해하는 것(= 나쁜 설계임을 알 수 있는 힌트)

design smell

 - rigidity : 딱딱하게 굳었다는 것. 시스템의 의존성 때문에 변경하기 어려워지는 것

 - fragility : 한 모듈의 수정이 다른 모듈에 영향을 미침

 - immobility : 이식(재사용) 어려움


TDD 작성시 테스트가 어렵다면

 -> 내가 좋은 코드를 작성하지 않고 있다는 뜻. 테스트를 나중에 작성했기 때문. 테스트를 먼저 작성해야 쉽다.


<ridigity 보충 설명>

조금 하고 수정 -> 조금 하고 수정 -> 조금 하고 수정

이런 방식의 프로그래밍이 가능하려면, 빌드와 테스트가 잘 돼야 함.

(내 생각 : 빌드나 테스트가 전체를 모두 수행해야 해서 오래 걸리거나, 모듈끼리 의존적이라 단위 테스트가 어려운 경우를 말하는 듯)

테스트 자동화도 되어 있어야 한다.

어쨌든 이런 방식(조금씩 수정 및 확인)으로 프로그래밍을 하려면 rigidity(시스템 의존성)이 낮아야 함.

 -> 이러려면 SOLID를 알아야 함.


<fragility 보충 설명>

런타임 의존성은 유지하지만, 컴파일 타임 의존성을 제거하자.

 -> 이걸 하려면 SOLID를 알아야 함. 그리고 인터페이스로 이렇게 구현할 수가 있다.


<immobility 보충 설명>

재사용 어려움

해결책 : DB, UI, 프레임워크와 결합도를 낮춰야 함.


<Viscosity(점성) 보충 설명>

빌드/테스트 같은 필수 작업이 오래걸리거나 수행이 어려우면 시스템은 역겨운(disgust) 것

역겹다니... 번역이 좀 이상하긴 한데, 이쪽 바닥에선 저 단어를 많이 사용하니 그냥 나도 그렇게 이해하자.


형상관리 브랜치 따려면?

변경이 적은 것을 브랜치를 따야 함.

브랜치를 따 놓고 마구 수정 -> trunc에 머지 -> 머지할 때 수정사항이 많이 발생 -> 사람이 직접 보면서 머지해야 함 -> 실수 발생하기 쉬움 -> 프로젝트 망함

근데 Git이나 Mercurial은 자동 머지가 잘 되고 쉬움. SVN도 3웨이 머지를 지원하지 않다가 현재는 지원하고 있다.


Layered ARchitecture를 사용할 때 상위레이어는 하위레이어를 호출할 수 있다.

(이건 런타임 의존성을 말하는 것. 소스코드 의존성은 없어야 함)



무책임한 용인 : 잘못된거 아는데 안고치는 것. 현실은 바쁘니까 알면서 방치. 근데 이게 모이면 나중에 거대한 똥(?)이 돼서 처리가 무척 힘들어짐.

(내 생각 : 무책임에서도 발생하지만, 무지에서도 발생함)



디자인을 너무 완벽하게 하려 하지 말고

리팩토링을 하다 보니 디자인이 되더라.

 (내 생각 : 신입때 이걸 간접적으로 배운 적이 있는 듯.. 난 스스로 설계능력이 떨어진다고 생각했고(신입이니 뭐 당연한 것이기도 하지만), 겨우겨우 코드를 짜서 잘 돌아가면 그걸로 끝이라고 생각했다. 근데 옆자리 대리님은 짜고나서 갈아엎고, 다시 짜고 하시더라.. 할거 많아 죽겠고, 다시 짜면 더 좋은 코드가 나올 것 같지도 않아서 "저렇게 하는 개발자도 있구나.."라고 개발자의 한 유형이라고 생각하고 대수롭지 않게 넘겼었다. 지금 생각하면 당연히 저런 시도를 했었어야 하는 것 같다.)


이런 변경사항이 나올거야...라고 예측하고 짜지 말 것

변경사항이 나왔을 때, 변경 할 수 있게 만드는 것이 중요함. 디자인패턴이 이런걸 할 수 있도록 도와줌.

당장 실행할 사항은 테스트만 제대로 할 수 있도록 코드를 짜야 한다는 것.


=============================

high level policy가 low level detail에 의존하도록 하지 말자.

절차적인 방법은?

예 : copy 모듈을 구현하려 하는데, 그것이 keyboard와 printer에 의존을 가짐. 근데 장치가 더 늘어나면 의존성이 계속 증가함.

fan-out이 늘어난다고 표현함.

결국 특정 장치를 수정하면 copy 자체도 수정해야 하는 상황이 옴. 의존성을 여기저기서 가지므로 copy는 수정되어야 할 가능성이 큼.

객체지향적인 방법은?

high level policy가 low level detail에 의존 안함.

copy가 getChar putChar 인터페이스에만 의존성을 가짐. 그것을 실제 구현한 keyboard와 printer에는 의존성을 안가짐. 오히려 keyboard와 printer가 getChar putChar에 맞춰 구현해야 하는 의존성을 가진다고 볼 수 있음(즉 low level detail이 high level policy에 의존성을 가진다는 뜻)

이것을 dependency intert(의존성이 역전되었다)라고 한다.


다시 설명하면...

절차지향 : 사용자가 도구라는 클래스에 의존성을 가짐

객체지향 : 사용자가 도구라는 인터페이스에 인터페이스에는 의존하지만 그것을 실제로 구현한 클래스에는 의존성 안가짐. 오히려 인터페이스로 구현했기 때문에 구현클래스가 인터페이스를 따라야 하는 상황. 사용자가 도구에 의존성을 가지던 것과 반대로 도구가 사용자의 인터페이스에 의존성을 갖기 때문에 의존성이 역전되었다고 말하는 것임)


또 다른 좋은 표현 나옴.

 -> flow는 정방향이지만, 디펜던시가 역방향이다. 그것이 dependency inversion이다.


=============================


객체지향은 실세계를 똑같이 모델링 하는 것

객체지향은 메시지를 전달하는 것이다!

Inheritance, Encapsulation, Polymorphism, 재사용은 객체지향의 핵심이 아니라 메커니즘이고, 구현방법일 뿐이다.

객체지향은 IoC를 통해 상위 레벨의 모듈을 하위 레벨의 모듈로부터 보호하는 것.

객체지향 설계란 디펜던시를 잘 관리하는 것. high level policy와 low level detail을 잘 분리하는 것.

 -> 이제 대충 이해 됐으면 SOLID를 공부하자



다형성이란?

약속된 인터페이스에 의해 동작하는 것

 - 어떻게 동작하는지는 모르고

 - 무엇을 원하는지를 전달하는 것



https://youtu.be/HIWJ8sF8lO8?list=PLNbcVkxjS5IfSskzUFpeJLT47p4xcTowG

 -> 여러번 반복해서 볼 가치가 있는 영상...

:
Posted by 클레잇