조각들

 

내용

34pg, 전산 용어, 알고리즘 이름, 패턴 이름, 수학 용어 등을 사용해도 괜찮다.

 

36pg, 맥락을 개선하면 함수를 쪼개기가 쉬워진다.

 

42pg, 함수를 만드는 첫째 규칙은 '작게!'다. 두번째 규칙은 '더 작게!'다.

 

43pg,

if문/else문/while문 등에 들어가는 블록은 한 줄이어야 한다.

함수에서 들여쓰기 수준은 1단이나 2단을 넘어서면 안 된다.

 

45pg,

함수는 한 가지를 해야 한다. 지정된 함수 이름 아래에서 추상화 수준이 하나인 단계만 수행한다면 그 함수는 한 가지 작업만 하는 것으로 취급한다.

 

한 가지 작업만 하는 함수는 자연스럽게 섹션으로 나누기 어렵다.


느낀점

45pg가 제일 핵심이라고 느꼈다.

함수는 하나의 기능만 수행하게 짧게 만들라는 말은 많이 들어왔지만 

함수 하나가 하나의 기능만을 수행하는 경우는 거의 없다. 

그런데 그 기준을 추상화 수준으로 잡는다면 얘기가 달라진다.

 

함수를 쪼개도 합치고 보면 전체 코드량은 비슷할 수 있으나 

가독성 측면에서 이득을 보기 때문에 쪼개라는 것 같다.

 

40pg를 보면 무슨 기능을 수행하는 코드인지 하나도 모르겠다.

그런데 이거를 여러 함수로 쪼개고, 쪼갠 후에는 그때마다 부여된 함수 이름을 통해 어떤 기능을 수행하는 함수인지 대략적인 hint를 얻을 수 있다. 이게 생각보다 큰 차이를 만들어내는 것 같다.

나도 체감했다. 리팩토링 후의 코드를 보여줬는데 34pg 때는 도통 감도 못잡겠던 코드를 얼핏 파악이라도 했냈으니 말이다.

 

어느정도로 쪼개야 하는지는 36pg와 45pg가 예시가 될 수 있을 것 같다.

36pg에서는 멤버변수 값을 갱신하는 2~3줄짜리 코드인데도 가독성을 위해 함수를 새로 만들어주었다.

 

90쪽 목록 4-7의 예시는 저번에 내가 리팩토링했던 drawCourse()함수의 경우인 것 같다.

해당 함수는 작업을 departureMarker 생성, routeMarker 생성, routeMarker 삭제 이렇게 3개의 섹션으로 나눠졌고 모두 한 함수 안에 길게 적혀있었다. 그래서 각각을 함수로 만들어주었다.

 


적용

DrawActivity에 작성해둔 createRouteMarker() 함수를 더 쪼개보려고 한다.

리팩토링 전 코드는 아래와 같다. 구현부에 담겨있는 코드들은 전체적인 맥락에서 createRouteMarker 안에 포함되는 게 적절하지만 단지 가독성의 목적이든, 섹션이 추가로 나뉘기 때문이든 더 쪼갤 수 있을 것 같다. 

    private fun createRouteMarker() {
        naverMap.setOnMapClickListener { _, coord ->
            if (isMarkerAvailable) {
                viewModel.isBtnAvailable.value = true
                if (touchList.size < 20) { // 마커 생성 갯수 제한
                    touchList.add(
                        LatLng(
                            coord.latitude,
                            coord.longitude
                        )
                    )

                    val routeMarker = Marker()

                    routeMarker.position = LatLng(
                        coord.latitude,
                        coord.longitude
                    )
                    routeMarker.anchor = PointF(0.5f, 0.5f)
                    routeMarker.icon = OverlayImage.fromResource(R.drawable.marker_route)
                    routeMarker.map = naverMap

                    markerList.add(routeMarker)

                    coords.add(LatLng(coord.latitude, coord.longitude)) // coords에 터치로 받아온 좌표값 추가

                    path.coords = coords // 경로선 그리기
                    path.color = Color.parseColor("#593EEC") // 경로선 색상
                    path.outlineColor = Color.parseColor("#593EEC") // 경로선 테두리 색상
                    path.map = naverMap

                    calculateDistance()
                } else {
                    Toast.makeText(this, "마커는 20개까지 생성 가능합니다", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }

 

아래는 리팩토링 후의 코드이다.

    private fun createRouteMarker() {
        naverMap.setOnMapClickListener { _, coord ->
            if (isMarkerAvailable) {
                viewModel.isBtnAvailable.value = true
                if (touchList.size < maxMarkerNum) {
                    addCoordsToTouchList(coord)
                    setRouteMarker(coord)
                    generateRouteLine(coord)
                    calculateDistance()
                } else {
                    Toast.makeText(this, "마커는 20개까지 생성 가능합니다", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }

여러 함수로 작게 쪼갰을 뿐 총 코드량은 비슷하겠지만 아마 배경지식이 없는 사람이 처음 코드를 접할 땐 리팩토링 전보다 후의 코드가 더 맥락 파악이 수월할 것이다.

 

함수를 계속 쪼갤수록 함수 이름도 계속 정해줘야 하는데 코드가 아니라 하나의 글을 써내려가는 느낌이다.

이름을 어떻게 지어줄지 고민이 많이 된다.

이번 경우에는 이미 최상위 단계 함수에 createRouteMarker라는 이름을 써주었는데 하위에 포함돼있는 마커 세팅 코드에는 어떤 이름을 붙여야 하나 고민이 됐다.

 

makeRouteMarker라고 이름을 지어주자니 createRouteMarker와 명확히 구분이 안 될 것 같았다.

그래서 make보다는 set이 낫겠다는 판단으로 setRouteMarker라는 이름을 붙여주었다.

 

이름을 정하는 게 생각보다 더 까다로운 작업이었다.

'독서 > Clean Code' 카테고리의 다른 글

클린코드(~33pg)  (1) 2023.03.13