2021-03-03(Wed)

항목

내용

학습 날짜

2021-03-03(수)

학습 시간

11:00~24:00

학습 범위 및 주제

테스트, 리팩토링

학습 목표

Tournament play 모듈

동료 학습 방법

eunhkim님과 페어코딩함

상세 학습 내용

루비에서 모듈 사용

만약 A가 B 상속을 받은 상태에서 B 클래스에서 인클루드된 모듈 C가 있다면, 아래 순서대로 메서드 탐색이 이뤄진다.

A 클래스 -> B 클래스 -> C 인클루드된 모듈 -> D 클래스 -> ... -> Object

그럼 여러 모듈이 인클루드된다면 메서드 탐색은 어떤 순서대로 이뤄질까? 정답은 '가장 마지막에 인클루드한 모듈을 가장 먼저 탐색한다' 이다. 마치 상속한 것과 비슷한 효과가 생긴다!

모듈을 인클루드한 객체가 특수한 행동을 추가할 수 있게 하려면 템플릿 메서드 패턴을 이용해야 한다. 그리고 훅 메서드를 사용해서 모듈을 인클루드한 객체가 super를 전송하지 않도록 해주어야 한다.

상속 적용이 필요한 안티패턴

작성하는 코드에 상속을 적용하면 좋을 것 같다고 말해주는 두 개의 안티패턴이 있다.

  1. type이나 category와 같은 이름을 가진 벼수가 있고, 이 변수를 가지고 self에 어떤 메시지를 전송할지 결정하는 경우. 이 경우 새로운 타입이 추가될 때마다 코드를 수정해야 한다.

  2. 객체의 클래스를 확인하고 어떤 메시지를 전송할지 판단하고 있다면 오리 타입을 놓치고 있다는 것이다.

상속의 이점

  • 확장에 열려있고, 수정에는 닫혀있다.

  • 제대로 구조화되었다면 코드의 작은 한 부분만 수정해도 행동의 변화를 크게 이끌어 낼 수 있으므로 적절하다.

상속의 비용

  • 상속이 어울리지 않는 문제를 해결하는 데 상속을 사용할 수 있다. 이는 새로운 행동을 추가해야할 때 어려움을 겪게될 수 있다.

  • 일단 상속된 코드는 의존성이 강제된다.

이런 이점과 비용을 고려해서 상속을 선택하자.

올바른 관계 선택하기

  • 무엇이다(is-a) 관계에서 상속사용하기

  • 무엇처럼 행동하는(behaves-like-a) 관계에는 오리 타입을 사용하라.

    • 역할을 수행하는 객체의 관점이 아니라, 역할을 부여하는 객체의 관점에서 생각해보면 쉽다.

  • 가지고 있는(has-a) 관계에서 조합 사용하기

    9장 비용-효율적인 테스트 디자인하기

    대부분의 프로그래머들은 테스트를 너무 많이 짠다. 테스트에서 더 나은 가치를 얻기 위한 방법 중 하나는 테스트를 덜 짜는 것이다. 이를 위해서는 모든 것을 단 한 번만 테스트하고, 제대로 된 곳에서 테스트해야 한다.

    아래 원칙을 지켜보자.

    • 테스트는 객체의 경계를 넘나드는 메시지에 집중해야 한다.

      • 들어오는 메시지들(incoming messages)는 메시지를 수신하는 객체의 퍼블릭 인터페이스를 규정한다.

      • 밖으로 나가는 메시지들(outgoing emssages)는, 그 본성상 다른 객체에 들어가는 메세지이다. 행동을 요청하는 커맨드 메시지와 정보를 전달하는 쿼리 메시지로 나눌 수 있다.

    • 들어오는 메시지에 대해서는 메시지가 반환하는 상태를 테스트하자.

    • 밖으로 나가는 커맨드 메시지에 대해서는 이 메세지가 제대로 전송되었는지 테스트해야 한다.

      • 밖으로 나가는 쿼리 메시지는 테스트할 필요가 없다.

    • 테스트는 실제 코드와 느슨하게 결합되어 있어야 한다.

    • 문제를 스파이크(spike)하면 안 된다는 것은 아니다. 실험을 통해 해결책이 명확히 떠오르지 않는 문제를 이리 저리 탐구해보는 것이다. 문제의 핵심이 보이고 디자인이 떠오르면 테스트를 먼저 작성하는 방식으로 되돌아간다.

      • 스파이크란 일단 테스트 없이 코드를 작성하면서 이것저것 실험해 보는 것이다.

    • 테스트의 의존성을 고립시키기 위해 스텁(stub)이나 목(mock)을 만들 수 있다. 하지만 실제 세계와 다른 가짜 환경을 만들어서 실패해야할 때 실패하지 않을 수 있으니 조심하자.

      • 스텁: 진짜 객체, 메서드는 아닌, 예상된 값을 반환하게끔 만든 임시 객체

      • 목: 행동에 대한 테스트이고, 상태에 대한 테스트와는 반대된다. 적극적으로 의존성 주입 기술을 사용했다면, 목 객체를 넣어서 메시지가 잘 전송되는지 확인해보자.

    • 테스트는 프라이빗 메서드를 숨겨야 한다.

    • 꼭 필요한 최소한의 테스트만 작성하자.

    잘못 디자인되고 테스트도 없는 코드는 그저 테스트할 수 없는 레거시 코드(legacy code)에 불과하다.

    상속 받은 클래스를 테스트할 땐 상속하는 클래스의 테스트를 공통 모듈로 만들어서 인클루드해서 테스트해보자.

학습 내용에 대한 개인적인 총평

Tournament operation 모듈은 PR 완료했고, Tournament play 모듈은 Game 모듈 쪽을 헤드잡고 진행하셨던 eunhkim님이 거진 완료해주셨지만, 테스트 결과 발생하는 문제들이 있어서 함께 해결하였다. 토너먼트 모듈 쪽은 매 시간 실행되는 job을 통해 잘 작동하는지 확인해봐야하는 부분이 있어서 테스트가 좀 어려웠다. 빠른 템포로 동작 가능 여부를 확인할 수 있도록 테스트를 만드는 것이 중요하다.

다음 학습 계획

  • Tournament play 모듈 완성

Last updated