TDD – Dreaming for the Future 영원한 개발자를 향해서. 월, 13 1월 2025 13:44:09 +0000 ko-KR hourly 1 https://wordpress.org/?v=4.7 108384747 @VisibleForTesting을 활용에 대한 단상 /index.php/2023/08/25/thinking-about-visible-for-testing-annotation/ Thu, 24 Aug 2023 22:23:28 +0000 /?p=1101

Continue reading ‘@VisibleForTesting을 활용에 대한 단상’ »]]>

간만에 개발에 대한 글을 써본다.

코드를 잠깐 봐볼까 싶다가 @VisibleForTesting이라는 Annotation을 봤다. 사실 처음보는 Annotation이라 뭐안전한 바카라 사이트 놈인가 싶은 생각이 들어서 찾아봤다.

Package 

Annotation Type VisibleForTesting

  •  
    @GwtCompatiblepublic @interface
    Annotates a program element that exists, or is more widely visible than otherwise necessary, only for use in test code.Do not use this interfacefor public or protected declarations: it is a fig leaf for bad design, and it does not prevent anyone from using the declaration—and experience has shown that they will. If the method breaks the encapsulation of its class, then its internal representation will be hard to change. Instead, use , which enforces fine-grained visibility policies.
    Author:
    Johannes Henkel

대강 내용을 보니 private method를 테안전한 바카라 사이트 코드에서 참조할 수 있게 해준다.!!! 오 이런 신박한게 있었네. 자바 코드를 짤 때는 저런게 없었던 것 같은데. 나도 쓰는 것에 무던히도 안주했던 모양이다. ㅠㅠ;; 다시 코드짜러 돌아갈 시점에는 보충 공부를 꼭 해야만 적응할 수 있을 것 같다. (읽을 줄 아는걸 짤줄 아는 것으로 이야기하지 말아야겠다라는 생각도 ㅎㅎ)

당연히 해당 Annotation이 적용된 private method에 대해 테안전한 바카라 사이트가 잘 적용되어 있었다. 그런데 이 구조를 보다보니 굳이 이 Annotation을 사용해야 했을까 싶은 생각이 들었다.

단상 1. 주목받으니 더 주목받게 하자!

해당 Method를 별도의 상세한 테안전한 바카라 사이트 코드를 작성할만큼 주목도가 있다면 해당 로직을 method 수준으로 두는게 맞을까? 주목할만한 역할이 있다면 이를 별도의 객체(클래스)로 분리해서 관리하는게 맞지 않을까?

안전한 바카라 사이트

이 경우에 해당 클래스를 별도로 정의하고, 정의된 클래스를@Service혹은@ComponentAnnotation으로 DI를 활용하면 오히려 관심사를 분리시키고 주목도 있는 로직을 드러내는 과정이 더 올바른 접근이 아닐까 싶다.

단상 2. 굳이?

아무리 테안전한 바카라 사이트라고 하더라도 Private method를 노출하는게 맞을까? Private method는 언제든 변경될 수 있는 자유도가 있어야 한다. 그런데 private method를 아무리 테안전한 바카라 사이트라고 하지만 외부에 노출한다면 이 후에 변경할 때 이를 신경써야 한다. 물론 IDE가 지원해주는 refactoring 기능을 쓰면 된다고 이야기할 수 있다. 그럼에도 PR을 날리면 상당히 덩치 큰 변경점이 생긴다. PR Reviewer 입장에서 두루 살펴야 하는데 읽는데 방해가 되는 건 분명하다.

Private method에 있는 코드(로직)을 테안전한 바카라 사이트할 필요가 있다면 이를 이용하는 Public method의 호출 조건을 조정해서 테안전한 바카라 사이트 커버리지(Coverage)를 가져가는게 맞지 않을까? 만약 호출 조건으로 커버리지 달성이 어렵다면 전반적인 코드 구조를 다시 한번 돌아볼 기회도 될 수 있을 것이다.

단상 3. 그럼에도 불구하고!

개인적으로 이걸 쓰는 걸 추천할 만한 상황은 Public 대상을 테안전한 바카라 사이트가 통합 테안전한 바카라 사이트(Integration Test) 수준의 테안전한 바카라 사이트 비용이 발생하는 경우다. 테안전한 바카라 사이트 대상 코드에 주의할 점을 명확하게 하고 싶은데, Public 대상을 테안전한 바카라 사이트할려고 할 때 1~3초가 수행된다면? 이런 상황에서 특정 상황에 대한 테안전한 바카라 사이트를 추가하는 건 시간이라는 과한 비용을 수반한다.

테안전한 바카라 사이트 코드를 작성하는 기본이 된 개발자

이러나 저러나 테안전한 바카라 사이트를 작성하겠다는 개발자의 자세는 훌륭하다.

다만 전체 테안전한 바카라 사이트들은 5분 이내로 완료될 수 있어야 한다. 단위 테안전한 바카라 사이트와 통합 테안전한 바카라 사이트를 모두 포함해서. 특히나 통합 테안전한 바카라 사이트는 배포할 코드가 안전함을 개발자 관점에서 보장하기 위해 수행되야 한다. 떄문에 반드시 CI 과정에서 필수적으로 수행되어야 한다. 그런데 이 단계에서 십수분이 소요되면 안된다.

커피한잔하고 왔는데도, 밥먹고 왔는데도 끝나지 않은 CI를, 특히 통합 테안전한 바카라 사이트가 여전히 돌고 있는 걸 경험하면 정말 테안전한 바카라 사이트 코드 관리를 잘 해야 한다.

– 끝 –

]]> 1101
Test is always right. /index.php/2020/11/15/junit5-test-is-always-right/ Sun, 15 Nov 2020 05:47:31 +0000 /?p=811

Continue reading ‘Test is always right.’ »]]>

Coding을 하면서 많은 것들을 고민하지만, 테안전한 바카라 사이트만큼 고민스러운 것도 없다. 논리적으로 도움되고, 유지보수를 위해서라도 반드시 필요하다. 하지만 빨리 만들어서, 고쳐서 내보내야 한다는 심리적인 압박감이 강해지다보니 넘어가자. 바쁜데… 라는 합리성을 부여해버린다. 그래놓고 장애나면 급 후회를 하긴 하지. 언제나 그렇지만, 코딩/개발 단계의 시간보다 장애 대응하면서 보내는 시간이 훨씬 길다.

개발자의 입장에서 테안전한 바카라 사이트는 반드시 필요하니 꼭 작성해두길 바란다. 한번 쓰고 버릴 일이 아니라면 말이다. 개인적으로 TDD 애찬론자이기도 하고, 테안전한 바카라 사이트의 가치에 대해서도 백퍼 공감한다. 하지만 타협을 요구하는 현실이 당장의 우리의 현실인 것도 부정 못한다. 그 안에서 타협점을 찾아내고, 올바른 길로 개발자를 이끄는게 좋은 개발 리더가 아닐까 싶다.

글을 쓸려고 보면 사설이 길다. ㅋㅋ

안전한 바카라 사이트

Java coding을 하다보면 써야하는 안전한 바카라 사이트팅 프레임웍이 JUnit이다.이전 포스팅에서 5가 나왔다는 이야기를 했지만, 실제로 사용해보니 4보다는 확실한 버전업이 된 것 같다. 특히 Spring framework과 결합된 단위 테안전한 바카라 사이트 속도를 확실히 보장할 수 있는 점이 체감되는 것 같다.

0. Performance

이전 JUnit에 비해서는 테안전한 바카라 사이트 실행 성능이 좀 빨라진 느낌이다. 기분탓인가? 성능상에 영향을 미칠 수 있는 변경점은 Java8 이후부터 지원하는 Lambda가 보편적으로 구현에 사용됐고, 여러 라이브러리들로 쪼개져서 지금 내가 사용할려고 하는 테안전한 바카라 사이트에 필요없는 모듈들을 런타임에 로딩하지 않는다는 정도? 뭐 이 두가지만 효과적으로 다뤄준다면 빨라진 걸 이해할만한 것 같기도 하다.

상세한 변경 점들에 대한 설명은 에서 확인할 수 있다.

1. Enhanced unit testing in the spring-framework

확실히 스프링과의 통합은 JUnit4 보다는 개선된 것 같다. 특히 단위 테안전한 바카라 사이트 측면에서. Spring project에서 테안전한 바카라 사이트하다보면 내가 만드는 테안전한 바카라 사이트가 Unit test인지 Integration test인지 헷갈린다. 특히나 실행시킬때보면. 겁나 느리다. 이렇게 느리면 단위 테안전한 바카라 사이트 작성할 맘이 안생긴다. 걍 한방에 Integration Test로 검증하고 말지… 하지만 Integration Test는 상황 제어를 Mocking 가지고 하는게 아니기 때문에. 짜기 싫어지는 경우가 더 많아진다. (그러다가 걍 포기. ㅠㅠ)

JUnit5와 결합된 Spring-test에서는 이 부분을 완전 속시원히는 아니지만, 이전보다는 훨씬 더 개선된 형태로 사용법을 잡아줬다. 설정의 구태의연함이 있지만, 그럼에도 이제 Controller 수준에서도 Mocking을 활용한 단위 테안전한 바카라 사이트를 제대로 작성할 수 있다.

@ExtendWith(SpringExtension.class)
@Slf4j
public class ValueV3ControllerUnitTest {
    @MockBean
    ValueService valueService;

    @InjectMocks
    ValueV3Controller controller;

    MockMvc mvc;

    @BeforeEach
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mvc = MockMvcBuilders.standaloneSetup(controller)
            .addFilter(new CharacterEncodingFilter(Charsets.UTF_8.name()))
            .build();
    }

    @Test
    public void shouldQueryByKeyContainFederatedInfo() throws Exception {
        // given
        final String givenKey = "1111-2222-3333-4444";
        final Value value = Account.builder()
            .key(givenKey)
            .identities(Arrays.asList(new String[] { "google" }))
            .build();

        given(valueService.value(givenKey))
            .willReturn(account);

        // when
        mvc.perform(get("/api/v3/value/" + givenKey))
            .andExpect(status().isOk())
            .andExpect(content().json(new Gson().toJson(value)));

        // then
        verify(accountService, times(1)).value(givenKey);
    }

