본문 바로가기
개발/개발론

클린 코드 - 3. 함수

by hongdor 2020. 12. 7.
728x90

출처 : 클린 코드(애자일 소프트웨어 장인 정신) - 로버트 C.마틴 지음/ 박재호, 이해영 옮김

 

주관적으로 정리한 내용이며 생략된 내용도 있습니다.

 

 

1. 작게 만들어라

 > if, while 등 블록 안에는 한줄의 함수가 들어간다. 들여쓰기는 2단을 넘어가지 않는다.

 

 

2. 한가지만 해라

 > 예를 들어 checkPassword 함수가 일정 횟수이상 틀렸을 때 세션을 초기화하는 경우, 한가지일을 하는것이 아니다.

    Password 확인과 세션 초기화, 두가지 일을 하는 것이다.

 

 

3. 함수 당 추상화 수준은 비슷하도록 한다.

 > getHtml() : 추상화 높음

    String pagePathName = PathParser.render(pagepath) : 추상화 중간

   .append("\n") : 추상화 낮음

 >> 피치못할 경우를 제외하고 위 세 개의 함수를 한개의 함수 안에 섞어 쓴다면 잘못된 것이다. 

 

 

4. 위에서 아래로 작성한다. 

 > 하나의 클래스 안에 여러개의 함수가 있을 경우 추상화 수준이 높은 함수를 위에 배치한다.

 

 

5. 서술적인 이름을 사용하라.

 > 축약어로 인해 이해가 어려운 용어보다 길고 이해가 잘가는 이름이 낫다.

 

 

6. 함수 인수

 > 적을수록 좋고, 2개까지만 허용한다.

 

 (1) 단항 함수

   1) boolean 판단

    > 명령과 조회를 분리한다.

 

    **전 

 if( set( "username", "unclebob" ) ){...}

    >> username이 존재할때 이름은 unclebob으로 설정하고 if문이 실행된다. 그냥봐서는 알기 어렵다.

   

    **후   

 if( attributeExists( "username" )){

        setAttribute( "username", "unclebob" );

        ....

 }

    >> Exist와 set으로 나누어 이해하기 좋다.

 

 

   2) 출력 인수를 입력 인수로 사용하지 않는다. 읽는 사람이 혼동한다.

    > StringBuffer transform(StringBuffer in)   - O

       StringBuffer transform(StringBuffer out) - X

 

  (2) 이항 함수

   > Point( x, y ) 같이 좌표 관련된 함수라면 자연적인 순서가 있으니 이해가 쉽지만 나머지는 그렇지 않다.

     assertEquals( expected, actual ) 은 인자의 순서가 자주 헷갈린다. 따라서 아래와 같은 코드가 더 좋다.

     assertExpectedEqualsActural( expected, actual )

 

 

7. 오류 코드보다 예외를 사용하라

 ** 전

 if( A - deletePage(page) == OK ){

     if( B == OK ){

         if( C == OK ){

         1...

         }else{

         2...

         }     

     }else{

     3...

     }

 }else{

 4....

 }

 >> if문을 통한 예외처리, 지저분하다. ( B, C는 A와 같은 종류의 함수를 비유한 것이다 )

 

 ** 후

 try{

     A

     B

     C  

 }

 catch{

     logger.log(e.getMEssage());

 }

 >> 깔끔하다.

 

 

8. 반복하지 마라

 > 반복되는 것들은 함수, 클래스 등을 활용해 제거한다.

 

 

** 사실 잘 공감가지 않는 것도 있다. 너무 잘게 쪼개면 보기 불편하던데.. 아직 내가 초짜라 그런 것일수도 있다. ㅎㅎ 아래는 잘 작성된 코드 예시이다. 나쁜 예시를 바꾼 것이고 나쁜 예시 코드는 아래 코드 중 일부를 복사해 구글링 하면 볼 수 있다.

 

package fitness.html;



import fitnesse.reponders.run.SuiteResponder;

import fitnesse.wiki.*;



puclic class SetupTeardownIncluder {

    private PageData pageData;

    private boolean isSuite;

    private WikiPage testPage;

    private StringBuffer newPageContent;

    private PageCrawler pageCrawler;

   

    public static String render ( Page Data pageData ) throws Exception {

        return render(pageData, false);

    }



    public static String render ( PageData pageData, boolean isSuite ) throws Exception {

        return new SetupTeardownIncluder ( pageData ) .render( isSuite);

    }

   

    private SetupTeardownIncluder ( PageData pageData ) {

        this.pageData = pageData;

        testPage = pageData.getWikiPage();

        pageCrawler = testPage.getPageCrawler();

        newPageContent = new String buffer();

    }



    private String render ( boolean isSuite ) throws Exception {

        this.isSuite = isSuite;

        if ( isTestPage() )

            includeSetipAndTeardownPages();

        return pageData.getHtml();

        }



    private boolean isTestPage() throw Exception {

        return pageData.hasAttribute("Test");

    }



    private void includeSetipAndTeardownPages() throws Exception {

        includeSetupPages();

        icludePageContent();

        includeTeardownPages();

        updatePageContent();

    }



    private void includeSetupPages() throws Exception {

        if (isSuite) includeSuiteSetupPage();

            includeSetupPage();

    }

   

    private void includeSuiteSetupPage() throws Exception{

        include( SuiteResponder.SUITE_SETUP_NAME, "-setup");

    }



    private void includeSetupPage() throws Exception {

        include( "SetUp", "=setup");

    }



    private void includePageContent() throws Exception {

        newPageContent.append( pageData.getContent() );

    }



    private void includeTeardownPages() throws Exception {

        includeTeardownPage();

        if ((is Suite) includeSuiteTeardownPage();

    }



    private void includeTeardownPage() throws Exception {

        include( "TearDown", "-teardown");

    }



    private void includeSuiteTeardownPage() throws Exception {

        include( SuiteResponder.SUITE_TEARDOWN_NAME, "=teardown");

    }



    private void updatePageContent() throws Exception {

        pageData.setContent( newPageContent.toString() );

    }



    private void include( String pageName, String arg ) throws Exception {

        WikiPage inheritedPage = findInheeritedPage( pageName);

        if ( inheritedPage != null ) {

            String pagePathName = getPathNameForPage( inheritedPage );

            buildIncludeDirective( pagePathName, arg );

        }

    }



    private WikiPage indInheritedPage( String pageName ) throws Exception {

        return PageCrawlerImpl.getInheritedPage( pageName, testPage );

    }



    private String getPathNameForPage( WikiPage page ) throws Excpetion {

        WikiPagePath pagePath = pageCrawler.getFullPath( page );

        return PathParser.render( pagePth) ;

    }



    private void buildIncludeDirective( String pagePathName, String arg ) {

        newPageContent

            .append("\n!include ")

            .append(arg)

            .appent(" .")

            .append(pagePathName)

            .append("\n");

    }

}
728x90

'개발 > 개발론' 카테고리의 다른 글

테스트 주도 개발  (0) 2022.04.21
도메인 주도 설계 철저 입문  (0) 2022.04.07
클린 코드 - 2. 의미 있는 이름  (0) 2020.12.06
클린 코드 - 1. 깨끗한 코드  (0) 2020.12.06

댓글