SlideShare a Scribd company logo
1 of 47
Download to read offline
꾸준히 자라나는 소프트웨어 (Software that grows!)
만들기 - 테스트 자동화, 리팩토링


박종빈 (jongbhin@nhn.com)




                                ⓒ 2010 NHN CORPORATION
목차

 0. 들어가기
 1. NHN의 한 개발자 이야기
 2. 자라나는 소프트웨어 (Software that Grows!)
 3. 리팩토링
 4. 테스트 자동화
 5. NHN의 리팩토링, 테스트 자동화 체계
 6. Quality Practice를 활용한 리팩토링, 테스트 자동화
 7. 맺음말
Software Development                  35




                       Architect

                       Architecture

                       Design
Software Development   34




   Build
Software that Grows! - Gardening                                        33




                                   Andrew Hunt and David Thomas, 1999
1. NHN의 한 개발자 이야기
1.   NHN의 한 개발자 이야기      32




        용기 300배 개발자 시절
1.   NHN의 한 개발자 이야기                  31




                      1일 방문자수: 7백만
                      1일 페이지뷰: 9천만

         NHN의 핵심 서비스
         배포코드 유지보수
1.   NHN의 한 개발자 이야기   30




냄새 나는
               코드……
1.   NHN의 한 개발자 이야기                                          29




        if   (type != null && (type == 1 || type == 2)) {
              if (reason != null && reason.length() > 0) {
                  if (type == 1) {
                      if (Stop.stop1() == false) {
                          …;
                      }
                  } else {
                      if (…) {
                          …;
                                    복잡한 if 문
                          if (…) {

냄새 나는
                              …;
                          }
                      } else {
                          …;



              }
                  }  코드……
                      }



        }
1.   NHN의 한 개발자 이야기                                  28




        if (type != null && (type == 1 || type == 2)) {
            if (reason != null && reason.length() > 0) {
                if (type == 1) {
                    if (Stop.stop1() == false) {
                         …;
                    }
                } else {
                    if (…) {
                         …;
                              복잡한 조건문
                         if (…) {


냄새 나는
                             …;
                         }
                    } else {
                         …;



            }
                } 코드……
                    }



        }
1.   NHN의 한 개발자 이야기                                              27




        if (type != null && (type == 1 || type ==          2))   {
            if (reason != null && reason.length() > 0) {
                if (type == 1) {
                    if (Stop.stop1() == false) {
                         …;
                    }
                } else {
                    if (…) {
                         …;
                                  뜻 모를 이름들
                         if (…) {


냄새 나는                    }
                    } else {
                         …;
                             …;

                                  을 수정하다가
            }
                }   코드……
                    }



        }
1.   NHN의 한 개발자 이야기         26




       10분간 전체 웹서버 다운


                      또 수정하다가
1.   NHN의 한 개발자 이야기       25




               간 전체 웹서버
1.   NHN의 한 개발자 이야기     24




     코드가 이해하기 쉬웠더라면…
     코드가 테스트하기 쉬웠더라면…
2. 자라나는 소프트웨어
   (Software that Grows!)
2.   자라나는 소프트웨어(Software that Grows!)                   23




         리팩토링               Quality Practice



     이해하기 쉽고
             소프트웨어로 성장해가는 것
       오류 없는


        테스트 자동화           CI (Continuous Integration)
3. 리팩토링
3.1   리팩토링이란?                             22




   리팩토링은 외부의 동작을 바꾸지 않고 내부의 구조를 개선하는 것
    – 마틴 파울러

   사람이 이해하기 어려운 코드를 이해하기 쉬운 코드로 바꿈으로써,
    코드수정에 드는 노력과 오류 발생 가능성을 줄일 수 있음




                     리팩토링
3.2   리팩토링 예제1   21

      복잡한 코드
3.2   리팩토링 예제1                                                                                                       20

      복잡한 코드
   아까 냄새 나는 코드의 원본
    - 중첩된 if문
    - 복잡한 조건문 : if (type != null && (type == 1 || type == 2))
      public void stop(Integer type, String reason) {
          if (type != null && (type == 1 || type == 2)) {
              if (reason != null && reason.length() > 0) {
                  if (type == 1) {
                      if (completeStop.stopNow() == false) {
                            throw new FailedStopException("Cannot stop the service.");
                      }
                  } else {
                      if (readOnlyStop.stopNow()) {
                            StopMessage stopMessage = new StopMessage();
                            stopMessage.setReason(reason);
                                                                                                                복잡도
                            stopMessage.setDate(new Date());
                            if (readOnlyNotifier.getRelatedServices().size() > 0) {
                                if (readOnlyNotifier.notifyToRelatedServices(stopMessage) == false)   {        CC2=11
                                    throw new FailedReadOnlyNotificationException();
                                }
                          }
                      } else {
                            throw new FailedStopException("Cannot stop the service.");
                      }
                  }
                  return;
              }
          }
          throw new IllegalArgumentException("Type or reason cannot be empty.");
      }




                               상세 리팩토링 과정과 코드는 별첨 참조
                                                                                     CC2 : Cyclomatic Complexity with Boolean
3.2   리팩토링 예제1                                                                           19

      복잡한 코드
   리팩토링 이후의 코드
    - 깊이 1단계의 if문
    - 간결한 조건문 : if (stopType == null)
      public void stop(StopType stopType, String reason) {
          if (stopType == null) {
              throw new IllegalArgumentException("StopType cannot be null.");
          }                                                                            복잡도
          if (isEmpty(reason)) {
              throw new IllegalArgumentException("Reason cannot be empty.");
          }
          if (stopType == StopType.COMPLETE_STOP) {                                    CC2=4
              stopNow(completeStop);
          } else {
              stopNow(readOnlyStop);
              readOnlyNotifier.notifyToRelatedServices(createStopMessageBy(reason));
          }
      }
      private StopMessage createStopMessageBy(String reason) {
          StopMessage stopMessage = new StopMessage();
          stopMessage.setReason(reason);                                               CC2=1
          stopMessage.setDate(new Date());
          return stopMessage;
      }
      private void stopNow(Stop specificStop) {
          boolean success = specificStop.stopNow();
          if (success == false) {                                                      CC2=2
              throw new FailedStopException("Cannot stop the service.");
          }
      }



                          상세 리팩토링 과정과 단계별 코드는 별첨 참조
3.3   리팩토링 예제2          18

      읽기 어려운 코드 - 네이밍