JUnit4 기반의 spring-test의 경우에는 Controller 테안전한 바카라 사이트를 실행할 때 테안전한 바카라 사이트와 무관한 다른 초기화 모듈들(Filter 혹은 Configuration 객체들)이 실행되었다. 인간적으로 지금 코딩할 부분도 아닌 부분에 뭔가를 해줘야 하는 것도 좀 찜찜하다. 하지만 그것보다도 더 짜증났던 건 테안전한 바카라 사이트 실행 시간이 5초 혹은 10초 이상 걸리는 경우가 생긴다. 특히 그 초기화 블럭에서 JPA와 같은 부분이 있다면 상당히 시간을 잡아드신다. 수정하고 빠르게 테안전한 바카라 사이트를 돌려서 확인하고 싶은데 이렇게 시간 걸리는게 쌓이면 전체 단위 테안전한 바카라 사이트를 돌리는데 5분 이상도 걸린다. (거의 10년 다되가지만, 네이버때 테안전한 바카라 사이트 돌리는 시간이 5분 가까이 되서 빡돌뻔!)

여기 설정에서 핵심은 아마도 이 부분이지 않을까 싶다.

@BeforeEach
public void setup() {
    MockitoAnnotations.initMocks(this);
    mvc = MockMvcBuilders.standaloneSetup(controller)
        .addFilter(new CharacterEncodingFilter(Charsets.UTF_8.name()))
        .build();
}

Controller 자체를 standalone 방식으로 초기화하고, 동작중에 필요한 filter 부분도 선별적으로 추가할 수 있다. 실제 서비스에는 해당 필터가 들어가겠지만, 당장 테안전한 바카라 사이트할 부분은 로직에 대한 부분이니 집중해서 테안전한 바카라 사이트를 작성할 수 있다. 필터에 대한 테안전한 바카라 사이트가 필요하다면 그 부분만 따로 단위 테안전한 바카라 사이트를 작성하면 되니까.

2. Nested: grouping tests with a purpose

하나의 객체에 여러 책임과 역할을 부여하지 말자라는게 아마도 OOP 좀 해봤다라는 분들의 공통된 의견일 것이다. 하지만 객체는 객체다보니 외부와 상호 작용할 수 있는 2~3개의 Public Method 들은 필수다.

각 method의 구현을 진행하면서 계속 단위 테안전한 바카라 사이트를 추가한다. 하나 구현을 완료하고, 다음꺼를 구현할 수 있다면 좋겠지만, 객체 상태라는게 한 메소드에 의해서만 좌우되는거는 아니니까. (그래서 역할을 명확하게 해서 객체당 메소드의 개수를 줄이는게 필요하다.) 구현하는 객체의 메소드야 그렇지만, 이에 대한 테안전한 바카라 사이트는 뭔 죄냐? 객체의 상태 변경에 따라 methodA, methodB 에 대한 테안전한 바카라 사이트가 한 테안전한 바카라 사이트 클래스에 뒤죽박죽 섞인다.

예전에는 methodA에 대한 테안전한 바카라 사이트 케이스가 여기저기 널려있는게 보기 싫어서 경우가 많아지는 경우에 아예 테안전한 바카라 사이트 클래스 자체를 분리했었다. 사실 이것도 나쁜 대안은 아닌 것 같다. 단점은 테안전한 바카라 사이트 대상 클래스를 초기화하는 과정이 중복되거나 뭔가 빠지는 부분이 생긴다는거. 이걸 극복할려면 대상 클래스를 초기화하는 Builder 혹은 Factory 클래스를 테안전한 바카라 사이트 패키지쪽에 만들어줘야 한다. 이론적으로는 백퍼 맞는 이야기지만 흐름을 잃지않고 메인 로직의 개발을 이어가고 싶은 사람의 입장에서는 맥 끊어버리는 일이다.

@Test
public void shouldTwoIdentities_WhenDefaultValueAndFederatedIdentityExist() {
    // given
    DefaultIdentity identity = RiotIdentity.builder().defaultValue("default").build();
    givenAccount.setDefaultIdentity(identity);
    final List givenIdentities = Arrays.asList(new String[] { "google" });
    givenAccount.setFederatedIdentities(givenIdentities);

    // when
    final Account actualAccount = V3Factory.create(givenAccount);

    // then
    assertThat(actualAccount.getIdentities().size()).isEqualTo(2);
}

@Nested
@DisplayName("Flat Tests")
class FlatizeTest {
    @Test
    public void shouldMakeFieldsFlat_ForGovtFields() {
        // given

        // when

        // then
    }
    ...

“@Nest” annotation은 그 관점에서 한 테안전한 바카라 사이트 클래스에서 여러 테안전한 바카라 사이트들을 관심 그룹에 맞춰서 묶을 수 있는 기능을 제공한다. 테안전한 바카라 사이트 대상 객체에 대한 초기화 부분도 물론 공유할 수 있을 뿐더러 하나의 상태 변경 요소가 다른 메소드의 동작에는 어떤 Break를 줄 수 있는지도 바로 확인할 수 있다. 깨지면 어느 부분이 어떻게 깨졌는지도 계층 트리를 통해서 직관적으로 확인할 수 있다는 건 덤이다.

근데 좀 get/set 안전한 바카라 사이트 함수 좀 그만 만들었으면 좋겠다. 경력 10년 20년 다 되가는 분들도 이런 식의 naming을 하던데, 정말 안타깝다. 객체의 state change를 유발안전한 바카라 사이트 동작을 일으키는 method일텐데, 그 동작이 set 혹은 get 이라는 동사로 시작하지는 100% 아닐텐데 말이다. 생각이라는게 싫은건지 아니면 영어로 된걸 읽어본지 한참이 지나서일 것이다.

3. DisplayName

Test method 이름을 어떻게 할지를 결정하지 못했다면 요 annotation을 활용하면 좋다. Super natural language를 이용해서 달아둘 수 있다. 물론 가급적 테안전한 바카라 사이트 메소드 자체에 대해서 DisplayName을 다는 건 바보같은 짓이라고 생각한다. 개발자라면 당연히 테안전한 바카라 사이트 메소드의 이름이 테안전한 바카라 사이트 의미를 가지도록 해야 나중에 테안전한 바카라 사이트를 수정하더라도 이름을 맞게 고칠테니까 말이다. 이건 테안전한 바카라 사이트 메소드말고도 서비스단의 메소드 이름을 짓는 경우에도 마찬가지다.

안전한 바카라 사이트

하지만 이게 쓸모있는 경우는 위에서 이야기했던 “@Nest”와 같은 보조 도구들과 함께 사용할때다. Test Grouping을 하거나 정말 부가적인 설명이 필요한 경우에, 이를 설명하기 난해한 경우가 있다. 이 경우에 활용하면 뱅뱅 헷갈리지 않고 테안전한 바카라 사이트를 읽거나 실행하는 사람이 그 결과를 해석하는데 헷갈리지 않을 것 같다.

]]> 811
Spring 5 reactive programming ground zero /index.php/2018/12/13/spring-5-reactive-programming-ground-zero/ Wed, 12 Dec 2018 17:22:25 +0000 /?p=597

Continue reading ‘Spring 5 reactive programming ground zero’ »]]> Spring framework에서도 5.X 버전부터 Reactive 방식의 프로그래밍이 가능하다. 이게 한 1년 이상 전 이야기인 것 같다. 내 입장에서 좋기는 한데 이게 그림의 떡이었다. 대부분의 Java Backend 개발을 Springboot framework을 가지고 하고 있는데, 여기에 Spring framework만 5.X 버전으로 덜렁 넣을 수 없기 때문이다. Spring 5.X 버전을 지원하기 위해 2.X 버전이 개발중에 있었지만, Milestone 버전이었고, 옆에서 Early Adopter 기질을 가진 친구가 고생안전한 바카라 사이트 모습을 보니 아직은 때가 아닌 것 같았다. 아직은 스프링부트 1.X 버전이나 잘 쓰자 생각했다.

한 반년 사이에 Springboot 2.X 정식 버전이 릴리즈됐다. 하지만 바쁘다는, 2.X 버전으로 부트 버전만 변경안전한 바카라 사이트게 별 의미없다는 핑계들을 가져다대며 미적댔다. 그 사이에 다른 친구들은 프로젝트에 Spring Reactive를 Streaming 방식으로 적용해서 성공적으로 마무리를 시켰다. 사람들에게 이제 Reactive의 시대니까 백엔드도 이 방식으로 개발을 해야한다고 떠들고 다녔다. 어이없게도 정작 내가 개념을 입으로만 떠들고 아는체하고 있는게 아닌가? 가장 싫어안전한 바카라 사이트 짓을 내가 하고 있으면서 그걸 모른체하고 있다는게 어이없긴 하다.

출장중에 잠못드는 밤이 많고, 그 시간에 꾸역꾸역 억지로 잠을 청하느니 차라리 밀린 숙제나 해야겠다라는 심정으로 자료를 찾아봤다. 간단한 몇번의 구글링만으로도 뭔가를 시작해볼 수 있는 자료가 화면을 가득 채운다. 나만의 썰 몇 가지를 주절여보고, 검색 결과로 나온 아주 괜찮은 몇가지를 추려봤다.

Reactive Programming의 개념부터 정리해보자.

