DI는 IoC를 사용하지 않아도 된다

Friday, 17 November 2017 00:00:00 UTC

Dependency Injection(DI)을 얘기할 때 빠지지 않는 글이 있다. Martin Folwer의 Inversion of Control Containers and the Dependency Injection pattern이다. 이 글에서 DI란 용어가 생겨나게된 배경을 볼 수 있다. 관련한 내용을 인용하면 다음과 같다.

When these containers talk about how they are so useful because they implement “Inversion of Control” I end up very puzzled. Inversion of control is a common characteristic of frameworks, so saying that these lightweight containers are special because they use inversion of control is like saying my car is special because it has wheels.

As a result I think we need a more specific name for this pattern. Inversion of Control is too generic a term, and thus people find it confusing. As a result with a lot of discussion with various IoC advocates we settled on the name Dependency Injection.

의존성 조립 임무를 담당하는 컨테이너는 Inversion of Control(IoC) 사용이 당연한 것으로 얘기된다. 자동차가 바퀴를 가져서 특별하다고 하면 어색한 것처럼 말이다. 그래서 좀 더 특별한 이름이 필요해, 많은 사람과 토론한 끝에 DI란 용어를 정했다고 한다.

나는 DI가 IoC 사용을 포함한다는 것에 강한 반감을 가지고 있다. IoC가 없는 DI도 큰 장점을 가지기 때문이다. 이 주장에 대한 근거를 말하기 전에, 먼저 DI와 IoC가 무엇인지 이해할 필요가 있다. 이 둘은 많이 혼돈되는 주제다. 좀 더 명확한 개념을 잡기 위해 Dependency Inversion Principle(DIP)까지 함께 얘기해보도록 하자.

Read more...

Sometimes tell, sometimes ask

Friday, 27 October 2017 00:00:00 UTC

필요한 데이터를 묻기보다, 하고 싶은 걸 말해라는 Tell, Don’t Ask(이하 TDA)라는 원칙이 있다. 필요한 데이터 요청없이 행위를 실행하려면, 행위와 데이터가 함께 있어야 한다. Oriented Object Programming(OOP)은 데이터(필드)와 관련 행위(메소드)를 클래스로 한데 묶는 것이 특징인데, TDA 원칙은 이를 잘 살려주는 도구이다.

아래 UserAccount 클래스는 emailpassword 데이터로 표현되며, 데이터베이스에 사용자 계정을 저장하기 위해 Save라는 행위를 가지고 있다. 데이터를 표현하는 필드, 행위를 의미하는 메소드가 동일 클래스에 위치해서 필요한 데이터를 따로 요청할 필요가 없다. TDA 원칙을 따른 것이다.

TDA 원칙이 OOP의 특징을 살려주는 도구이지만, 다른 시각에서 보면 문제가 있다.

Read more...

Testing, Oh my!

Friday, 20 October 2017 00:00:00 UTC

이 글에서 별도 설명없이 사용되는 테스트라는 용어는 코드로 수행되는 자동화테스트를 의미한다.

예전에 회사 후배가 어떤 코드를 테스트하고 싶은데, 아직 경험과 스킬이 부족해서 힘들다란 말을 했다. 그 후배가 테스트하고자 하는 코드(System Under Test, 이하 SUT)는 테스트하기 어려운 IO 로직에 직접 의존하고 있어 테스트가 거의 불가능했다. 수동테스트 밖에 길이 없었던 것이었다.

테스트에 어려움을 느끼는 초심자의 큰 오해 중 하나는, 그 어려움이 테스트 스킬 부족 때문이라고 생각하는 것이다. 테스트 스킬이 중요하지 않은 것은 아니지만, 그보다 SUT가 얼마나 테스트하기 쉽게 디자인되었는지가 더 중요한 요소이다. 후배의 예처럼 IO 로직 같은 테스트하기 어려운 코드를 직접 참조해버리면 아무리 뛰어난 스킬이 있더라도 손과 눈으로 수동테스트하는 방법밖엔 없는 것이다.

나는 TDD(Test-Driven Development)가 디자인 도구라 생각하지 않는다. 테스트가 디자인을 이끄는 것이 아니라 좋은 디자인이 테스트하기 쉬운 코드를 만든다고 생각한다. 여기서 다뤄지는 내용은 테스트를 먼저 작성하든(TDD), 테스트를 나중에 작성하든 디자인은 그것들보다 먼저 계획된다는 관점에서 기술되었다.