3.3    리팩토링 예제2                                                   17

       읽기 어려운 코드 - 네이밍
   코딩은 글쓰기(Writing)의 일종임
   클래스, 메소드, 변수의 이름은 의도하는 바를 명확하게 드러내야 이해하기 쉬움

                           네이밍 예제

 if (argv[0] == TYPE1) {    if (numberOfAttendees == CROWDED) {
     return 0;                  return INCREASE_LUNCH_BOX;
 } else {                   } else {
     return 1;                  return DECREASE_LUNCH_BOX;
 }                          }



  컴퓨터가 이해할 수 있는 코드는 어느 바보나 다 짤 수 있다.
  좋은 프로그래머는 사람이 이해할 수 있는 코드를 짠다.
      - 마틴 파울러
4. 테스트 자동화
4   테스트 자동화                                                    16




              사진출처: http://www.automatedtestinginstitute.com
4.1   테스트 자동화의 필요성                                                            15




   기능이 추가되면서 전체 테스트 항목도 증가하나 충분한 테스트가 수행되지 않음
   Regression 결함이 발생할 수 있어 테스트 자동화가 필요함


                                                142       147
                                       137
                             130
비용                                                                   기능수
                  120



            100




                                                                      전체기능수
                                                                      QA 테스트 비용
        100
                  +20                                                 개발 비용
                            +10        +7       +5         +5

       Ver.1.0    Ver.1.1   Ver.1.2   Ver.1.3   Ver.1.4    Ver.1.5
4.2   개발자 테스트의 필요성                                14




   대부분의 결함은 코딩단계에서 발생함
   수정비용은 단계가 지날 수록 기하급수적으로 증가함
   개발자 테스트가 비용대비 효과가 좋음


      100%                         $16,000




      50%                          $8,000




       0%                           $0
             코딩   통합   테스트    운영             결함발생 비율
                                             결함발견 비율
                                             결함수정비용
4.3   단계별 테스트 자동화                                             13




   단위, 통합, QA 전체 테스트 단계에서 테스트 자동화가 필요함
                                                        빨리, 자주
                                                         실행

          • 최소 단위의 White-box 테스트
 단위 테스트
          • 클래스 별로 메소드에 대해 정상 동작     단위테스트 자동화
 개발자가
            여부를 확인                   (JUnit)
 수시로 수행
          • 개별 클래스 단독으로 신속하게 수행 가능

                                     단위테스트자동화
          • 두 개 이상의 구성 요소 간의
                                     (JUnit)
 통합 테스트     인터페이스를 테스트
                                     통합테스트 자동화
 하루에 한번   • Black-box 테스트
                                     (FitNesse)
 수행       • 시스템 간의 연동 테스트
                                     UI 테스트 자동화
          • 기능이 제대로 수행되는지 검증
                                     (Selenium)

 QA 테스트                              UI 테스트 자동화
 QA       • 시나리오 기반의 테스트             (Selenium)
 단계에서     • 개발과 독립적인 조직이 수행          성능테스트
 수행                                  (PerformaSure)

                                                      상위 레벨
5. NHN의 리팩토링, 테스트 자동화 체계
5   NHN의 리팩토링, 테스트 자동화 체계   12
5.1           NHN의 테스트 자동화와 리팩토링                                             11

              Quality Practice를 활용
   QP 활동의 정착이 테스트 자동화와 리팩토링의 문화적 밑거름으로 작용
    - 각 지표를 통해 코드의 성장 모습을 확인할 수 있음

                   Quality Practice (QP)         지표

                      Code Coverage          Code Coverage
      오류 없는 코드




                                                                      테스트
                                                                      자동화
                                              잔존 정적분석
                       Static Analysis
                                               결함 밀도

                     Coding Convention       코딩 표준 준수율       성장하는
                                                             모습확인
      이해하기 쉬운 코드




                                                             개선 포인트
                        Code Review          코드 리뷰 수행율
                                                                      리팩토링
                                               CC≥30
                      Code Complexity
                                               모듈 비율

                   Code Duplicate Analysis         -
5.2           Quality Practice 지원 도구 와 CI 서버                                    10




         활동 별로 지원도구가 있음
         CI 서버와 연동하여 빌드 수행 시 마다, 꾸준하게 현재수준과 개선 포인트를 제공
                QP           도구
               Code
                            Clover
오류 없는 코드




              Coverage                               Checkstyle
                Static
                           Klocwork
               Analysis

               Coding                   CPD                          Klocwork
                           Checkstyle
             Convention                               CI 서버
                                                     (Hudson)
이해하기 쉬운 코드




             Code Review   Crucible

               Code         NSIQ              NSIQ
             Complexity    Collector                              Clover
                                          Collector
               Code
              Duplicate      CPD
              Analysis                                  Java환경에서 가장 많이 활용하는 도구들임
6. Quality Practice를 활용한
   리팩토링, 테스트 자동화
6   Quality Practice를 활용한 리팩토링, 테스트 자동화   9
6.1           복잡하고 위험한 코드 식별                                                                                  8




         코드 복잡도가 높으나 테스트가 이루어지지 않은 항목을 쉽게 찾을 수 있음
         리팩토링을 수행하여 복잡도를 낮추거나, 추가 테스트로 커버리지를 높임
                QP
                                                  커버리지-복잡도 산점도
               Code
오류 없는 코드




              Coverage                                       이렇게 복잡도는 높으나
                                                             테스트가 이루어지지 않은
                Static                                       메소드가 있어서는 안됨
               Analysis

               Coding
             Convention                                        테스트
이해하기 쉬운 코드




             Code Review
                                               리팩토링
               Code
             Complexity

               Code
              Duplicate
                                                        NHN 개발 Hudson Plug-in
              Analysis     http://wiki.hudson-ci.org/display/HUDSON/Coverage+Complexity+Scatter+Plot+PlugIn
6.2           커버리지 확인 및 테스트 케이스 보완                       7




         소스코드의 테스트가 수행되지 않은 부분(분기, 구문)을 파악하여 테스트를 보완

                QP
               Code
오류 없는 코드




              Coverage

                Static
               Analysis

               Coding
             Convention
이해하기 쉬운 코드




             Code Review

               Code
             Complexity

               Code
              Duplicate
              Analysis                 테스트가 수행되지 않은 구문
6.3           읽기 쉬운 코드 만들기                                 6




         코딩 컨벤션 중 구문 형식을 따르지 않은 코드는 도구로 검출할 수 있음
         의도가 명확한 이름처럼, 의미론적인(Semantic) 것은 사람이 리뷰를 통해 확인
                QP
               Code              NHN 코딩 컨벤션
오류 없는 코드




              Coverage            - 네이밍 규칙
                                  - 코딩작성 규칙
                Static            - 주석작성 규칙
               Analysis           - JSP작성 규칙
                                  - 보안코드 작성규칙
               Coding
             Convention