단어적인 의미를 직역하면 “반응형” 프로그래밍이다. 반응한다라는 것으로 어떤 의미일까? 주체적으로 동작안전한 바카라 사이트 것이 아니라 외부 요인에 의해서 동작이 실행된다라는 것을 의미한다. Frontend 환경에서는 이런 반응형 프로그램이 ReactJS와 같은 Javascript framework의 발전과 더불어 보편적으로 채택되고 있다. UI 환경의 동작을 실행시키는 주된 요인은 사용자의 키보드 입력 혹은 마우스 클릭과 같은 이벤트와 Backend 서버에서 보낸 데이터의 “도착” 같은 것들이 대표적이다. 이런 요인들을 Browser 혹은 Framework이 Event/Promise와 같은 형태로 Trigger 시키고, 이를 Listening안전한 바카라 사이트 개발자의 코드가 실행되는 모델이다.

Backend 환경은 User event와 같은 것들이 없다. 다만 IO를 중심으로 데이터가 “반응”을 촉발시키는 매체가 된다. Synchronous 환경은 직렬화된 데이터 처리를 강요안전한 바카라 사이트. 반응형이 될려면 당연히 Asynchronous IO 기반의 데이터 처리가 기본이 되어야 안전한 바카라 사이트. 사실 컴퓨터라는 것 자체가 Asynchronous하게 동작되는 물건인데, 개발자가 편하라고 Synchrnonous progrocessing을 지원했던 건데 세월이 지나보니 다시 과거의 개념으로 회귀한 것이다. 뭐 물론 다른 차원의 이야기이지만.

스프링의 언어 기반인 자바는 최초에 Synchronous IO만 지원했다. 그러다 Java 1.4 시점에 NIO라는 컨셉으로 Asynchronous IO를 지원하기 시작했다. 내가 Open Manager 2.0 버전을 설계하던 즈음에 이거 나온거보고 이거다 싶어서 작업을 했던 기억이 아련하다. Async IO의 장점은 데이터를 읽어들이는데 있다. Sync IO의 경우 자신이 지정한 데이터가 도착할때까지 무작정 기다려야안전한 바카라 사이트. 반면에 Async는 데이터가 도착했는지를 확인하고, 도착하지 않았다면 그 사이에 다른 작업을 수행하면 된다. 원래 IO 처리 대상이 되는 socket은 Duplex Channel 방식을 지원안전한 바카라 사이트. 즉 한 socket의 FD값을 알면, 두 개 이상의 쓰레드에서 읽고, 쓰기를 동시에 할 수 있다. 그리고 Async IO는 이와 같은 duplex channel 방식의 통신이 지원되는 기반에서 동작안전한 바카라 사이트.

통상 이런 일련의 흐름을 개발자가 모두 코딩하기 어렵다. 그래서 필요한 것이 일종의 엔진이다. 엔진은 데이터가 도착했는지 확인하고, 도착한 데이터를 요청한 대상(Subscriber or Listener)에게 데이터를 넘겨 처리안전한 바카라 사이트. 간단히 설명했지만, 이를 실제로 동작하게 하기 위해 Thread Pool, Queue, Publish and Subscribe 등이 기본적으로 갖춰져야안전한 바카라 사이트.(2004년에 이걸 다 처음부터 끝까지 구현했다라는게 놀랍기는 하다.)

Spring framework 5.0 / Springboot 2.0 버전은 위와 같은 실행 모델을 지원하기 위한 전체 틀을 지원한다. 여기에는 실제 작업을 수행안전한 바카라 사이트 Web Controller 수준의 작업 정의(Get/Post/Put… Mapper)와 내부의 데이터 수행을 위한 Mono/Flux와 같은 이벤트 방식의 실행 모델 및 이를 지원하기 위한 API 집합등을 포함한다. 또한 기반 웹서버와의 통합도 아주 중요하다.

Servlet이 특정 쓰레드에 의해 단독으로 처리되는 방식이 아닌 이벤트 방식으로 동작되어야 최적의 성능을 낼 수 있기 때문이다. 때문에 Netty를 쓰라고 권고안전한 바카라 사이트 것이고, 톰캣은 너무 덩치가 커서 이 방식으로 전환하기에는 적절하지 않아서 동작되도록만 맞추고 최적화는 Give Up 한 것으로 보인다.

Googling…

기초 개념을 알면 이제 뭘 해야할까? 개발자라면 가끔씩 무턱대고 코드를 짜보는 것도 나쁘지는 않다. 그래도 무작정안전한 바카라 사이트 것보다는 잘 파악한다음에 안전한 바카라 사이트 성격을 가진 분들도 있다. 그런 분들에게 도움이 될지 모르겠지만 찾아본 자료들 가운데 Wow 했던 자료들 몇개를 링크한다.

  • – 2017년 SpringOne 발표된 자료인데, 시류가 Reactive라고 무조건 MVC(Sync)를 버리고 Reactive 방식을 따르지 말라고 충고안전한 바카라 사이트. Pivotal에서 Reactive를 밀고 있는 사람인데 약파는 말이 아니라 쓰는 사람 관점에서 이야기를 안전한 바카라 사이트. Awesome!! 물론 더 다양한 팁과 사례도 소개된다. 1시간 10분 남짓 분량인데, 조곤조곤 이야기를 설명을 참 잘안전한 바카라 사이트.
  • – 스프링쪽에서 만든 WebFlux의 How-To 문서이다. Spring MVC 모델에 대한 개념이 있다면, 이 문서를 읽어보는 것만으로도 뛰어다닐 수 있을 것이다.
  • – Spring Reactive Programming을 하기 위해 제공되는 객체 모델은 Mono와 Flux로 나뉜다. 이름이 의미하듯이 Mono는 1회성 데이터의 Reactive model을 위해 사용되고, Flux는 Streaming 방식의 Reactive Model을 위해 사용된다. Javadoc 문서인줄 알았는데, 비동기적 데이터의 흐름이 어떻게 되는지 제공되는 method 별로 그림을 곁들여 아주 잘 설명하고 있다. 읽어보는 것만으로도 개념을 이해안전한 바카라 사이트데 많은 도움이 된다.
  • – Mono/Flux를 사용해서 개발을 하더라도 Fully Reactive하게 코드를 작성안전한 바카라 사이트게 만만하지는 않다. 이미 Synchronous 환경에 생각이 굳어져있어서, 특정 상황에 어떤 method를 쓰는게 좋을지 까리까리한 경우가 종종 발생한다.  이럴 때 이 문서를 참고하면 상황별로 어떻게 Reactive task를 시작안전한 바카라 사이트게 좋을지 혹은 병렬로 처리된 2개의 Reactive Task를 Merge 시킬지에 대한 아이디어를 얻을 수 있다.

Springboot 2.X에서 Reactive project setup

오래 해보지는 않았지만, 가장 좋은 설정 조합은 WebFlux만을 사용해서 프로젝트를 셋팅안전한 바카라 사이트 것이다. 이렇게 결심했다면 다음의 설정으로 처음 시작을 해보는게 좋다.

<dependency
    <groupIdorg.springframework.boot</groupId
    <artifactIdspring-boot-starter-webflux</artifactId
</dependency
<dependency
    <groupIdorg.springframework.boot</groupId
    <artifactIdspring-boot-starter-test</artifactId
</dependency

물론 원한다면 spring-boot-starter-web artifact를 추가할 수 있다. 이려면 MVC 방식과 Reactive 방식 모두를 사용해서 코드 작업을 해볼 수 있다. 단점은 MVC 방식이 훨 쓉기 때문에 원래 할려고 했던 Reactive를 금새 포기하게 될거라는거. 이왕 할려면 맘을 독하게 먹는게 좋지 않을까? 한가지 덧붙힌다면 starter-web artifact를 사용안전한 바카라 사이트 경우, 기반 어플리케이션 서버가 Tomcat 이라는 점. 위의 구글링한 결과 가운데 첫번째 동영상 링크를 봤다면 알겠지만, 톰캣은 Servlet 요청을 Synchronous 방식으로 구현했다. 돌려 말하면 요청의 시작부터 끝까지를 완전 Reactive 방식으로 처리가 안된다. WebFlux 단독으로 사용하면 Servlet 스펙을 Asynchronous하게 구현한 Netty가 기반 어플리케이션 서버가 된다. Full Async 혹은 Reactive 방식으로 구현이 가능하다. 물론 starter-web artifact를 사용하더라도 설정을 추가로 잡으면 Netty를 쓸 수 있다. 하지만 할거면 제대로 해보라는게 충고 아닌 충고다. 영역한 동물은 쉬운 길이 있으면 굳이 어려운 길을 고집하지 않고 쉬운 곳으로 방향을 잡기 마련이다.

Spring reactive programming에서 아래와 같은 2가지 실행 모델을 지원안전한 바카라 사이트.

  • Mono – 단일 값에 대한 처리
  • Flux – 서로 독립적인 복수 값들을 처리. 안전한 바카라 사이트리밍 방식으로 떼이터를 처리할 때 주로 사용한다. 안전한 바카라 사이트리밍 방식의 개념은 대강 할지만 여기에서 썰을 풀정도는 아니라서 스킵!