그 후배에게 들려줬던 테스트 방법에 대한 내용을 글로 써봤다. 어떤 코드가 테스트하기 쉬운지 또는 어려운지(Testable Code), 테스트가 쉬운 코드는 어떻게 작성하는지(How to write more testable code), 테스트가 어려운 코드는 어떻게 다뤄야 하는지(Test Humility), 그리고 테스트하기 쉬운 코드와 어려운 코드가 만나게 되는 지점은 어떤 테스트 방법이 있는지(Function Root Testing)에 대한 내용들이다.

Read more...

Function Root Testing

Tuesday, 17 October 2017 00:00:00 UTC

프로그램에서 각 기능 진입점 역할을 하는 함수 또는 메소드를 Function Root란 용어로 소개한 바 있다. Function Root는 대체로 외부세상과 소통하는 IO 작업 담고 있어 테스트하기 힘든 코드로 분류된다. 테스트 비용을 줄이기 위해 테스트 가능한 코드는 Function Root로 부터 분리된다. 따라서 Function Root는 테스트하기 쉬운코드와 그렇지 않은 코드가 만나는 장소를 제공하며, 이들을 어떻게 구성하지가 주된 임무가 된다. Function Root는 순수함수코드와 비순수함수코드 전체를 가로지르는 통합테스트로 검증할 수 있는데, 자동화테스트 비용이 높으면 이를 포기하고 수동테스트로 검증할 수도 있다. 이때 Function Root는 겸손해야 한다.

Read more...

Test Humility

Sunday, 15 October 2017 00:00:00 UTC

이 글에서 별도 설명없이 사용되는 테스트라는 용어는 코드로 수행되는 자동화테스트를 의미한다.

이전 글에서 테스트하기 쉬운코드가 무엇인지 알아보았다. IO 작업과 관련되지 않은 순수함수 형태가 테스트하기 쉬운 코드였다. 순수함수 코드는 입력 값이 같으면 항상 동일한 결과값을 리턴한다. 외부세상을 변경시키는 부수효과 또한 없다. 코드로 수행되는 자동화테스트 검증에 적합한 경우다. 반면 IO 작업과 관련된 비순수함수 테스트는 항상 고비용이 요구되는 것은 아니다. 테스트 비용을 줄일 수 있는 도구들이 속속 등장하고 있기 때문이다. 원격 저장소와 동일한 기능을 로컬 머신에서 실행하고 테스트할 수 있는 에뮬레이터, 설정과 관리비용이 적은 로컬 데이터베이스, 그리고 메모리를 데이터베이스 저장소 활용하여 테스트할 수 있는 도구도 있다. 자동화테스트 검증 비용이 낮아짐으로 기존에 비용이 높아 자동화테스트 범주에 속하지 못했던 코드들이 점차 그 테두리 안으로 들어오고 있다.

테스트 용이성은 상대적인 것이기 때문에 한 편에서 느끼는 테스트 비용부담은 다른 편에선 그렇지 않게 느낄 수 있다. 예를들어 비밀번호 재설정을 위한 메일 발송 시나리오를 생각해보자. 이메일이 잘 발송되었는지 자동으로 테스트하려면 실제 메일서비스에 접속하여 메일이 잘 도착되었는지 코드를 통해 검증해야 한다. 이 검증에 대해 비용이 높다는 사람이 있는 반면, 자동화테스트에서 오는 회귀검증의 실이익이 더 크다고 생각하는 사람도 있다.

Read more...

How to write more testable code

Friday, 13 October 2017 00:00:00 UTC

이전 글에서 테스트하기 어려운 코드와 쉬운 코드를 어떻게 구분하는가에 대해 알아보았다. TDD, Unit Test를 설명하는 글 속에서 만나게 되는 예제는 대부분 테스트하기 쉬운 경우에 속한다. 테스트하기 어려운 코드로 테스트를 쉽게 설명할 수 없기 때문이다. 실제 프로젝트에서는 테스트하기 쉬운 코드만 있는 것이 아니다. 요구사항을 구현하기 위해 메일도 보내야하고 데이터베이스에 데이터를 저장하거나 읽어야 한다. 소프트웨어를 통해 이루려는 것은 필연적으로 외부세상과 소통이 필요하기 때문에 테스트하기 어려운 코드는 피할 수 없다. 우리는 이를 최대한 줄이려고 노력해야 한다. 테스트하기 쉬운 코드를 가능한 많이 작성해야 한다는 뜻이다. 이런 노력은 궁극적으로 테스트에 드는 비용을 최소화하기 위함이다.

