독서/📚

[클린코드] 3장. 함수

leejinwoo1126 2022. 2. 22. 22:13
반응형

 

 


해당 장을 통해 중복👎, 가독성👍, 재사용성👍 할 수 있는 함수 작성 방법에 살펴 보았다.

 

1. 함수명

✔ 동사 + 명사

# init 
public void initData(){..}   // 데이터 초기화 

# is/has/can
public boolean isNumber(){..}  // 숫자 여부 판단
public boolean hasData(){..}   
public boolean canOrder(){..} 

# create
public Board create(){..}   // 새로운 객체 생성 후 리턴

# find 
public Element findElement(int number){..}

 

✔ 전치사 + 명사 || 전치사

# to 
public String toString(){..}  // String 변환 
public String toStringDateTime(LocalDateTime localDateTime){..}
public Board toEntity(){} // Board Entity로 변환

# of 
public static <T> Optional<T> of(T value) {
    return new Optional<>(value);
}

public static<T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}

# by
public Board findById(Long id){..}    // Spring Data JPA 에서 자주 보이는 네이밍 findBy*

 

2. 함수 인자

- 인수의 개수는 0~2개 적당( 이상적인 개수는 0개✨)

- 3개 이상인 경우 ?

생성자 파라미터가 3개 이상인 경우, 인자 값 전달시 신경 써야 하는 부분이 늘고, 실수할 가능성이 높아지므로 객체로 넘기는 방식이나 builder pattern 등을 활용하는 것이 좋은거 같다

// 객체를 인자로 넘기기 
Circle makeCircle(double x, double y , double radius); //👎 
Circle makeCircle(Point center , double radius); //👍 

// 가변 인자를 넘기기 -> 특별한 경우가 아니면 잘 .. 🤔 
String.format(String format, Object… args);

 

3. 디자인 패턴 활용 - 팩토리 패턴

✔ 팩토리(factory) - 객체의 생성, 소멸 주기 관리하는 클래스

팩토리 패턴 예시 – 중개 수수료 계산 ( 그 외 SNS 로그인, 카드 결제 등 )

  • 장점) 인터페이스 통해 구현체 바꿔 끼움으로써 느슨한 결합을 가지게 됨
  • 단점) 결국엔 신규 클래스 추가시 인터페이스 구현해줘야 함

직접 실천해보기

✔ 함수 인수 개선

// 수정 전) 함수 인수가 너무 많음 💩
public static PagingDTO getPagingInfo(int currentPage, int size, int pageGroupSize, int totalCount) {
    return new PagingDTO(currentPage, size, pageGroupSize, totalCount);
}

// 수정 후) 객체 전달하여 인수 줄임 👨‍💻
public static PagingDTO getPagingInfo(SearchDTO searchDTO, int totalCount) {
    return new PagingDTO(searchDTO, totalCount);
}

 

✔ 함수 내용 개선 --- 페이징(1)

함수는 한가지 일을 제대로 수행해야 한다.

// 수정 전) 하나의 함수가 여러가지 일을 수행함 💩
private void setPagingInfo(){
        startPage = currentPage - ((currentPage - 1) % pageGroupSize);
        endPage = startPage - 1 + pageGroupSize;

        totalPages = (int)(totalCount/size + (totalCount%size == 0 ? 0 : 1));

        if(totalCount == 0) isEmpty = true;

        if(startPage > pageGroupSize && currentPage > pageGroupSize){
            isPrev = true;
            prevPage = startPage - 1;
        }

        if(endPage > totalPages){
            endPage = totalPages;
        }

        if(endPage != totalPages){
            isNext = true;
            nextPage = endPage + 1;
        }

        pages = new ArrayList();
        for(int i = startPage ; i <= endPage; i++){
            pages.add(i);
        }
}


// 수정 후) 작은 함수 단위로 나눔, 서술적 함수명 사용, 순차적 진행 💻
private void setPagingInfo(){
        calcStartPage();
        calcEndPage();
        calcTotalPage();

        isEmptyTotalCount(); // 함수명 이상하네 😳

        setPrevPage();
        isEndPageBiggerThanTotalPage(); // 함수명 이상하네 😳
        setNextPage();
        addPageNumber();
}

 

✔ 함수 내용 개선 --- 조회수 중복 증가 방지 Cookie(2)

① 손으로 로직을 말로써 풀어봄

② 메서드 단위로 분리

③ 클래스 생성해서 작성

④ 점진적 개선 ( 확장 가능성은 추후..😳 )

 

인터넷에서 쉽게 찾을 수 있는 게시판 중복 조회수 증가 방지용 쿠키 처리 코드이다. 

하나의 Method 안에서 cookie 조회하고, 처리하는 로직이 있어 이를 개선해보았다.

// 수정 전) 함수명도 이상하게 정했고, 함수 안에서 여러가지 일을 수행함 💩
public void chkBoardCookie(Long id, HttpServletRequest request, HttpServletResponse response){

        Cookie old = null;
        Cookie[] cookies = request.getCookies();

        if(cookies != null){
            for(Cookie cookie : cookies){
                if("viewCookie".equals(cookie.getName())) old = cookie;
            }
        }

        if(old != null){
            if(!old.getValue().contains("%"+id+"%")){
                boardRepository.updateViewCnt(id);
                old.setValue(old.getValue() + "%"+id+"%");
                old.setPath("/");
                old.setMaxAge(60*60*24);
                response.addCookie(old);
            }
        }else {
            boardRepository.updateViewCnt(id);
            Cookie cookie = new Cookie("viewCookie", "%" + id + "%");
            cookie.setPath("/");
            cookie.setMaxAge(60 * 60 * 24);
            response.addCookie(cookie);
        }
}

// 수정 후) ViewCookie라는 클래스 만들어서 캡슐화한 후 public 한 함수만 사용하도록 처리함 👨‍💻
@GetMapping("/board/detail/{id}")
public String boardDetail(@PathVariable Long id, Model model, @LoginUser SessionUser user
            ,HttpServletRequest request, HttpServletResponse response){

        ViewCookie viewCookie = new ViewCookie(request, response, id);
        if (viewCookie.isPossibleUpdateViewCnt()) {
            viewCookie.setCookieToResponse();
            boardService.updateViewCnt(id);
        }

        BoardResponseDTO board = boardService.findById(id);
        //..이하 생략
}

 

중복 조회수 방지 동작 확인

잘 동작한다.🤗 아쉬운 부분이 남아 있기 때문에 점진적으로 개선하는 것으로 😀


느낀점

이번 챕터 진행하면서 저자가 설명하는 내용에 공감하고 따라해보면서 더럽던 코드가 어떻게 개선되어 가는지 확인해 볼 수 있었던 흥미로운 시간이었다. (좀 더 잘 하고 싶다!😶 )

반응형