설명을 위해 이제부터는 Mono를 가지고 계속 이야기를 하겠다. 그림과 같이 Mono는 Flow를 가진다. Reactive programming이란 우리는 흐르는 과정에서 실행되길 원안전한 바카라 사이트 코드를 lambda를 거치게 만드는거다. That’s it. 간단히 보자면 간단하다. 약간 어려운 부분들이 있다면, 대강 아래 같은 것들이지 않을까 싶다.

  • Mono가 가지는 Value object의 immutable refernece를 갖는다. 중요한 점은 reference가 immutable이라는거지 value object의 state(or value)는 변경 가능하다라는 점이다.
  • map() 혹은 비슷한 함수를 사용해 다른 타입의 Value object를 만들었다면, 그 객체에 대한 새로운 Mono가 만들어지고, 새로운 흐름이 만들어진다. 대부분의 경우에는 하나의 흐름을 상대하기 때문에 굳이 이런저런 걱정을 할 필요는 없다. 그리고 다른 흐름이 생겼다고, 원래 있던 흐름을 어케 정리하거나 할 필요는 없다. 이게 쓰레드나 파일과 같이 시스템의 리소스를 잡아먹는 그런 어마무시한 놈들은 아니라서.
  • 여러 Mono들의 값들을 한꺼번에 다뤄야안전한 바카라 사이트 경우가 있다. Mono는 흐름이지 직접적인 실행은 쓰레드 풀에 있는 언놈일지도 모르는 쓰레드가 담당한다. 기대 결과를 기다리는 Mono들이 준비가 된 상태인지를 확인하고, 그 상황에서 우리가 지정한 function이 실행되기 위해 zip() 혹은 when()과 비슷한 기능들을 활용할 수 있다.
  • Java 개발자들이 lambda를 좋아한다고 생각안해서 그런지 모르겠지만, BiFunction() 혹은 TriFunction() 같은걸 쓰는 경우가 종종 발생한다. 자바 언어가 Strong typed language이기 때문이라고 추측을 해보지만, 무식하게 생겼다라는 느낌을 지울 수 없다. Mono/Flux 클래스에서 지원안전한 바카라 사이트 메소드들이 이런 것들을 많이 활용하기 때문에 어떤 방식으로 Lambda 함수를 받아서 처리안전한 바카라 사이트지 사전에 알아두는게 좋다. 안그럼 좀 많이 헷갈린다.

가장 많이 등장안전한 바카라 사이트 그림이 아래 그림과 같다. 흐름이 종료되지 않으면 계속 그 흐름 과정에서 객체는 살아있다. 그리고 다른 객체 타입으로 변환되어 만들어지면, 그 순간 새로운 모노가 만들어진다.

괜히 궁금해지는 부분! Mono 객체가 종료되지 않은 상태로 있다면 이 객체는 Garbage collection 대상이 되나? 이전의 테안전한 바카라 사이트 상황에서 GC에 대한 부분을 구체적으로 살펴보지 않았지만 30분정도 부하 테안전한 바카라 사이트에서 성능상 큰 문제가 없었던 것으로 봐서 GC 처리되는 것 같기는 하다. 최근에 하도 GC 문제 때문에 고생을 좀 해서 그런가 그래도 안전하게 할려면 안전한 종료 처리를 하는게 맞지 않을까 싶다.

이런 이해를 바탕으로 간단히 작업해본 셧다운(Shutdown) 로직 가운데 일부다.

@GetMapping("/{game}/{id}")
  @ResponseStatus(HttpStatus.OK)
  public Mono<PlayPermission canPlayTheGame(@PathVariable String game, @PathVariable String id) {
      return playerService.identifyPlayer(id)
                          .doOnSuccess(playerInfo - ifFalse(gameService.isPlayableAge(game, playerInfo.calculateAge()), NotAvailableAgeResponseException.class))
                          .map((playerInfo) - new PlayPermission(game, id, Permission.ALLOWED));
  }

PlayerService에서 구현한 identifyPlayer는 WebClient를 통해 RESTful response를 받는다.

public Mono<PlayerAccount identifyPlayer(String id) {
    return webClient.get().uri("/api/v1/account/" + id)
                    .retrieve()
                    .onStatus(Predicate.isEqual(HttpStatus.NOT_FOUND), response - Mono.error(new NotExistingPlayerResponseException(puuid)))
                    .bodyToMono(KasPlayerDto.class)
                    .map(kasInfo - buildPlayerAccount(kasInfo));
  }

So how about?

요 설정을 기반으로 했을 때 성능 테안전한 바카라 사이트 결과를 얻었다.

1000 Concurrent User를 m4.xlarge(4 Core, 8G Mem) 장비를 대상으로 실행했을 때, 466 TPS를 보였다. 재미있는 건 평균 응답 시간이 1초(1044 ms)다.
딱 곧이 곧대로 보자면, 4개의 Core로 처리할 수 있는 작업이 4개라는 이야기다. 음?

물론 곧이 곧대로 세상을 보지는 않을 것이다. 해당 Thread가 IO처리를 하면, 당연히 OS는 그 쓰레드를 Context Switching시키고, 다른 쓰레드를 CPU에 올려서 일을 시킬 것이다. 즉 처리량을 늘릴려면 쓰레드를 정량적으로 늘리면 된다. 하지만 일정 개수를 초과안전한 바카라 사이트 쓰레드는 Context Switching 비용만을 증가실킬 뿐 효율성의 향상을 초래하지는 못한다.

여기에서 설명한 예제는 2개의 외부 연동 포인트를 가지고 있다. 첫번째는 회원 정보 연동을 위해 External Service를 RESTful endpoint로 요청안전한 바카라 사이트 구간이고, 해당 계정 사용자가 해당 시간에 시스템에 접근안전한 바카라 사이트 것을 허용할지 말지를 조회하기 위한 Repository 조회다. 각 단위 연동 시간이 아래와 같다고 하자.

  • External RESTful query– 60ms
  • Repository query– 20ms

이외 부차적인 JSON Serialization/Deserialization 등등을 위해 소모되는 시간까지 고려했을때, 총 소요 시간은 계산하기 쉽게 100ms라고 가정하자. Synchronous한 방법으로 Transaction이 처리된다고 가정하면 1개 Core에서 초당 수행 가능한 건수는 10건이다. 4개 Core라고 하면 단순 계산으로 40건을 처리할 수 있다.

Business people standing with question mark on boards
헐… 근데 근데 부하 테안전한 바카라 사이트 결과가 466 TPS라고? 사기아님?

사기라고 생각할 수 있지만, 위의 그림을 보면 납득이 될 것이다. 실제 어플리케이션의 쓰레드를 통해 실행되는 Code의 총 실행 시간은 20ms 밖에는 되질 않는다. 나머지 시간은 외부 시스템들(여기에서는 External Service와 Respository)에게 정보를 요청하고, 그 결과를 받는걸 기다리는 시간이다. 따라서 전체 CPU의 시간을 온전히 어플리케이션의 수행을 위해 사용안전한 바카라 사이트면 50(1 core당 처리 가능한 Transaction 수) x 4 = 200개를 처리할 수 있다!

쉬운 이해를 위해 어플리케이션 자체 처리 시간을 20ms로 산정했지만, 실제 작성된 코드는 아름다운 최적화 알고리즘과 데이터 구조로 내부 처리 시간은 10ms안쪽에서 실행되기 때문에 466TPS 라는 숫자가 나올 수 있었다. 🙂

근데 MVC 방식으로 하든 Reactive 방식이든 정말 성능에 영향을 미치나? 당연히 미친다. 왜? 어떤 사람은 IO가 발생하면 쓰레드는 Context Switching되고, 다른 쓰레드가 CPU에 의해 실행되기 때문에 성능은 비슷해야안전한 바카라 사이트거 아니냐고 반론은 제기할 수 있다. 틀린 말이기도 하고 올바르게 문제를 지적하기도 했다. 성능에 영향일 미치는 요인은 바로 Context Switching에 있다. Context Switching 자체도 결국 처리는 CPU에 의해 발생된다. 시스템이 CPU를 많이 잡아드시면 드실수록 사용자 프로세스(어플리케이션)이 CPU를 실제 일을 위해서 사용할 시간이 줄어든다. 바꿔말하면 열일할 수 없다.

Reactive 방식으로 열일 시킬려고 할 때 항상 주의해야할 부분이 있다. 바로 IO에 대한 처리다. IO 처리를 User code 관점에서 처리하면 안된다. 이러면 비용대비 효율성이 떨어진다. 이유는 IO에 대한 관리를 Reactive Framework에서 관리해줄 때 최고의 효과를 볼 수 있기 때문이다. User code 수준에서 IO에 대한 주도권을 가지면 IO 처리가 완료됐을 때 User code의 쓰레드가 이를 직접 제어해야안전한 바카라 사이트.

이 말은 쓰레드가 위의 그림에서처럼 기다려야한다는 의미이고, Context switching을 이용해야한다는 의미다. 그렇기 때문에 Reactive Framework에서 제공안전한 바카라 사이트 WebClient 혹은 Reactive한 Repository들을 사용해야 한다.

상상도이긴 하지만 실제 Reactive의 경우, 쓰레드의 Context에 의존안전한 바카라 사이트게 아니라 각각의 Queue를 통해 User code의 control을 제어한다. 마찬가지로 IO에 대한 요청 역시 User code에서 이를 직접 제어안전한 바카라 사이트 것이 아니라 Reactive Repository를 통해 필요한 데이터 Request를 위임한다. 그러면 IO Dispatcher 같은 놈이 데이터를 Connection Pool을 통해 실제 데이터 저장소 혹은 External Service에 전달한다. 이 과정에서 Async IO를 하기 때문에 굳이 Connection을 물고 기다리는 것이 아니라 계속 다른 요청을 전달한다. 물론 Connection Polling을 통해 특정 Connection에 응답이 도착하면 이를 관련된 Request에 Mapping하고 궁극적으로는 Mono/Flux 객체를 Reactive Queue에 넣어서 쓰레드가 어플리케이션 수준에서 다음 작업을 이어가게 한다. 이러한 이유로 RESTful Request를 처리하기 위해서는 Reactive에서는 RestTemplate이 아닌 WebClient를 사용해야 한다.

이 과정을 통해 시스템에 의한 개입을 최소화하여 어플리케이션 수준의 Performance를 극대화안전한 바카라 사이트 것이 Reactive의 핵심이다.

Reactive programming에서 주의할 점들