이해하기 쉬운 코드




             Code Review

               Code
             Complexity

               Code
              Duplicate
              Analysis
6.4           코드와 함께 자라나는 테스트 자동화                     5




         코드 작성과 함께 (또는 이전에) 테스트 코드를 작성하는 문화가 정착되어 가고 있음

                                     LOC
                QP
               Code
오류 없는 코드




              Coverage

                Static
               Analysis

               Coding
             Convention          Test Result Trend
이해하기 쉬운 코드




             Code Review

               Code
             Complexity

               Code
              Duplicate          Code Coverage
              Analysis
6.5           테스트로 찾기 어려운 결함 검출                                                   4




         정적 분석 도구를 활용하여 잠재된 결함을 조기에 발견하고 제거함
         동적 테스트로는 검출하기 어려운 결함을 발견해 줌
                QP
               Code                       자주 발견되는 정적 분석 결함
오류 없는 코드




              Coverage
                           중요도             카테고리                     설명
                Static
               Analysis

               Coding                                    Null Pointer Exception
                                      Possible Runtime
             Convention    Critical                      Null 값을 역참조할 경우
                                      Failures
                                                         발생
이해하기 쉬운 코드




             Code Review

               Code                                      Memory Leak
             Complexity                                  리소스가 할당되었으나 사용
                            Error     Resource Leaks
                                                         후 적절히 해제되지 않을 때
               Code
              Duplicate
                                                         발생
              Analysis
6.6    리팩토링, 테스트 자동화 사례         3




       대상 서비스: 핵심 서비스
        - 1일 방문자수     : 630만
        - 1일 페이지뷰수    : 1억7천만
        - 8년 된 코드


       리팩토링
       - 주요 기능의 코드 70% 리팩토링
       - 미사용 테이블 삭제


       테스트 자동화
       - 단위 테스트 자동화
       - UI 테스트 자동화
6.7    리팩토링, 테스트 자동화 결과                              2




       Java 코드 감소 :   20~30% 감소
       DB 테이블 감소 :    50% 감소 (464개)

              테스트 커버리지                  월간 장애 발생건수
 60

 50

 40
                                        개선된 코드 배포


 30

                         서비스
 20
                         어드민
 10

  0
                                       09/01




                                       10/01
                                          03


                                          06
                                          02

                                          04
                                          05

                                          07
                                          08
                                          09
                                          10
                                          11
                                          12

                                          02
                                          03
        개선전       단위    통합(단위+UI)
7. 맺음말
7.   맺음말   1
한편....                           0




도입부의 NHN의 한 개발자는
리팩토링과 테스트 자동화에 관하여 연구에 연구를 거듭,
NHN의 Key Man으로 성장해 가고 있음
별첨: 리팩토링 사례

리팩토링 전

http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?view=mar
kup&root=refactoring&pathrev=2

리팩토링 후

http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?revision=1
2&root=refactoring&view=markup&pathrev=12

http://dev.naver.com/scm/viewvc.php/trunk/src/test/java/com/naver/dev/refactoring/servicestop/ServiceStopperTest.java?view=
markup&root=refactoring&pathrev=13

리팩토링 과정

#1. 리팩토링 전 ServiceStopper에 대한 단위 테스트를 만듬.
http://dev.naver.com/scm/viewvc.php/trunk/src/test/java/com/naver/dev/refactoring/servicestop/ServiceStopperTest.java?view=
markup&root=refactoring&pathrev=3

#2. 파라메터 변수 type의 의미가 명확하지 않아 stopType으로 변경함.
http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?view=diff
&root=refactoring&pathrev=6&r1=2&r2=4&diff_format=h

#3. Integer로 구분하던 StopType을 Enum StopType으로 바꿈. 그 결과로 잘못된 타입정보에 대한 검사구문이 사라졌고, 1,2로 구분되던 코
드가 COMPLETE_STOP과 같은 문자열로 바뀌어 의도가 더 명확히 드러나게 됨.
http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?view=diff
&root=refactoring&pathrev=6&r1=4&r2=5&diff_format=h

#4. StopType과 Reason의 Type검사를 하기 위해 존재하던 중첩 IF 문을 깊이 1단계의 IF문으로 변경함. 가독성에 긍정적 영향을 미치기를 기
대함.
http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?view=diff
&root=refactoring&pathrev=6&r1=5&r2=6&diff_format=h
별첨: 리팩토링 사례

#5. Reason 입력검사하는 부분의 조건절의 코드를 Commons StringUtils.isEmpty로 교체함. 그 결과로 가독성 향상을 기대함.
http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?view=diff
&root=refactoring&pathrev=6&r1=6&r2=7&diff_format=h

#6. 유형별로 stopNow를 호출하는 부분에 중복이 있어 해당 부분을 stopNowCleanly라는 메서드로 분리시킴. 중복을 제거하고 가독성을 향
상시키고자 함.
http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?view=diff
&root=refactoring&pathrev=6&r1=7&r2=8&diff_format=h

#7. 위 3번에서 실수로 생긴 버그를 수정함. 이 실수는 만들어 놓은 테스트를 실행해보지 않아 생겼음. 따라서 테스트를 작성하는 것도 중요하지
만 코드를 수정할 때마다 테스트를 실행해보고 문제가 발생하지 않았나를 검사하는 것도 매우 중요한 요소임.
 http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?root=refa
ctoring&r1=9&r2=8&pathrev=9

#8. ReadOnlyStop시 관련 서비스가 있는지 검사하고, 관련 서비스가 있을 때 알림을 전송하던 부분을 ReadOnlyNotifier로 이동시킴. 이 부분
에 대한 책임은 ServiceStopper보다는 ReadOnlyNotifier에 있는 것이 더 적합하다는 판단임.
 http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?root=refa
ctoring&view=diff&r1=9&r2=10&diff_format=h

#9. StopMessage 생성하는 부분을 별도의 메서드로 분리시킴. 핵심로직이 아닌데 많은 줄을 차지하는 부분을 의미를 드러내는 한줄의 메서드
로 바꿈으로써 가독성을 향상시키기 위함임.
 http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?root=refa
ctoring&view=diff&r1=10&r2=11&diff_format=h

#10. StopMessage는 한 곳에서만 사용되며 굳이 임시변수로 둘 필요가 없기 때문에 메서드 호출로 변경함.
 http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?root=refa
ctoring&view=diff&r1=11&r2=12&diff_format=h

More Related Content

What's hot