Read more...

Testable Code

Monday, 09 October 2017 00:00:00 UTC

이 글에서 별도 설명없이 사용되는 테스트라는 용어는 코드로 수행되는 자동화테스트를 의미한다.

코드로 수행되는 자동화테스트는 모든 시나리오에 적용될 수 없다. 테스트가 어렵거나 경우에 따라 불가능 경우도 있기 때문이다. 사용자가 비밀번호를 잃어버릴 경우에 대비하여, 비밀번호 재설정을 위한 메일을 발송하는 시나리오를 생각해보자. 메일이 잘 발송되었는지 테스트하는 것은 불가능하지 않지만 상당히 어렵다.이 글에서는 무엇이 테스트를 어렵게 만드는지 일반화된 사실로 정리해보고자 한다. 특정 기능을 수행하는 코드를 작성할 때, 같은 동작을 하더라도 테스트가 어려운 코드가 있는 반면, 테스트하기 쉬운 코드가 있다. 우리가 최대한 후자의 경우로 코드를 작성하려면 테스트하기 쉬운코드와 어려운 코드를 구분할 수 있어야 한다.

Read more...

상속은 코드 중복제거를 위한 최후의 보루

Monday, 19 December 2016 00:00:00 UTC

최근들어 주변에서 구성(composition)과 상속(inheritance)에 대해 얘기하는 것을 많이 듣게 되었습니다. 예전부터 구성과 상속에 대해 개인적인 생각을 한번 정리하고 싶었습니다. 이 기회를 빌려 그동안 미뤄왔던 생각을 정리해볼까 합니다.

구성과 상속은 코드 재사용 방법에서 큰 비중을 차지합니다. 이 둘은 코드 재사용 면에서는 공통점이 있지만 클래스 혹은 개체(object) 간 관계를 표현하는 것에는 차이를 보입니다. 구성은 특정 기능의 개체를 가지는 것으로 HAS-A관계를 의미합니다. 반면 상속은 부모에서 구현된 멤버가 자식 클래스를 통해 노출되는 것으로 IS-A관계를 의미합니다. GoF의 디자인패턴 책에서 아래과 같이 상속보다는 구성을 활용하라 는 원칙을 제시합니다. 이 글에서는 왜 IS-A관계보다 HAS-A관계가 좋은지, 어떤 경우에 IS-A관계를 쓸 수 있는지 알아보려 합니다. 결론에서는 HAS-A 사용에 대한 실천적인 방법에 대해서도 살펴보겠습니다.

Faver object composition over class inheritance.

Read more...

TfsBuilder 소개

Thursday, 05 December 2013 00:00:00 UTC

Visual Studio Online에서는 무료로 월 60분의 빌드서비스를 제공하고 있습니다. CI(Continuous Integration)서버를 직접 구축하지 않고 이용할 수 있다는 것이 큰 매리트인 것 같습니다. 무료 월 60분이 좀 적은 시간인 것 같긴 하지만 그래도 이게 어딘가하는 생각이 드네요. 부족 분에 대해서는 분 당 30원의 이용금액을 지불하고 이용할 수 있다고 합니다.(가격정책 참고)

Visual Studio Online에서는 자체 소스리포지토리를 이용할 경우는 CI 빌드를 제공합니다. 즉, 소스를 중앙리포지토리로 push하면 이것을 신호로 서버에서는 빌드작업을 하게 됩니다. 이 빌드작업에 배포작업까지 끼우게 되면 소스 push로만 빌드에서 배포까지 이루어지는 것입니다.

그러나, Visual Studio Online에서 만약 GitHub와 같은 외부 소스 리포지토리를 이용하게 되면, CI빌드를 제공하지 않고, 스케줄 빌드 혹은 매뉴얼(직접)빌드만 제공합니다. 그래서 Visual Studio Online에 대한 빌드 서비스훅을 만들어 보았습니다.

소스와 사용법에 대해서는 GitHub프로젝트 TfsBuilder에 있습니다.


Page 1 of 1