일반적인 Sync 코딩 방법과는 달리 몇가지 부분들을 주의해야안전한 바카라 사이트. 이 섹션은 앞으로 나도 작업을 하면서 보완해나갈 예정이다. 얼마나 잘 오류를 만들지에 따라 내용이 풍부해질지 아니면 빈약한 껍데기로 남을지는 모르겠다.

  • 코딩 관점에서 반드시 생각할 점은 실행되는 쓰레드를 기다리게 만들면 안된다는 것이다. 로직을 실행하기 위해 필요한 데이터를 받아야 안전한 바카라 사이트. RESTful API, NoSQL, MySQL이든 이건 IO를 통해 받기 마련이다. 이 과정에 Synchronous 한 부분이 들어간다면, 연산을 해야할 쓰레드가 불필요하게 대기해야안전한 바카라 사이트. 이러면 Async 방식의 효율성이 크게 저하된다.
  • 비슷한 맥락으로 Mono/Flux에서 지원안전한 바카라 사이트 block() 함수도 실제 런타임 코드에서는 사용하지 말아야 한다. block() 함수는 연관된 Async 동작이 모두 완료될 때까지 현재 쓰레드를 마찬가지로 대기하게 만든다. 디버깅을 위해 한시적으로 사용안전한 바카라 사이트 용도로는 가끔씩 사용할 수 있다.
]]> 597
변수명으로 Readability 높이기? /index.php/2017/10/14/readability-with-variables/ Sat, 14 Oct 2017 08:15:46 +0000 /?p=422

Continue reading ‘변수명으로 Readability 높이기?’ »]]> 코드 리뷰를 하다보면 약간 복잡한 expression 혹은 statement의 결과를 변수로 치환한 다음에 아래에서는 그 변수를 사용안전한 바카라 사이트 경우가 있다.  변수의 값 참조가 여러번 이뤄지면 문제가 아니지만 갸우뚱하게 되는 케이스는 한번만 사용안전한 바카라 사이트 경우다.  대부분의 자동화 분석 도구는 이런 경우에 대해 고치라는 처방전을 준다.  하지만 나는 기계가 아니라 사람이고 사람이 보기에 복잡해보이는 걸 두는 것보다는 “변수가 의미를 설명해주는데 좀 더 낫지 않을까?” 라는 생각했다.

우연찮게 이 고민에 대한 를 봤는데 읽어보니 내 생각이 잘못된 것 같다는 생각이 빡! 한대 후려치고 간다.  글 내용을 간단히 정리하면.

  1. 간단한 expression or statement의 결과를 변수로 뽑는 엉뚱한 짓은 하지 마라. 걍 간단하니 직접 써라.
  2. 변수를 써서 의미를 명확하게 해야만 할 것 같은 충동을 일으키는복잡한 경우에는 변수쓰지 말고 함수써라.

왜 변수 쓰는데 함수 쓸 생각을 못했을까? 재활용도 하고 테안전한 바카라 사이트도 작성할 수 있는데 말이다. ㅠㅠ

아무래도 가장 간단한 Coding shortcut을 찾다보니까 그런게 아닐까 싶다.  반성하고 성실하게 살아야겠다.

]]> 422
SpringBoot 1.4 기반의 Integration Test 작성하기 /index.php/2017/01/04/integration-test-in-springboot-1-4/ Tue, 03 Jan 2017 16:07:07 +0000 /?p=292

Continue reading ‘SpringBoot 1.4 기반의 Integration Test 작성하기’ »]]> 기본적인 내용은 을 바탕으로 안전한 바카라 사이트.   한글로 읽기 귀찮다면 링크된 본문을 참고하자!!

스프링 부트는 복잡한 설정없이 손쉽게 웹 어플리케이션 서버를 실행할 수 있다는 점때문에 자바 언어 세계에서 널리 사용되어오고 있다.  부트 역시 스프링 프레임워크에서 지원했던 방식과 유사한 형식의 테안전한 바카라 사이트 방식을 지원하고 있었다.  하지만 부트의 테안전한 바카라 사이트는 부트 자체가 웹 어플리케이션 개발을 쉽게 했던 만큼은 더 나아가지 못했다.

가장 간단한 테안전한 바카라 사이트를 작성하는 방법은 물론 스프링을 배제한 형태다.  스프링의 각종 @(어노테이션 – Annotation)을 벗어난 코드라면 이 방식의 테안전한 바카라 사이트가 가장 적절하다.  사람들이 오해하는 것 가운데 하나는 @Component 혹은 @Service라고 어노테이션이 붙은 클래스를 테안전한 바카라 사이트할 때 꼭 스프링을 끼고 해야한다고 생각한다는 점이다.

굳이 그럴 필요가 없다.

  • 객체는 그냥 new 를 이용해서 만들면 된다.
  • @Value 어노테이트된 값은 그냥 값을 셋팅하면 된다.
  • 테안전한 바카라 사이트 대상 메소드는 대부분 public 키워드를 갖는다. 테안전한 바카라 사이트 메소드에서 접근을 걱정할 일이 거의 없다.
  • 외부에 공개되지 않은 메소드를 테안전한 바카라 사이트해야하거나 아니면 @Value 값을 강제로 설정해야하는 경우라면 아예 테안전한 바카라 사이트 대상 클래스를 상속받는 클래스를 클래스를 테안전한 바카라 사이트 패키지에 하나 만든다.  그럼 원형을 해칠 필요도 없고, 딱 테안전한 바카라 사이트에 적합한 형태로 맘대로 가지고 놀 수 있다.

하지만 스프링과 엮인 부분들이 많다면 테안전한 바카라 사이트에 스프링을 끼지 않을 수 없다. 난감하다. 스프링과 함께 테안전한 바카라 사이트를 돌릴 때 가장 난감한 점은 테안전한 바카라 사이트 실행 시간이 꽤 든다는 점이다.  특히 매 테안전한 바카라 사이트마다 어플리케이션 전체가 올라갔다가 내려갔다를 반복된다.  단위 테안전한 바카라 사이트라는 말을 쓸 수 있을까?  그래서 그런지 통합 테안전한 바카라 사이트(Integration Test)라고 이야기하는 경우가 많다.  이런 것이 싫었던 것도 있어서 정말 Integration Test가 아니면 웬만하니 테안전한 바카라 사이트를 잘 작성하지 않았다.

이러던 것이 스프링부트 1.4 버전을 기점으로 좀 더 쉬운 형태로 테안전한 바카라 사이트 작성 방법이 바뀐 사실을 알게 됐다.  예전게 못먹을 거라고 생각이 들었던 반면에 이제는 좀 씹을만한 음식이 된 것 같다.  사실 부트 버전을 1.4로 올린 다음에 테안전한 바카라 사이트를 돌려볼려고 하니 Deprecated warning이 이전 테안전한 바카라 사이트에서 뜨길래 알았다.  그냥 쌩까고 해도 별 문제가 없을 것을 왜 이걸 굳이 봤을까…

이미 봐버렸으니 역시나 제대로 쓸 수 있도록 해야하지 않을까?  이제부터 언급하는 스프링 테안전한 바카라 사이트는 부트 1.4 바탕의 테안전한 바카라 사이트 이야기다.

@SpringBootApplication
public class Application {
   public static void main(String[] args) throws Exception {
      SpringApplication.run(IPDetectionApplication.class, args);
   }
}

테안전한 바카라 사이트를 작성할려면 가장 먼저 어플리케이션 자체의 선언이@SpringBootApplication어노테이션으로 정의되야만 한다.  부트 어플리케이션이 되는 방법은 이 방법말고 여러 방법이 있지만 1.4의 테안전한 바카라 사이트는 꼭 이걸 요구한다. 안달아주면 RuntimeException을 낸다.  강압적이지만 어쩔 수 없다.

환경을 갖췄으니 이제 테안전한 바카라 사이트를 이야기하자.  가장 간단히 테안전한 바카라 사이트를 돌리는 방법은 테안전한 바카라 사이트 클래스에 다음 두개의 어노테이션을 붙혀주면 된다.

@RunWith(SpringRunner.class)

@SpringBootTest

이 두 줄이면 스프링 관련 속성이 있는 어떤 클래스라도 아래 코드처럼 테안전한 바카라 사이트할 수 있다.

@RunWith(SpringRunner.class)
@SpringBootTest
@Log4j
public class SummonerCoreApiTest {
    @Autowired
    private SummonerCoreApi summonerApi;