[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현
[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현
[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현NAVER D2
 
NDC11_슈퍼클래스
NDC11_슈퍼클래스NDC11_슈퍼클래스
NDC11_슈퍼클래스noerror
 
About Visual C++ 10
About  Visual C++ 10About  Visual C++ 10
About Visual C++ 10흥배 최
 
이산수학 C1 프로젝트 7
이산수학 C1 프로젝트 7이산수학 C1 프로젝트 7
이산수학 C1 프로젝트 7pkok15
 
세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발Jay JH Park
 
인수테스트 주도 개발
인수테스트 주도 개발인수테스트 주도 개발
인수테스트 주도 개발Jaehoon Oh
 
[OKKYCON] 박재성 - 의식적인 연습으로 TDD, 리팩토링 연습하기
[OKKYCON] 박재성 - 의식적인 연습으로 TDD, 리팩토링 연습하기[OKKYCON] 박재성 - 의식적인 연습으로 TDD, 리팩토링 연습하기
[OKKYCON] 박재성 - 의식적인 연습으로 TDD, 리팩토링 연습하기OKKY
 
[OKKYCON] 정진욱 - 테스트하기 쉬운 코드로 개발하기
[OKKYCON] 정진욱 - 테스트하기 쉬운 코드로 개발하기[OKKYCON] 정진욱 - 테스트하기 쉬운 코드로 개발하기
[OKKYCON] 정진욱 - 테스트하기 쉬운 코드로 개발하기OKKY
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스Sungik Kim
 
[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기
[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기
[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기OKKY
 
[Shader study] Color control (2014.05.12)
[Shader study] Color control (2014.05.12)[Shader study] Color control (2014.05.12)
[Shader study] Color control (2014.05.12)해강
 
Blockchain 4th dapp programming
Blockchain 4th dapp programmingBlockchain 4th dapp programming
Blockchain 4th dapp programmingihpark92
 
2013 C++ Study For Students #1
2013 C++ Study For Students #12013 C++ Study For Students #1
2013 C++ Study For Students #1Chris Ohk
 
Python vs Java @ PyCon Korea 2017
Python vs Java @ PyCon Korea 2017Python vs Java @ PyCon Korea 2017
Python vs Java @ PyCon Korea 2017Insuk (Chris) Cho
 
빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)SeongHyun Ahn
 
Nexon Developers Conference 2017 Functional Programming for better code - Mod...
Nexon Developers Conference 2017 Functional Programming for better code - Mod...Nexon Developers Conference 2017 Functional Programming for better code - Mod...
Nexon Developers Conference 2017 Functional Programming for better code - Mod...Isaac Jeon
 
C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2Chris Ohk
 
파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229Yong Joon Moon
 
객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회beom kyun choi
 

What's hot (20)

[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현
[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현
[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현
 
NDC11_슈퍼클래스
NDC11_슈퍼클래스NDC11_슈퍼클래스
NDC11_슈퍼클래스
 
About Visual C++ 10
About  Visual C++ 10About  Visual C++ 10
About Visual C++ 10
 
이산수학 C1 프로젝트 7
이산수학 C1 프로젝트 7이산수학 C1 프로젝트 7
이산수학 C1 프로젝트 7
 
이산수학07
이산수학07이산수학07
이산수학07
 
세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발
 
인수테스트 주도 개발
인수테스트 주도 개발인수테스트 주도 개발
인수테스트 주도 개발
 
[OKKYCON] 박재성 - 의식적인 연습으로 TDD, 리팩토링 연습하기
[OKKYCON] 박재성 - 의식적인 연습으로 TDD, 리팩토링 연습하기[OKKYCON] 박재성 - 의식적인 연습으로 TDD, 리팩토링 연습하기
[OKKYCON] 박재성 - 의식적인 연습으로 TDD, 리팩토링 연습하기
 
[OKKYCON] 정진욱 - 테스트하기 쉬운 코드로 개발하기
[OKKYCON] 정진욱 - 테스트하기 쉬운 코드로 개발하기[OKKYCON] 정진욱 - 테스트하기 쉬운 코드로 개발하기
[OKKYCON] 정진욱 - 테스트하기 쉬운 코드로 개발하기
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스
 
[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기
[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기
[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기
 
[Shader study] Color control (2014.05.12)
[Shader study] Color control (2014.05.12)[Shader study] Color control (2014.05.12)
[Shader study] Color control (2014.05.12)
 
Blockchain 4th dapp programming
Blockchain 4th dapp programmingBlockchain 4th dapp programming
Blockchain 4th dapp programming
 
2013 C++ Study For Students #1
2013 C++ Study For Students #12013 C++ Study For Students #1
2013 C++ Study For Students #1
 
Python vs Java @ PyCon Korea 2017
Python vs Java @ PyCon Korea 2017Python vs Java @ PyCon Korea 2017
Python vs Java @ PyCon Korea 2017
 
빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)
 
Nexon Developers Conference 2017 Functional Programming for better code - Mod...
Nexon Developers Conference 2017 Functional Programming for better code - Mod...Nexon Developers Conference 2017 Functional Programming for better code - Mod...
Nexon Developers Conference 2017 Functional Programming for better code - Mod...
 
C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2
 
파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229
 
객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회
 

Viewers also liked

테스트자동화 성공전략
테스트자동화 성공전략테스트자동화 성공전략
테스트자동화 성공전략SangIn Choung
 
2010 SW Testing Trend
2010 SW Testing Trend2010 SW Testing Trend
2010 SW Testing TrendMurian Song
 
Automated Web Testing and Open Source Tools
Automated Web Testing and Open Source ToolsAutomated Web Testing and Open Source Tools
Automated Web Testing and Open Source ToolsHank Huang
 
테스트 코드 삽질기 + 리팩토링
테스트 코드 삽질기 + 리팩토링테스트 코드 삽질기 + 리팩토링
테스트 코드 삽질기 + 리팩토링종훈 박
 
Automated Testing Tools for Desktop, Web and Mobile Software
Automated Testing Tools for Desktop, Web and Mobile SoftwareAutomated Testing Tools for Desktop, Web and Mobile Software
Automated Testing Tools for Desktop, Web and Mobile SoftwareRanorex
 
Unit Tests And Automated Testing
Unit Tests And Automated TestingUnit Tests And Automated Testing
Unit Tests And Automated TestingLee Englestone
 
자바 8 스트림 API
자바 8 스트림 API자바 8 스트림 API
자바 8 스트림 APINAVER Corp
 
Automated Testing with Agile
Automated Testing with AgileAutomated Testing with Agile
Automated Testing with AgileKen McCorkell
 
Beyond Java: 자바 8을 중심으로 본 자바의 혁신
Beyond Java: 자바 8을 중심으로 본 자바의 혁신Beyond Java: 자바 8을 중심으로 본 자바의 혁신
Beyond Java: 자바 8을 중심으로 본 자바의 혁신Sungchul Park
 
자바8 람다 나머지 공개
자바8 람다 나머지 공개자바8 람다 나머지 공개
자바8 람다 나머지 공개Sungchul Park
 
테스트 자동화와 TDD(테스트 주도 개발방법론)
테스트 자동화와 TDD(테스트 주도 개발방법론)테스트 자동화와 TDD(테스트 주도 개발방법론)
테스트 자동화와 TDD(테스트 주도 개발방법론)KH Park (박경훈)
 
화성에서 온 개발자, 금성에서 온 기획자
화성에서 온 개발자, 금성에서 온 기획자화성에서 온 개발자, 금성에서 온 기획자
화성에서 온 개발자, 금성에서 온 기획자Yongho Ha
 

Viewers also liked (14)

테스트자동화 성공전략
테스트자동화 성공전략테스트자동화 성공전략
테스트자동화 성공전략
 
2010 SW Testing Trend
2010 SW Testing Trend2010 SW Testing Trend
2010 SW Testing Trend
 
Automated Web Testing and Open Source Tools
Automated Web Testing and Open Source ToolsAutomated Web Testing and Open Source Tools
Automated Web Testing and Open Source Tools
 
테스트 코드 삽질기 + 리팩토링
테스트 코드 삽질기 + 리팩토링테스트 코드 삽질기 + 리팩토링
테스트 코드 삽질기 + 리팩토링
 
The Introduction to Refactoring
The Introduction to Refactoring The Introduction to Refactoring
The Introduction to Refactoring
 
Automated Testing Tools for Desktop, Web and Mobile Software
Automated Testing Tools for Desktop, Web and Mobile SoftwareAutomated Testing Tools for Desktop, Web and Mobile Software
Automated Testing Tools for Desktop, Web and Mobile Software
 
Unit Tests And Automated Testing
Unit Tests And Automated TestingUnit Tests And Automated Testing
Unit Tests And Automated Testing
 
자바 8 스트림 API
자바 8 스트림 API자바 8 스트림 API
자바 8 스트림 API
 
Automated Testing with Agile
Automated Testing with AgileAutomated Testing with Agile
Automated Testing with Agile
 
Beyond Java: 자바 8을 중심으로 본 자바의 혁신
Beyond Java: 자바 8을 중심으로 본 자바의 혁신Beyond Java: 자바 8을 중심으로 본 자바의 혁신
Beyond Java: 자바 8을 중심으로 본 자바의 혁신
 
Code Refactoring
Code RefactoringCode Refactoring
Code Refactoring
 
자바8 람다 나머지 공개
자바8 람다 나머지 공개자바8 람다 나머지 공개
자바8 람다 나머지 공개
 
테스트 자동화와 TDD(테스트 주도 개발방법론)
테스트 자동화와 TDD(테스트 주도 개발방법론)테스트 자동화와 TDD(테스트 주도 개발방법론)
테스트 자동화와 TDD(테스트 주도 개발방법론)
 
화성에서 온 개발자, 금성에서 온 기획자
화성에서 온 개발자, 금성에서 온 기획자화성에서 온 개발자, 금성에서 온 기획자
화성에서 온 개발자, 금성에서 온 기획자
 

Similar to 자라나는 소프트웨어

[NDC 2016] 유니티, iOS에서 LINQ 사용하기
[NDC 2016] 유니티, iOS에서 LINQ 사용하기[NDC 2016] 유니티, iOS에서 LINQ 사용하기
[NDC 2016] 유니티, iOS에서 LINQ 사용하기Daehee Kim
 
14장 - 15장 예외처리, 템플릿
14장 - 15장 예외처리, 템플릿14장 - 15장 예외처리, 템플릿
14장 - 15장 예외처리, 템플릿유석 남
 
객체지향 정리. Part1
객체지향 정리. Part1객체지향 정리. Part1
객체지향 정리. Part1kim HYUNG JIN
 
C++ 프로그래밍 2014-2018년 기말시험 기출문제
C++ 프로그래밍 2014-2018년 기말시험 기출문제C++ 프로그래밍 2014-2018년 기말시험 기출문제
C++ 프로그래밍 2014-2018년 기말시험 기출문제Lee Sang-Ho
 
NDC 2011, 네트워크 비동기 통신, 합의점의 길목에서
NDC 2011, 네트워크 비동기 통신, 합의점의 길목에서NDC 2011, 네트워크 비동기 통신, 합의점의 길목에서
NDC 2011, 네트워크 비동기 통신, 합의점의 길목에서tcaesvk
 
KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기Ryan Park
 
아두이노 2015-2 한동대학교 공학설계입문
아두이노 2015-2 한동대학교 공학설계입문아두이노 2015-2 한동대학교 공학설계입문
아두이노 2015-2 한동대학교 공학설계입문Sangjun Han
 
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기Chris Ohk
 
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)Sang Don Kim
 
Android audio system(오디오 플링거 서비스 초기화)
Android audio system(오디오 플링거 서비스 초기화)Android audio system(오디오 플링거 서비스 초기화)
Android audio system(오디오 플링거 서비스 초기화)fefe7270
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 명신 김
 
Lecture 1: Introduction to Python and TensorFlow
Lecture 1: Introduction to Python and TensorFlowLecture 1: Introduction to Python and TensorFlow
Lecture 1: Introduction to Python and TensorFlowSang Jun Lee
 
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It종빈 오
 
안드로이드 설계코드 노하우 및 개발방법
안드로이드 설계코드 노하우 및 개발방법안드로이드 설계코드 노하우 및 개발방법
안드로이드 설계코드 노하우 및 개발방법mosaicnet
 
2012 Ds B1 01
2012 Ds B1 012012 Ds B1 01
2012 Ds B1 01seonhyung
 

Similar to 자라나는 소프트웨어 (17)

HI-ARC PS 101
HI-ARC PS 101HI-ARC PS 101
HI-ARC PS 101
 
[NDC 2016] 유니티, iOS에서 LINQ 사용하기
[NDC 2016] 유니티, iOS에서 LINQ 사용하기[NDC 2016] 유니티, iOS에서 LINQ 사용하기
[NDC 2016] 유니티, iOS에서 LINQ 사용하기
 
14장 - 15장 예외처리, 템플릿
14장 - 15장 예외처리, 템플릿14장 - 15장 예외처리, 템플릿
14장 - 15장 예외처리, 템플릿
 
객체지향 정리. Part1
객체지향 정리. Part1객체지향 정리. Part1
객체지향 정리. Part1
 
C++ 프로그래밍 2014-2018년 기말시험 기출문제
C++ 프로그래밍 2014-2018년 기말시험 기출문제C++ 프로그래밍 2014-2018년 기말시험 기출문제
C++ 프로그래밍 2014-2018년 기말시험 기출문제
 
NDC 2011, 네트워크 비동기 통신, 합의점의 길목에서
NDC 2011, 네트워크 비동기 통신, 합의점의 길목에서NDC 2011, 네트워크 비동기 통신, 합의점의 길목에서
NDC 2011, 네트워크 비동기 통신, 합의점의 길목에서
 
KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기
 
아두이노 2015-2 한동대학교 공학설계입문
아두이노 2015-2 한동대학교 공학설계입문아두이노 2015-2 한동대학교 공학설계입문
아두이노 2015-2 한동대학교 공학설계입문
 
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
 
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
 
MutiCore 19-20
MutiCore 19-20MutiCore 19-20
MutiCore 19-20
 
Android audio system(오디오 플링거 서비스 초기화)
Android audio system(오디오 플링거 서비스 초기화)Android audio system(오디오 플링거 서비스 초기화)
Android audio system(오디오 플링거 서비스 초기화)
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14
 
Lecture 1: Introduction to Python and TensorFlow
Lecture 1: Introduction to Python and TensorFlowLecture 1: Introduction to Python and TensorFlow
Lecture 1: Introduction to Python and TensorFlow
 
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
 
안드로이드 설계코드 노하우 및 개발방법
안드로이드 설계코드 노하우 및 개발방법안드로이드 설계코드 노하우 및 개발방법
안드로이드 설계코드 노하우 및 개발방법
 
2012 Ds B1 01
2012 Ds B1 012012 Ds B1 01
2012 Ds B1 01
 

자라나는 소프트웨어

  • 1. 꾸준히 자라나는 소프트웨어 (Software that grows!) 만들기 - 테스트 자동화, 리팩토링 박종빈 (jongbhin@nhn.com) ⓒ 2010 NHN CORPORATION
  • 2. 목차 0. 들어가기 1. NHN의 한 개발자 이야기 2. 자라나는 소프트웨어 (Software that Grows!) 3. 리팩토링 4. 테스트 자동화 5. NHN의 리팩토링, 테스트 자동화 체계 6. Quality Practice를 활용한 리팩토링, 테스트 자동화 7. 맺음말
  • 3. Software Development 35 Architect Architecture Design
  • 5. Software that Grows! - Gardening 33 Andrew Hunt and David Thomas, 1999
  • 6. 1. NHN의 한 개발자 이야기
  • 7. 1. NHN의 한 개발자 이야기 32 용기 300배 개발자 시절
  • 8. 1. NHN의 한 개발자 이야기 31 1일 방문자수: 7백만 1일 페이지뷰: 9천만 NHN의 핵심 서비스 배포코드 유지보수
  • 9. 1. NHN의 한 개발자 이야기 30 냄새 나는 코드……
  • 10. 1. NHN의 한 개발자 이야기 29 if (type != null && (type == 1 || type == 2)) { if (reason != null && reason.length() > 0) { if (type == 1) { if (Stop.stop1() == false) { …; } } else { if (…) { …; 복잡한 if 문 if (…) { 냄새 나는 …; } } else { …; } } 코드…… } }
  • 11. 1. NHN의 한 개발자 이야기 28 if (type != null && (type == 1 || type == 2)) { if (reason != null && reason.length() > 0) { if (type == 1) { if (Stop.stop1() == false) { …; } } else { if (…) { …; 복잡한 조건문 if (…) { 냄새 나는 …; } } else { …; } } 코드…… } }
  • 12. 1. NHN의 한 개발자 이야기 27 if (type != null && (type == 1 || type == 2)) { if (reason != null && reason.length() > 0) { if (type == 1) { if (Stop.stop1() == false) { …; } } else { if (…) { …; 뜻 모를 이름들 if (…) { 냄새 나는 } } else { …; …; 을 수정하다가 } } 코드…… } }
  • 13. 1. NHN의 한 개발자 이야기 26 10분간 전체 웹서버 다운 또 수정하다가
  • 14. 1. NHN의 한 개발자 이야기 25 간 전체 웹서버
  • 15. 1. NHN의 한 개발자 이야기 24 코드가 이해하기 쉬웠더라면… 코드가 테스트하기 쉬웠더라면…
  • 16. 2. 자라나는 소프트웨어 (Software that Grows!)
  • 17. 2. 자라나는 소프트웨어(Software that Grows!) 23 리팩토링 Quality Practice 이해하기 쉽고 소프트웨어로 성장해가는 것 오류 없는 테스트 자동화 CI (Continuous Integration)
  • 19. 3.1 리팩토링이란? 22  리팩토링은 외부의 동작을 바꾸지 않고 내부의 구조를 개선하는 것 – 마틴 파울러  사람이 이해하기 어려운 코드를 이해하기 쉬운 코드로 바꿈으로써, 코드수정에 드는 노력과 오류 발생 가능성을 줄일 수 있음 리팩토링
  • 20. 3.2 리팩토링 예제1 21 복잡한 코드
  • 21. 3.2 리팩토링 예제1 20 복잡한 코드  아까 냄새 나는 코드의 원본 - 중첩된 if문 - 복잡한 조건문 : if (type != null && (type == 1 || type == 2)) public void stop(Integer type, String reason) { if (type != null && (type == 1 || type == 2)) { if (reason != null && reason.length() > 0) { if (type == 1) { if (completeStop.stopNow() == false) { throw new FailedStopException("Cannot stop the service."); } } else { if (readOnlyStop.stopNow()) { StopMessage stopMessage = new StopMessage(); stopMessage.setReason(reason); 복잡도 stopMessage.setDate(new Date()); if (readOnlyNotifier.getRelatedServices().size() > 0) { if (readOnlyNotifier.notifyToRelatedServices(stopMessage) == false) { CC2=11 throw new FailedReadOnlyNotificationException(); } } } else { throw new FailedStopException("Cannot stop the service."); } } return; } } throw new IllegalArgumentException("Type or reason cannot be empty."); } 상세 리팩토링 과정과 코드는 별첨 참조 CC2 : Cyclomatic Complexity with Boolean
  • 22. 3.2 리팩토링 예제1 19 복잡한 코드  리팩토링 이후의 코드 - 깊이 1단계의 if문 - 간결한 조건문 : if (stopType == null) public void stop(StopType stopType, String reason) { if (stopType == null) { throw new IllegalArgumentException("StopType cannot be null."); } 복잡도 if (isEmpty(reason)) { throw new IllegalArgumentException("Reason cannot be empty."); } if (stopType == StopType.COMPLETE_STOP) { CC2=4 stopNow(completeStop); } else { stopNow(readOnlyStop); readOnlyNotifier.notifyToRelatedServices(createStopMessageBy(reason)); } } private StopMessage createStopMessageBy(String reason) { StopMessage stopMessage = new StopMessage(); stopMessage.setReason(reason); CC2=1 stopMessage.setDate(new Date()); return stopMessage; } private void stopNow(Stop specificStop) { boolean success = specificStop.stopNow(); if (success == false) { CC2=2 throw new FailedStopException("Cannot stop the service."); } } 상세 리팩토링 과정과 단계별 코드는 별첨 참조
  • 23. 3.3 리팩토링 예제2 18 읽기 어려운 코드 - 네이밍
  • 24. 3.3 리팩토링 예제2 17 읽기 어려운 코드 - 네이밍  코딩은 글쓰기(Writing)의 일종임  클래스, 메소드, 변수의 이름은 의도하는 바를 명확하게 드러내야 이해하기 쉬움 네이밍 예제 if (argv[0] == TYPE1) { if (numberOfAttendees == CROWDED) { return 0; return INCREASE_LUNCH_BOX; } else { } else { return 1; return DECREASE_LUNCH_BOX; } } 컴퓨터가 이해할 수 있는 코드는 어느 바보나 다 짤 수 있다. 좋은 프로그래머는 사람이 이해할 수 있는 코드를 짠다. - 마틴 파울러
  • 26. 4 테스트 자동화 16 사진출처: http://www.automatedtestinginstitute.com
  • 27. 4.1 테스트 자동화의 필요성 15  기능이 추가되면서 전체 테스트 항목도 증가하나 충분한 테스트가 수행되지 않음  Regression 결함이 발생할 수 있어 테스트 자동화가 필요함 142 147 137 130 비용 기능수 120 100 전체기능수 QA 테스트 비용 100 +20 개발 비용 +10 +7 +5 +5 Ver.1.0 Ver.1.1 Ver.1.2 Ver.1.3 Ver.1.4 Ver.1.5
  • 28. 4.2 개발자 테스트의 필요성 14  대부분의 결함은 코딩단계에서 발생함  수정비용은 단계가 지날 수록 기하급수적으로 증가함  개발자 테스트가 비용대비 효과가 좋음 100% $16,000 50% $8,000 0% $0 코딩 통합 테스트 운영 결함발생 비율 결함발견 비율 결함수정비용
  • 29. 4.3 단계별 테스트 자동화 13  단위, 통합, QA 전체 테스트 단계에서 테스트 자동화가 필요함 빨리, 자주 실행 • 최소 단위의 White-box 테스트 단위 테스트 • 클래스 별로 메소드에 대해 정상 동작 단위테스트 자동화 개발자가 여부를 확인 (JUnit) 수시로 수행 • 개별 클래스 단독으로 신속하게 수행 가능 단위테스트자동화 • 두 개 이상의 구성 요소 간의 (JUnit) 통합 테스트 인터페이스를 테스트 통합테스트 자동화 하루에 한번 • Black-box 테스트 (FitNesse) 수행 • 시스템 간의 연동 테스트 UI 테스트 자동화 • 기능이 제대로 수행되는지 검증 (Selenium) QA 테스트 UI 테스트 자동화 QA • 시나리오 기반의 테스트 (Selenium) 단계에서 • 개발과 독립적인 조직이 수행 성능테스트 수행 (PerformaSure) 상위 레벨
  • 30. 5. NHN의 리팩토링, 테스트 자동화 체계
  • 31. 5 NHN의 리팩토링, 테스트 자동화 체계 12
  • 32. 5.1 NHN의 테스트 자동화와 리팩토링 11 Quality Practice를 활용  QP 활동의 정착이 테스트 자동화와 리팩토링의 문화적 밑거름으로 작용 - 각 지표를 통해 코드의 성장 모습을 확인할 수 있음 Quality Practice (QP) 지표 Code Coverage Code Coverage 오류 없는 코드 테스트 자동화 잔존 정적분석 Static Analysis 결함 밀도 Coding Convention 코딩 표준 준수율 성장하는 모습확인 이해하기 쉬운 코드 개선 포인트 Code Review 코드 리뷰 수행율 리팩토링 CC≥30 Code Complexity 모듈 비율 Code Duplicate Analysis -
  • 33. 5.2 Quality Practice 지원 도구 와 CI 서버 10  활동 별로 지원도구가 있음  CI 서버와 연동하여 빌드 수행 시 마다, 꾸준하게 현재수준과 개선 포인트를 제공 QP 도구 Code Clover 오류 없는 코드 Coverage Checkstyle Static Klocwork Analysis Coding CPD Klocwork Checkstyle Convention CI 서버 (Hudson) 이해하기 쉬운 코드 Code Review Crucible Code NSIQ NSIQ Complexity Collector Clover Collector Code Duplicate CPD Analysis Java환경에서 가장 많이 활용하는 도구들임
  • 34. 6. Quality Practice를 활용한 리팩토링, 테스트 자동화
  • 35. 6 Quality Practice를 활용한 리팩토링, 테스트 자동화 9
  • 36. 6.1 복잡하고 위험한 코드 식별 8  코드 복잡도가 높으나 테스트가 이루어지지 않은 항목을 쉽게 찾을 수 있음  리팩토링을 수행하여 복잡도를 낮추거나, 추가 테스트로 커버리지를 높임 QP 커버리지-복잡도 산점도 Code 오류 없는 코드 Coverage 이렇게 복잡도는 높으나 테스트가 이루어지지 않은 Static 메소드가 있어서는 안됨 Analysis Coding Convention 테스트 이해하기 쉬운 코드 Code Review 리팩토링 Code Complexity Code Duplicate NHN 개발 Hudson Plug-in Analysis http://wiki.hudson-ci.org/display/HUDSON/Coverage+Complexity+Scatter+Plot+PlugIn
  • 37. 6.2 커버리지 확인 및 테스트 케이스 보완 7  소스코드의 테스트가 수행되지 않은 부분(분기, 구문)을 파악하여 테스트를 보완 QP Code 오류 없는 코드 Coverage Static Analysis Coding Convention 이해하기 쉬운 코드 Code Review Code Complexity Code Duplicate Analysis 테스트가 수행되지 않은 구문
  • 38. 6.3 읽기 쉬운 코드 만들기 6  코딩 컨벤션 중 구문 형식을 따르지 않은 코드는 도구로 검출할 수 있음  의도가 명확한 이름처럼, 의미론적인(Semantic) 것은 사람이 리뷰를 통해 확인 QP Code NHN 코딩 컨벤션 오류 없는 코드 Coverage - 네이밍 규칙 - 코딩작성 규칙 Static - 주석작성 규칙 Analysis - JSP작성 규칙 - 보안코드 작성규칙 Coding Convention 이해하기 쉬운 코드 Code Review Code Complexity Code Duplicate Analysis
  • 39. 6.4 코드와 함께 자라나는 테스트 자동화 5  코드 작성과 함께 (또는 이전에) 테스트 코드를 작성하는 문화가 정착되어 가고 있음 LOC QP Code 오류 없는 코드 Coverage Static Analysis Coding Convention Test Result Trend 이해하기 쉬운 코드 Code Review Code Complexity Code Duplicate Code Coverage Analysis
  • 40. 6.5 테스트로 찾기 어려운 결함 검출 4  정적 분석 도구를 활용하여 잠재된 결함을 조기에 발견하고 제거함  동적 테스트로는 검출하기 어려운 결함을 발견해 줌 QP Code 자주 발견되는 정적 분석 결함 오류 없는 코드 Coverage 중요도 카테고리 설명 Static Analysis Coding Null Pointer Exception Possible Runtime Convention Critical Null 값을 역참조할 경우 Failures 발생 이해하기 쉬운 코드 Code Review Code Memory Leak Complexity 리소스가 할당되었으나 사용 Error Resource Leaks 후 적절히 해제되지 않을 때 Code Duplicate 발생 Analysis
  • 41. 6.6 리팩토링, 테스트 자동화 사례 3  대상 서비스: 핵심 서비스 - 1일 방문자수 : 630만 - 1일 페이지뷰수 : 1억7천만 - 8년 된 코드  리팩토링 - 주요 기능의 코드 70% 리팩토링 - 미사용 테이블 삭제  테스트 자동화 - 단위 테스트 자동화 - UI 테스트 자동화
  • 42. 6.7 리팩토링, 테스트 자동화 결과 2  Java 코드 감소 : 20~30% 감소  DB 테이블 감소 : 50% 감소 (464개) 테스트 커버리지 월간 장애 발생건수 60 50 40 개선된 코드 배포 30 서비스 20 어드민 10 0 09/01 10/01 03 06 02 04 05 07 08 09 10 11 12 02 03 개선전 단위 통합(단위+UI)
  • 44. 7. 맺음말 1
  • 45. 한편.... 0 도입부의 NHN의 한 개발자는 리팩토링과 테스트 자동화에 관하여 연구에 연구를 거듭, NHN의 Key Man으로 성장해 가고 있음
  • 46. 별첨: 리팩토링 사례 리팩토링 전 http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?view=mar kup&root=refactoring&pathrev=2 리팩토링 후 http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?revision=1 2&root=refactoring&view=markup&pathrev=12 http://dev.naver.com/scm/viewvc.php/trunk/src/test/java/com/naver/dev/refactoring/servicestop/ServiceStopperTest.java?view= markup&root=refactoring&pathrev=13 리팩토링 과정 #1. 리팩토링 전 ServiceStopper에 대한 단위 테스트를 만듬. http://dev.naver.com/scm/viewvc.php/trunk/src/test/java/com/naver/dev/refactoring/servicestop/ServiceStopperTest.java?view= markup&root=refactoring&pathrev=3 #2. 파라메터 변수 type의 의미가 명확하지 않아 stopType으로 변경함. http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?view=diff &root=refactoring&pathrev=6&r1=2&r2=4&diff_format=h #3. Integer로 구분하던 StopType을 Enum StopType으로 바꿈. 그 결과로 잘못된 타입정보에 대한 검사구문이 사라졌고, 1,2로 구분되던 코 드가 COMPLETE_STOP과 같은 문자열로 바뀌어 의도가 더 명확히 드러나게 됨. http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?view=diff &root=refactoring&pathrev=6&r1=4&r2=5&diff_format=h #4. StopType과 Reason의 Type검사를 하기 위해 존재하던 중첩 IF 문을 깊이 1단계의 IF문으로 변경함. 가독성에 긍정적 영향을 미치기를 기 대함. http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?view=diff &root=refactoring&pathrev=6&r1=5&r2=6&diff_format=h
  • 47. 별첨: 리팩토링 사례 #5. Reason 입력검사하는 부분의 조건절의 코드를 Commons StringUtils.isEmpty로 교체함. 그 결과로 가독성 향상을 기대함. http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?view=diff &root=refactoring&pathrev=6&r1=6&r2=7&diff_format=h #6. 유형별로 stopNow를 호출하는 부분에 중복이 있어 해당 부분을 stopNowCleanly라는 메서드로 분리시킴. 중복을 제거하고 가독성을 향 상시키고자 함. http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?view=diff &root=refactoring&pathrev=6&r1=7&r2=8&diff_format=h #7. 위 3번에서 실수로 생긴 버그를 수정함. 이 실수는 만들어 놓은 테스트를 실행해보지 않아 생겼음. 따라서 테스트를 작성하는 것도 중요하지 만 코드를 수정할 때마다 테스트를 실행해보고 문제가 발생하지 않았나를 검사하는 것도 매우 중요한 요소임. http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?root=refa ctoring&r1=9&r2=8&pathrev=9 #8. ReadOnlyStop시 관련 서비스가 있는지 검사하고, 관련 서비스가 있을 때 알림을 전송하던 부분을 ReadOnlyNotifier로 이동시킴. 이 부분 에 대한 책임은 ServiceStopper보다는 ReadOnlyNotifier에 있는 것이 더 적합하다는 판단임. http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?root=refa ctoring&view=diff&r1=9&r2=10&diff_format=h #9. StopMessage 생성하는 부분을 별도의 메서드로 분리시킴. 핵심로직이 아닌데 많은 줄을 차지하는 부분을 의미를 드러내는 한줄의 메서드 로 바꿈으로써 가독성을 향상시키기 위함임. http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?root=refa ctoring&view=diff&r1=10&r2=11&diff_format=h #10. StopMessage는 한 곳에서만 사용되며 굳이 임시변수로 둘 필요가 없기 때문에 메서드 호출로 변경함. http://dev.naver.com/scm/viewvc.php/trunk/src/main/java/com/naver/dev/refactoring/servicestop/ServiceStopper.java?root=refa ctoring&view=diff&r1=11&r2=12&diff_format=h