[TIL] Tidy First - Chanpter 02

해당 글은 퀜트 백의 Tidy First 책을 읽고 정리한 글이다.

Chapter 02

팀이 소프트웨어 설계를 함께 수행하는 방법과 이유

  • 코드 정리는 언제 시작하나요?
  • 코드 정리는 언제 멈추나요?
  • 코드 구조를 변경하는 코드 정리와 시스템의 동작 변경을 어떻게 결합할 수 있나요?

코드 정리 구분

변경은 변경을 낳는다.

코드 정리를 할 때 변경 대상 중에는 동작 변경과 구조 변경이 있다. 처음에는 동작과 구조가 섞여있고, 이 때는 동작과 구조 사이에 어떤 흐름도 존재하지 않는다..

이 과정이 조금 지나게 되면, 공통 흐름을 알아채게 되고, 비슷한 코드끼리 정리하면 설명하는 헬퍼가 생기고, 이를 만들면 이어지는 동작 변경이 훨신 쉬워진다. 이렇게 되면 프로그래밍이 체스와 비슷해져서 몇 수 앞을 짐작할 수 있게 된다.

그렇게 순서를 부여한 동작 변경과 구조 변경이 있다. 이것들을 모두 한꺼번에 모아놓으면 쉽게 엉망이 되어버리고, PR 리뷰가 힘들어진다. 그래서 이러한 변경 사항을 별도의 PR로 나누어야한다. 순서대로 나열한 코드 정리는 PR 한개로 만든다. 동작 변경 역시 별도의 PR로 만든다. 코드 정리와 동작 변경 사이를 번갈아가면서 전환할 때마다 새 PR을 열어야한다.. (이거 맞아?)

이렇게 PR을 나눌지 한 개의 PR로 처리할지는 장단점이 있다. 크고 포괄적인 경우 전체 그림을 보여주지만, 검토하는 입장에서는 유용한 피드백을 받기 어렵다. 반대로 작은 PR은 소소한 피드백을 받을 수 있지만 무시될 우려가 있다.

코드 정리에 익숙해지고, 작은 단위에 익숙해지고, 안전하게 작업하는데에 익숙해지면, 코드 정리 PR을 의도적으로 검토하지말아보자..(그럼 그 사람은 상처를 받고..희생양) PR을 더욱 작게 만들 수 있도록 효과를 만들어서 대기 시간이 추가로 줄어들 수 있다.

연쇄적인 정리

코드 정리는 손이 가는 새우깡과 같다. 코드를 계속 정리하고 싶은 충동을 관리하는 것도 코드 정리의 핵심 기술이다.(내가 제일 잘하는듯 미루는 것!) 방금 정리했는데 또 정리해도 될지는 상황에 따라 다르다.

아주 작게 나누어서 코드를 정리하는 방식으로 실험해라. 그렇게 각 단계를 최적화하여라. 코드 정리는 체스게임과 같아서 코드정리를 하게되면 다음 수를 내다볼 수 있게된다. 다음에 어떤 정리를 할지 살펴보자.

소프트웨어 개발에서 변경은 많은 비용이 든다. 그 중에서도 코드를 이해하는 일에 비용이 가장 많이 든다. 그래서 작동하는 코드의 구조, 의도에 대해 잘 소통하는 것이 가장 가치있는 기술이다. 코드 정리는 의사소통이 어디까지 가능한지 나아갈 수 있도록 해준다.

코드 구조를 바꿀때 너무 많이, 빠르게 변경하지 않도록 주의하자. 대부분 작은 정리를 순차적으로 성공하는 것이 무리한 정리로 실패하는 것보다 시간을 아껴준다.

코드 정리의 일괄 처리량

통합과 배포를 하기 전에 코드 정리는 어느 정도 크기가 적합할까?

  • 코드 정리를 다음 동작 변경을 돕는 구조 변경으로 보면, 다음 동작 변경을 지원하기 위해 얼마나 많은 구조 변경이 필요할까? -> 이는 기본적으로 코드 정리는 먼 미래를 보는 것이 아니므로 즉각적인 필요를 다뤄야한다.
  • 코드 정리의 크기가 어느 정도일 때 쉽게 통합하고 배포할 수 있을까?

PR에는 코드 정리와 동작 변경을 섞지 않도록 했다. 그렇다면 모든 코드 정리를 한꺼번에 할지, 아니면 모두 개별적으로 할지, 그 중간을 택할 것인지 뭐가 더 좋을까?

충돌

한번 처리할 때 코드 정리가 많아질 수록 통합하는 과정의 지연 시간이 길어지게 된다. 그리고 코드 정리 작업이 다른 사람의 작업과 충돌할 가능성도 커진다. 그래서 코드 병합 과정에서 충돌이 발생할 수록 이를 병합하는 비용 또한 더욱 커진다.

상호작용

또한 코드 정리를 한 번에 처리하다가 동작 변경으로 이어질 수도 있다. 그렇게 생겨버린 상호작용으로 인해 병합 비용 또한 증가하게 된다.