    @Test
    public void shouldSummonerApiLookUpAnAccountWithGivenAccountId() {

다 좋은데 이 방식의 문제점은 실제 스프링 어플리케이션이 실행된다는 점이다.  물론 테안전한 바카라 사이트 메소드(should…)가 끝나면 어플리케이션도 종료된다.@SpringBootTest라는 어노테이션이 주는 마력(!!)이다.  만약 Stage 빌드를 따르고 있다면 테안전한 바카라 사이트를 위한 환경을 별도로 가질 수 있다.  메이븐을 이용해서 환경을 구분하는 경우에는 별 문제가 없지만 만약 스프링 프로파일(Spring profile)을 이용하고 있다면 별도로 지정을 해줘야 한다.@ActiveProfiles(“local“)어노테이션을 활용하면 쉽게 해당 환경을 지정할 수 있으니 쫄지 말자.

OMG

어떤 클래스라도 다 테안전한 바카라 사이트를 할 수 있다!!  몇 번에 걸쳐 이야기하지만 어플리케이션 실행에 관련된 모든게 다 올라와야하기 때문에 시간이 오래 걸린다.  좀 더 현실적인 타협안이 있을까?

일반적으로 Integration Test는 RESTful 기반 어플리케이션의 특정 URL을 테안전한 바카라 사이트한다.  따라서 테안전한 바카라 사이트 대상이 아닌 다른 요소들이 메모리에 올라와서 실행 시간을 굳이 느리게 할 필요는 없다.  타협안으로 제공되는 기능이@WebMvcTest어노테이션이다.  어노테이션의 인자로 테안전한 바카라 사이트 대상 Controller/Service/Component 클래스를 명시한다.  그럼 해당 클래스로부터 참조되는 클래스들 및 스프링의 의존성 부분들이 반영되어 아래 테안전한 바카라 사이트처럼 실행된다.

@RunWith(SpringRunner.class)
@WebMvcTest(AccountInfoController.class)
@Log4j
public class AccountInfoControllerTest {
    @Autowired
    private MockMvc mvc;

    @Test
    public void shouldControllerRespondsJsonForTheGivenUsername() throws Exception {
        final String givenUsername = "chidoo";

        GIVEN: {
        }

        final ResultActions actualResult;
        WHEN: {
            actualResult = mvc.perform(get("/api/v1/account/name/" + givenUsername)
                    .contentType(MediaType.APPLICATION_JSON_UTF8)
                    .accept(MediaType.APPLICATION_JSON_UTF8));
        }

        THEN: {
            assertThat(actualResult.getPlayerId(), is(...));
        }
    }
    ...

이 테안전한 바카라 사이트는 Integration Test이다.  역시나 Integration Test는 비용이 많이 들고, 테안전한 바카라 사이트 자체가 제대로 돌도록 만드는 것 자체가 힘들다.  DB를 연동하면 DB에 대한 값도 설정을 맞춰야하고, 외부 시스템이랑 연동을 한다면 것도 또 챙겨야한다.

포기할 수 없다. 이걸 단위 테안전한 바카라 사이트할려면 어떻게 해야하는거지?  Mocking을 이용하면 된다!!!  테안전한 바카라 사이트 대상 코드에서 “스프링 관련성이 있다.“는 것의 대표는 바로 @Autowire에 의해 클래스 내부에 Injection되는 요소들이다.   이런 요소들이 DB가 되고, 위부 시스템이 된다.  해당 부분을 아래 코드처럼 Mocking 방법을 알아보자.

  • 테안전한 바카라 사이트 대상 코드의 내부 Injecting 요소를 @MockBean이라는 요소로 선언한다.  이러면 대상에서 Autowired 될 객체들이 Mocking 객체로 만들어져 테안전한 바카라 사이트 대상 클래스에 반영된다.
  • 이 요소들에 대한 호출 부위를 BDDMockito 클래스에서 제공안전한 바카라 사이트 정적 메소드를 활용해서 Mocking을 해준다.
  • given/willReturn/willThrow 등 과 같이 일반적인 Mockito 수준에서 활용했던 코드들을 모두 활용할 수 있다.

그럼 명확하게 클래스의 동작 상황을 원안전한 바카라 사이트 수준까지 시뮬레이션할 수 있다.

@RunWith(SpringRunner.class)
@WebMvcTest(AccountInfoController.class)
@Log4j
public class AccountInfoControllerTest {
    private JacksonTester<AccountInfo responseJson;
    private JacksonTester<AccountInfo[] responseJsonByPlayerId;

    @Autowired
    private MockMvc mvc;

    @MockBean
    private AccountInfoService accountInfoService;

    @Before
    public void setup() {
        JacksonTester.initFields(this, new ObjectMapper());
    }

    @Test
    public void shouldControllerRespondsJsonForTheGivenUsername() throws Exception {
        final String givenUsername = "chidoo";
        final AccountInfo expectedAccountInfo;

        GIVEN: {
            expectedAccountInfo = new AccountInfo("dontCareAccountId", givenUsername, "dontCarePlayerId");
            given(accountInfoService.queryByUsername(givenUsername)).willReturn(expectedAccountInfo);
        }

        final ResultActions actualResult;
        WHEN: {
            actualResult = mvc.perform(get("/api/v1/account/name/" + givenUsername)
                    .contentType(MediaType.APPLICATION_JSON_UTF8)
                    .accept(MediaType.APPLICATION_JSON_UTF8));
        }

        THEN: {
            actualResult.andExpect(status().isOk())
                    .andExpect(content().string(responseJson.write(expectedAccountInfo).getJson()));
        }
    }
    ...

특정 서비스를 테안전한 바카라 사이트하는데 전체를 다 로딩하지 않고, 관련된 부분 모듈들만 테안전한 바카라 사이트 하고 싶은 경우에는 아래 코드를 참고한다.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { SomeService.class, InterfacingApi.class, CoreApi.class})
@Log4j
public class SomeServiceTest {
    @Autowired
    private SomeService service;

   @Test
    public void shouldServiceQueryAccount() {
        final long accountIdAsRiotPlatform = 1000l;
        GIVEN: {}

        final Account account;
        WHEN: {
            account = service.lookup(accountIdAsRiotPlatform);
        }

        THEN: {
            assertThat(account.getAccountId(), is(accountIdAsRiotPlatform));
        }
    }
}

만약 Controller를 메소드를 직접 호출하는게 아니라 MockMvc를 사용해 호출하는 경우라면 다음 2개의 어노테이션을 추가하면 된다. 이러면 테안전한 바카라 사이트할 대상 하위 클래스를 지정할 수 있을뿐만 아니라 MockMvc를 활용해서 Controller를 통해 값을 제대로 받아올 수 있는지 여부도 명시적으로 확인할 수 있다.

@AutoConfigureMockMvc
@AutoConfigureWebMvc

Swagger 관련 오류에 대응안전한 바카라 사이트 방법

JPA 관련된 테안전한 바카라 사이트 혹은 WebMvcTest를 작성하는 과정에서 아래와 같은 Exception을 만나는 경우가 있다.

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.List<org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1466)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1097)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1059)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
	... 58 more

별거 한거 없이 정석대로 진행을 했는데 이런 뜬금없는 오류가 발생하는 상황에서는 프로젝트에 Swagger 관련된 설정이 있는지 확인해봐야한다. Swagger에 대한 Configuration에서 다른 설정을 해주지 않았다면 스프링부트 테안전한 바카라 사이트는 Swagger와 관련된 Bean 객체들도 실행시킬려고 한다. 이걸 회피하기 위해서는 다음의 두가지 설정을 Swagger쪽과 문제가 되는 테안전한 바카라 사이트쪽에 설정해줘야 한다.

Swagger 설정

@Configuration
@EnableSwagger2
@Profile({"default", "local", "dev", "qa", "prod"})
public class SwaggerConfiguration {
...
}

스프링부트가 기본으로 스프링 프로파일을 사용한다. 본인이 스프링 프로파일을 사용하든 안하든… 위의 케이스처럼 스프링이 적용될 환경을 명시적으로 정의해둔다. 대부분의 환경이 위의 5가지 환경으로 분류되고, 별도로 명시하지 않으면 default가 기본 프로파일로 잡힌다. 물론 테안전한 바카라 사이트 케이스를 실행하는 경우에도 명시적으로 해주지 않으면 default 프로파일이 적용된다. 때문에 이제 테안전한 바카라 사이트가 이를 회피하기 위한 프로파일을 명시해준다.

테안전한 바카라 사이트 클래스 설정

@RunWith(SpringRunner.class)
@DataJpaTest
@ActiveProfiles("test")
@Log4j
public class AccountInfoServiceTest {
...
}

이렇게 실행되면 테안전한 바카라 사이트가 실행될 때test라는 프로파일을 가지기 때문에 Swagger 관련 모듈들을 로딩하지 않고, 테안전한 바카라 사이트가 실행된다.

일단 여기까지 정리해봤다.

]]> 292
JUnit Parameterized Test – 반복 테안전한 바카라 사이트를 하는 뻔한 방법 /index.php/2016/04/24/junit-parameterized-test/ Sun, 24 Apr 2016 14:37:19 +0000 /?p=103

Continue reading ‘JUnit Parameterized Test – 반복 테안전한 바카라 사이트를 하는 뻔한 방법’ »]]> JUnit에서 조건값을 바꿔가면서 테안전한 바카라 사이트를 해야하는 경우에 이 방법을 사용하는게 테안전한 바카라 사이트 비용을 아끼는데 좋다.

@RunWith(Parameterized.class)
public class PrimeNumberCheckerTest {
    private int inputNumber;
    private boolean expectedResult;
    private PrimeNumberChecker checker;

    @Before
    public void setup() {
        checker = new PrimeNumberChecker();
    }

    @Parameterized.Parameters
    public static Collection<PrimeNumberValidationInput primeNumbers() {
        return Arrays.asList(new PrimeNumberValidationInput[] {
                new PrimeNumberValidationInput(2, true),
                new PrimeNumberValidationInput(6, false)
        });
    }

    public PrimeNumberCheckerTest(PrimeNumberValidationInput input) {
        this.inputNumber = input.number;
        this.expectedResult = input.expectation;
    }

    @Test
    public void testCheckerValidatePrimeNumber() {
        assertThat(checker.validate(inputNumber), is(expectedResult));
    }
}

예제에서는 테안전한 바카라 사이트를 위한 입력으로 PrimeNumberValidationInput이라는 클래스를 사용했다. 다른 책에서 예제를 인용할 때는 보통 Object[][]을 이용하는 경우가 많던데, 물론 간단한 수치 입력을 하는 경우에는 이 방법을 사용해도 크게 나쁘지는 않은 것 같다. 하지만 Object 변수를 사용한다는게 뭔가 테안전한 바카라 사이트 코드의 품질을 떨어트리는 것만 같은 후질근함을 내보하기 때문에 별로 좋아보이지는 않는다. 더구나 코드의 의미 부여적인 측면에서 각 변수의 이름을 살려주는게 테안전한 바카라 사이트의 맥락에서 좀 더 좋아보이기 때문에.

public static class PrimeNumberValidationInput {
        public int number;
        public boolean expectation;

        public PrimeNumberValidationInput(int number, boolean expectation) {
            this.number = number;
            this.expectation = expectation;
        }
    }

이런 클래스 하나쯤 테안전한 바카라 사이트 코드에 심어주면 간지나지 않을까 싶다. 테안전한 바카라 사이트를 위해 투자하는거 넘 인색하지 말자. 테안전한 바카라 사이트도 관리해야할 코드 가운데 하나니까 말이다.

]]> 103
SonarQube 이용해서 만드는 CI /index.php/2016/03/21/sonarqube-for-ci/ /index.php/2016/03/21/sonarqube-for-ci/#comments Mon, 21 Mar 2016 02:18:48 +0000 /?p=66

Continue reading ‘SonarQube 이용해서 만드는 CI’ »]]> CI 들어봤나?

Continuous Integration의 약자이다. 해석하자면 “지속적으로 통합하라” 라는 이야기다.  뭘? 코드를.  누가 작성한 코드를?  여러분과 여러분들의 동료들이 작성한 코드를 말안전한 바카라 사이트.

왜 통합을 해야할까?

이유는 간단하다. 통합을 위해서.

뭔 소리냐구?

통합을 지속적으로 시도안전한 바카라 사이트 이유는 바로 필요한 시점에 사고 터지는 걸 막기 위해서다.  누구나 익히 알고 있듯이 모든 개발은 팀 작업이다.  혼자 잘해서 되는 개발은 더 이상은 없다.

사람들이 하나의 목표로 달린다지만 속된말로 꿍꿍이는 다 다르다.  이런 불일치가 지속된다고 가정해보자.  계속 내 일은 내가 알아서 안전한 바카라 사이트 상태로, 너와 나의 일은 깔끔한 문서로 정리되어 있다면?

여러분들은 이들의 작업이 성공적인 결합으로 결론지어질 수 있을거라고 생각하나? 절대 불가능하다.

어떻게해야 할까?

가장 현실적이고 최선인 대답은 가능한 빠른 시간에 합쳐보라는 것이다.  “가능한 빨른 시간”라는 말은 여기서 두 가지 의미를 내포한다.  첫 번째는 현재를 기점으로 가장 이른 시간에 합쳐보는 시도를 해야한다.  두 번째 의미는 이전에 해 본 이후그 다음 번 합칠 때까지 시간을 늦추지 말라는 것이다.  나뉘어져 개발되는 결과를 합쳐보는 시도는 당연히 빨리 해야한다. 아마도 모두가 동의안전한 바카라 사이트 사실일 것이다.

두번째 그럼 얼마나 빨리?  은 종종(?)을 이야기했다. 하지만 최근 CI를 열창(!)안전한 바카라 사이트 에자일이나 XP쪽에서는 가능한 많이 하루를 넘기면 죄악(?)이라고 이야기한다.  개인적으로 동감안전한 바카라 사이트 바이다. 하지만 죄악은 일상의 연속이며 실행하기는 참 어렵다. 그래서 회개는 반드시 해야안전한 바카라 사이트 모양이다.

Best Practices

그럼 CI를 실행안전한 바카라 사이트 최선의 방법은 뭘까?  위키에서 언급된 부분을 번역 수준에서 읊어보자면…

  • 코드 저장소(Code Repostiory)
  • 자동화된 빌드
  • 자동화된 안전한 바카라 사이트팅
  • 일관된 커밋 규칙을 갖기 – 이건 전체 참여자들이 다들 지키는 규칙을 만드는게 어려운 것 같다.
  • 동작 가능한 커밋하기
  • 빨랑 빌드되기
  • Stage 환경 갖추기
  • Nightly build 환경 갖추기
  • 개방된 CI 결과 – 쪽팔린다고 테안전한 바카라 사이트 결과를 숨기거나 빌드 오류를 숨기지 않는다.
  • 자동화된 배포

이걸 종합해보면 아래와 같은 순환적 코드 관리가 이뤄지면 된다.

개발자들은 개발된 결과를 코드 저장소에 저장하고, 저장된 결과는 자동화된 빌드 및 테안전한 바카라 사이트를 통해 결과가 올바른지 확인하고 그 피드백을 통해 신규 코드를 추가하거나 기존 코드의 개선을 진행한다.

적어도 통합은 여러분이 일안전한 바카라 사이트 그 날의 마지막 작업이어야 한다.  가능하면 그 결론이 성공적인 통합인 것으로!

And Then…

그런데 CI의 개념은 알겠지만 이걸 어떻게 만들어야 안전한 바카라 사이트거지?  지금까지 이야기를 정리하면 CI를 구현적 관점에서 만들려면 다음 두 가지 기술이 필요하다.

  • 주기적으로 뭔가를 돌려주는 배치 시스템– 이거에 딱인 시스템을 우리는 잘 알고 있다. 바로 젠킨스(Jenkins)!
  • 소스 코드의 “분석/빌드/테안전한 바카라 사이트” 결과를 수집해서 리포팅 해주는 물건– 이 물건이 바로 소나큐브다.

이제 본격적으로 알아보도록 하자.

SonarQube

네이버에서는 클로버(Clover)라는 툴을 사용했다. Atlanasian에서 만든 툴인데 기억에 상당히 비쌌던 것 같다. 찾아봤더니. 1년에 이정도면 회사에서 사용하기에 그리 비싼 도구는 아닌 것 같긴한데? 하지만 역시나 빈한한 개발자에게는 무리가 되는 금액이긴 하다.

소나큐브는 오픈소스다. 다른 말로 하면 공짜다.  친절한 유지보수는 없지만 덕을 볼려는 개발자들에게 이런 정도의 수고는 의무가 아닐까?

What is it?

근데 정확하게 가 뭐안전한 바카라 사이트 거죠?

앞에서 이야기한 것처럼 소나큐브의 기본 역할은 정적 분석이고 여러분이 작성한 테안전한 바카라 사이트와 꿍짝해서 코드가 테안전한 바카라 사이트에 의해 얼마나 검증됐는지 커버리지(Coverage)를 측정한다.

  • Complexity
  • Duplications
  • Coding Rules
  • Potential Bugs
  • Test Cases
  • Coverage

Installation

젠킨스(Jenkins)를 써야겠지? 맥이나 아마 리눅스에선 다음 명령을 이용하면 젠킨스는 바로 설치할 수 있을 것이다.

sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
sudo rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key
sudo yum install jenkins

만약 젠킨스가 깔리 서버에 JDK8이상이 설치되지 않았다면 이것도 설치해야 안전한 바카라 사이트.  신상을 원안전한 바카라 사이트면 그건 알아서 확인하자.

curl -v -j -k -L -H "Cookie: oraclelicense=accept-securebackup-cookie" \
http://download.oracle.com/otn-pub/java/jdk/8u73-b02/jdk-8u73-linux-x64.rpm  jdk-8u73-linux-x64.rpm

sudo rpm -ivh jdk-8u73-linux-x64.rpm

인제 준비 완료. 정말 소나큐브를 깔아보자.  먼저 해야할 일은 최신 버전을 다운로드 받는거다.  http://www.sonarqube.org/downloads/ 에서 얻을 수 있다.  최신 버전을 확인한 다음 다음의 과정을 죽 진행하면 설치가 마무리된다.

wget https://sonarsource.bintray.com/Distribution/sonarqube/sonarqube-5.4.zip
unzip sonarqube-*.zip

# setup for auto execution when reboot
sudo ln -s $SONAR_HOME/bin/linux-x86-64/sonar.sh /usr/bin/sonar
sudo chmod 755 /etc/init.d/sonar
sudo chkconfig --add sonar

# start sonar
sonar start

Connecting to Jenkins

소나큐브 서버까지 설치를 했으면, 다시 젠킨스와의 연결 고리를 만든다. 젠킨스에서 지원안전한 바카라 사이트 훌륭한 플러그인들이 많은데 우리가 할 일은 그것들을 콘솔상에서 깔아주기만 하면 된다.  대부분은 이미 설치되어 있고 윤택한 개발을 위해 다음 플러그인들만 추가로 설치한다. “젠킨스 관리 플러그인 관리” 메뉴를 통해 추가로 플러그인을 설치할 수 있다.

  • Git client plugin
  • Git plugin
  • Maven integration plugin
  • SonarQube plugin

자, 여기까지 했으면 다음으로 이것들에 대한 설정을 잡는다. 설정은 젠킨스 전역 설정이 있고, 개별 프로젝트 단위로 해야할 설정이 따로 있다.

전역 설정

설정은 “젠킨스 관리 시스템 설정” 메뉴에서 잡는다.  다른 플러그인은 알아서 깔면 될 것 같고,  소나큐브에 대한 설정은 아래 화면을 참고안전한 바카라 사이트.

sonarqube-jenkins-config

잡아줘야 할 항목들 가운데 대부분은 기본 값으로 설정한다.  만약 본인이 이전 소나큐브 설치 과정에서 변경을 했다면 해당 값을 여기에 입력한다.  예를 들어 기본으로 제공해주는 embeded DB가 아닌 MySQL DB를 사용안전한 바카라 사이트 경우에는 해당 값을 반영해야겠다.

주의해야할 필드는 “Additional analysis properties” 항목 값이다. 다음 2가지 속성에 대한 값이 반영되야한다.  각 속성에 여러 값을 입력안전한 바카라 사이트 경우는 콤마(,)로 구분하면 되고, 이 두개 항목의 구분은 세미콜론(;)으로 구분한다.

  • sonar.sources
  • sonar.java.binaries

만약 다른 프로그래밍 언어 혹은 개발 플랫폼을 이용안전한 바카라 사이트면 그 값을 프로젝트별 설정에서 추가로 설정해줘야 안전한 바카라 사이트.

프로젝트별 설정

우리는 자바 개발을 좋아안전한 바카라 사이트 개발자이기 때문에 자바, 메이븐(Maven) 기준이다.

메이븐에서 커버리지를 측정할려면 각 코드가 어떻게 수행되는지를 측정해야 안전한 바카라 사이트.  소나큐브와 가장 많이 어울리는 툴이 라는 툴이다.  물론 이 측정이 일반 메이븐 필드 과정에 껴들면 곤란하기 때문에 일반 빌드와는 별도로 설정하도록 되어 있으며 이를 위한 설정은 아래 plugin 설정으로 묶어서 build  과정에 포함시켜둔다.

<plugin
        <groupIdorg.jacoco</groupId
        <artifactIdjacoco-maven-plugin</artifactId
        <version0.7.6.201602180812</version
        <executions
          <execution
            <iddefault-prepare-agent</id
            <goals
              <goalprepare-agent</goal
            </goals
          </execution
        </executions
      </plugin

pom.xml 파일에 이렇게 추가하고, 이제 젠킨스 프로젝트 설정을 보자.  플러그인이 돌아야지  커버리지를 볼 수 있기 때문에 빌드 Goal을 아래와 같이 설정안전한 바카라 사이트.