추측

다음 동작 변경에 도움이 될 만큼만 코드 정리를 하는 것이 좋다고 했었다. 즉, 한 번에 처리하는 코드 수가 많을 수록 더 많은 코드를 정리하게 되는데 그렇게 되면 더 많은 동작 변경에 대한 코드를 정리하게 된다. 이로 인해 추가 비용이 발생한다.

이렇게 보통 한 번에 처리하는 코드 정리 개수를 줄인 후 통합과 배치를 할 수 있도록 한다. 그럼에도 불구하고 대량의 코드 정리를 일괄로 처리하는 경우가 많은데, 그 이유는..

많은 조직에서 하나의 변경 사항을 검토하고 배포하는 데 드는 고정 비용은 상당히 많다. 작은 PR도 많은 직원들의 검토 비용이 고정적으로 들기 때문인듯 프로그래머는 이를 체감하기 때문에 충돌, 상호작용, 추측으로 인한 비용이 증가되는데도 불구하고 타협점으로 찾으려고 한다.

하지만. 그래도 코드 정리 비용을 줄이려면 코드 정리 PR 개수 자체를 늘려서 동작 변경에 쓰이는 비용을 줄이자. 그러면 검토 비용을 줄일 수가 있다.

일괄 처리 규모를 줄이면 검토 비용도 줄고 코드 정리 비용도 줄어든다. 팀에 신뢰와 문화가 있다면 코드 정리 후에는 검토할 필요가 없다. 코드 정리가 소프트웨어 안정을 해치지않으면 상호작용의 위험도 줄어든다. 하지만 이는 시간이 걸린다. 연습해라.

어쨋든 작게 하기. 작게하면 결국 모두에게 좋다.

리듬

특정 동작 변경 이전에 수행한 구조 변경에 시간이 얼마나 소요되어야할까? 이 책의 목적에 따라 분 단위를 유지하되, 한 시간을 넘지 않도록 한다.

한 번의 코드 정리에 한 시간 이상이 걸리면, 이는 원하는 동작 변경을 위해 필요한 최소한의 구조 변경 시기를 놓쳤다는 의미이다. 아니면 코드가 너무 엉망이라서 코드 정리를 선행하는 것이 더 유리할 수도 있다. 하지만 오래 지속될 수는 없다. 동작 변경은 코드 안에 뭉쳐서 나타나는 경향이 있다. 코드 정리는 선행하면 코드 정리 내용이 뭉쳐진다는 것이다. 그리고 이는 동작 변경하기에 가장 좋은 위치에서 뭉쳐져 있다.

그래서 코드 정리를 많이 하는 경우에도 해당 코드 정리를 끝낸 코드로 동작 변경을 하고 싶어하는 자신을 볼 수 있다. 계속 코드 정리를 한다면, 대부분의 변경 작업은 이미 정리된 코드 안에서 이루어지게 된다. 즉 정리되지 않은 코드를 만나는 일이 코드 정리를 할 수록 급격하게 줄어든다. 그래서 한 시간이면 충분하다.

얽힘 풀기

어떤 코드의 동작 변경을 하고 있다고 할 때, 변경을 쉽게할 코드 정리를 알고 있다. 그렇게 코드 정리를 진행하고, 동작을 변경할 차례에서 코드 정리할 곳이 더 생기는 경우에 어떻게 작업을 해야할까?

  • 변경 대상인 동작을 모두 알게 되었다.
  • 쉽게 동작을 변경하기 위해서 어떤 코드를 정리해야하는지도 알게 되었다.
  • 문제는 이미 정리한 코드와 변경할 동작이 얽혀버렸다.

선택지는 3개가 있다.

  • 그대로 배포한다. 오류가 발생하기 쉽지만 당장 처리할 수 있다.
  • 이미 정리한 코드와 정리할 코드의 변경 사항을 별도의 PR로 나누거나 하나의 PR을 여러 번의 커밋으로 나눈다. 이같은 경우 작업횟수가 늘어나게 된다.
  • 진행중인 작업을 버리고, 코드 정리를 선행하는 순서로 다시 시작한다. 작업 자체는 많아지지만, 커밋과의 일관성이 생긴다.

세 번째를 진행하는 것을 권장한다. 이를 진행하면서 또 다시 새로운 것을 발견할 가능성도 생긴다. 얽혀있는 부분을 풀려면 일단 얽혀있다는 것을 알아차려야 한다. 그것을 알아차리는 행위를 더 일찍 할 수록 작업량은 적어질 것이다. 코드 정리를 하기로 마음먹고 진행하다보면, 어디까지 코드 정리를 할지 고민하다가 코드 정리와 동작 변경 사이에서 끊어내는 시점을 놓치기 쉽다. 분명 순조롭게 잘 하고 있었는데, 그게 아니라서 난감해질 수도 있다. 하지만 이런 선후문제는 시간이 지나면 해결된다.

코드 정리 시점