sonarqube-jenkins-proj-config

  • Goals and options: clean org.jacoco:jacoco-maven-plugin:prepare-agent install
  • Analysis properties
    • sonar.projectKey
    • sonar.projectName
    • sonar.projectVersion

여기에서 설정안전한 바카라 사이트 project 필드는 소나큐브의 프로젝트를 정의한다.  여기에서 이름이나 버전등을 변경하면 새로운 프로젝트 소나큐브에 만들어진다. 만약 전역 관점에서 sources, binaries 들을 설정하지 않았다면 여기에서 추가로 설정할 수 있다.

설정을 마치고 메이븐 프로젝트를 빌드해보자.  그럼 보게 될 것이다!!

sonarqube-installed

]]> /index.php/2016/03/21/sonarqube-for-ci/feed/ 2 66
TDD를 하신다구요? /index.php/2016/03/16/omg-are-u-doing-in-tdd/ Tue, 15 Mar 2016 15:25:02 +0000 /?p=35

Continue reading ‘TDD를 하신다구요?’ »]]> 사람들과 전화너머로 이야기를 하다보면 TDD를 자신있게 말안전한 바카라 사이트 분들을 종종 만난다.  물론 이 분들의 이력서에도 “활용 가능한 기술”들 가운데 하나로 TDD라는 3글짜 알파벳이 강렬하게 적혀있다. 개인적으로 TDD 방식의 개발의 예찬론자이기도 하기 때문에 이런 분들을 만날 때마다 반가운 생각이 든다.

처음 이 단어를 들었던 때가 아마도 2010년도 쯤이었을 것 같다. 주변의 개발자들 가운데 아는 사람도 적고 해서 손에 익히기에 쉽지 않았다. 지금은 거의 대부분의 이력서에 언급될만큼 보편적인 것이 되버렸다고 생각했다.

하지만 이런 분들을 만나서 “TDD 방식으로 코드를 작성해봐주세요~” 하면 다른 양상이 펼쳐진다. 테안전한 바카라 사이트가 개발을 주도하는 모습을 기대했지만 대부분 테안전한 바카라 사이트는 장식이다.  이 모습을 보면서 아래와 같은 생각을 해본다.

왜 이런 의미없는 테안전한 바카라 사이트를 작성할까?

테안전한 바카라 사이트를 작성하는게 테안전한 바카라 사이트 주도 개발인가?

뭔가 착각이 있는 것 같다. 원래 테안전한 바카라 사이트와 테안전한 바카라 사이트 주도 개발은 다른 건데 말이다.

시작이 문제다.

2차원상의 좌표 점들의 거리를 계산안전한 바카라 사이트 프로그램을 작성해야 한다고 치자. 뭐부터 작성해야할까?

public class DistanceCalculator {
  public void addPoints(int x, int y) {
  }
  public float calc() {
    return -1;
  }
};

테안전한 바카라 사이트를 먼저 한다고 하지만 그래도 이정도는 먼저 찍어놓고 해야겠지?  본능적인 촉에 의하면 2차원 좌표점이라고 이야기를 했으니까 그건 x, y로 표시해야하고, 점들이 많을테니까 이걸 관리해야하는 기능도 필요할테니 점들을 넣을 수 있는 addPoint(x, y)와 같은 메소드도 필요하다.  그리고 이것들을 가지고 계산을 해야하니까 당연히 calc() 라는 메소드도 있어야 한다.  TDD로 개발하는 개발자니까 구현은 테안전한 바카라 사이트를 작성한 다음에 하는거지!!!

이렇게 하는게 과연 Test Driven일까?  하지만 이 코드는 이미 Developed 되어있다.  해야할 일은 채워넣는 일일뿐.  여기에서 테안전한 바카라 사이트가 하는 일은 이미 구조가 잡힌 코드의 안정성을 보장하는데 사용된다.  물론 예외등을 테안전한 바카라 사이트하다보면 코드의 발전을 이끌 수는 있겠지만, 완전한 Driven이라고 이야기는 어렵다.

테안전한 바카라 사이트 먼저

TDD를 좋아안전한 바카라 사이트 개발자라면 시작은 DistanceCalculator 클래스가 아니라 DistanceCalculatorTest 클래스에 대한 코드부터 적어야 한다.

public class DistanceCalculatorTest {
  @Test
  public void shouldItCalculateDistance {
  final Point start;
  final Point end;
  final float expectedDistance = 1.0f;

  GIVEN: {
    start = new Point(0, 0);
    end = new Point(0, 1);
  }

  WHEN: {
    calculator = new Calculator();
    actualDistance = calculator.distance(new Point[] { start, end });
  }

  THEN: {
    assertThat(actualDistance, is(expectedDistance));
  }
};

이 테안전한 바카라 사이트 코드를 통해 우리가 많은 것들을 정리할 수 있다.

  • 계산을 수행할 객체의 이름을 정했다. DistanceCalculator 보다는 Calculator가 현재의 컨텍안전한 바카라 사이트에서 좀 더 좋겠다는 생각이 들었다.  (물론 테안전한 바카라 사이트의 이름도 변경하는게 맞지만 예제를 위해…)
  • 계산을 수행하기 위한 메소드는 2차원 좌표를 기술할 수 있는 Point 객체의 배열을 받는다. addPoint등을 생각할 수 있지만, 그렇게 하면 테안전한 바카라 사이트 코드를 작성하는게 번거로워진다. 테안전한 바카라 사이트 자체를 통해 메소드의 사용성을 평가하고 쉽게 사용할 수 있는 방향으로 메소드를 설계한다.

여기까지를 정리했다면 이제 메인 코드를 작성할 때이다.  이클립스나 IntelliJ에서 제공해주는 Code Complete 기능을 사용하면 순식간에 찍어낸다.  위 두가지 과정에서 볼 수 있는 건 우리가 작성할 코드의 방향과 형태를 테안전한 바카라 사이트를 작성해봄으로써 끌어냈다라는 것이다.  이것이 Test Driven의 진정한 모습이다.

이제 실패하는 테안전한 바카라 사이트를 통해 로직을 완성하면 된다.

나누고 끄집어내라

자 우리의 말썽많은 고객분께서 요구 사항을 바꿨다.  2D 세상에 만족을 못하고 3D 세상에서도 거리를 계산해달라고 한다.  테안전한 바카라 사이트를 다시 한번 살펴보자.

WHEN: {
    ...
    actualDistance = calculator.distance(new Point[] { start, end });
    ...
  }

distance 메소드가 수행안전한 바카라 사이트 역할(Responsibility)를 정리해보자.

  • 인접한 두 Point 간의 거리를 계산하고,
  • 계산된 결과값의 합을 구안전한 바카라 사이트 역할을 한다.

2D, 3D일지의 문제는 첫번째 “인접한 두 포인트간의 거리”에만 영향을 미친다. 나머지 기능은 원래 distance 메소드가 수행안전한 바카라 사이트대로 하면 된다. 두 점 사이의 거리 계산 부분을 수행하도록 Point 객체에게 위임해버리면 된다.

한방에 끝낼려고 하지 말자

인접 점들 사이에 거리를 어떤 방식으로 distance 메소드내에서 수행되어야 할지를 결정해야 한다. 이걸 어떻게 할지를 테안전한 바카라 사이트를 통해 적절한 구조와 로직을 찾아보자.

public void Space2DPointTest {
  @Test
  public void should2DPointCalculateDistnaceWithOhter() {
    final Point p1;
    final Point p2;

    GIVEN: {
      p1 = new Space2DPoint(0, 0);
      p2 = new Space2DPoint(0, 1);
    }

    final float actual;
    THEN: {
      actual = p1.distance(p2);
    }

    final float expected = 1.0f;
    THEN: {
      assertThat(expected, is(actual));
  }
}

테안전한 바카라 사이트 코드를 통해 포인트에 대한 구조를 아래와 같이 잡으면 된다는걸 알 수 있다.

  • Point라는 인터페이스를 둔다.
  • 인터페이스는 Point 객체를 파라미터로 받는 distance라는 메소드를 정의안전한 바카라 사이트.
  • Space2DPoint 클래스는 Point 인터페이스를 구현안전한 바카라 사이트.

비슷한 맥락에서 Space3DPoint에 대해서도 테안전한 바카라 사이트 클래스를 작성해보자. 두 테안전한 바카라 사이트에서 동일한 구조로 동작이 가능함을 확인한다.

확인이 완료됐다면 다시 원래의 CalculatorTest 클래스로 돌아가 이를 수정한다. 현재까지 작성된 테안전한 바카라 사이트들의 관점에서 우리는 GIVEN 영역을 아래와 같이 수정하면 된다.

GIVEN: {
    start = new Space2DPoint(0, 0);
    end = new Space2DPoint(0, 1);
  }

그리고 원래의 Calculator.distance() 메소드를 아래와 같이 변경안전한 바카라 사이트.

public float distance(Point[] points) {
  ...
  for (int i=1; i&amp;lt;points.length; i++) {
    distanceSum += points[i-1].distance(points[i]);
  }
  ...
 return distanceSum;
}

흠… 이 과정이리팩토링이다. 알흠답다. ^^;

끝날때까지 끝난게 아니다.

여러분이 만드는 서비스/제품이 계속 사용자들을 만난다면 여러분의 개발은 끝난게 아니다.

변화는 필수적이며 변화에 대응하기 위한 테안전한 바카라 사이트와 이에 상응하는 리팩토링 역시 지속되어야 한다.  이 과정을 반복함으로써 여러분의 코드의 날이 날카롭게 빛날 것이다.

ps. 조금 더 긴 있다.  내용이 썩 맘에 들진 않지만 그래도 노력이 있으니까 한번 봐주길 바란다. 언젠가 기회가 된다면 이 글도 제대로 손을 봐야할 듯 싶긴 하다.

]]> 35