- 개발 프로세스 자체가 레거시 코드의 발생 원인이 되기도 한다.
- 문제는 기술 부족 이외에도 심리적 안정감, 커뮤니케이션, 조직적 요인 등 굉장히 다양한 원인으로 발생한다.
- 각각의 문제와, 그 해결 방법에 대해 설명해보자
16.1 커뮤니케이션
16.1.1 커뮤니케이션이 부족하면 설계 품질에 문제가 발생
- 팀 개발에서는 팀원과 어떤 코드를 작업할 때 서로의 로직이 제대로 맞물리지 않아 버그로 이어지는 상황이 매우 흔하다.
- 커뮤니케이션이 부족해 서로가 무엇을 하고 있는지 잘 모르기 때문이다.
16.1.2 콘웨이 법칙
- 커뮤니케이션 문제 해결과 관련된 콘웨이 법칙
- 콘웨이 법칙은 ‘시스템의 구조는 그것을 설계하는 조직의 구조를 닮아간다’ 라는 법칙이다.
- 개발 부문이 3개의 팀으로 구분되어 있다면 모듈의 수도 팀의 수와 동일하게 3개로 구성되는 시스템이 만들어진다.
- 커뮤니케이션 비용 구조의 법칙으로 팀 내부에서 이뤄지는 커뮤니케이션은 비용이 낮고, 팀 외부와의 커뮤니케이션은 비용이 높다는 비용 구조 자체가 시스템 구조에 영향을 준다.
- 최근에는 반대로 접근하는 역콘웨이 법칙이 등장했다.
- 역콘웨이 법칙이란 ‘소프트웨어의 구조를 먼저 설계하고, 이후 소프트웨어의 구조에 맞게 조직을 편성한다'는 접근 방법이다.
- 하지만 커뮤니케이션 문제는 팀원 간 커뮤니케이션 비용이 높다는 이야기다. 역콘웨이 법칙을 내세우며 팀을 구성하더라도 팀 내부의 문제가 있다면 본질적인 문제가 해결되지 않는다.
16.2 설계
- 설계는 굉장히 중요한 개발 프로세스이다. 설계가 제대로 이루어지지 못하게 하거나, 설계한 것이 제대로 동작하지 않게 하는 다양한 함정이 있다.
- 각각의 함정과 대처 방법을 살펴보자.
16.2.1 ‘빨리 끝내고 싶다’는 심리가 품질 저하의 함정
- 품질이 나쁜 시스템을 만드는 팀은 클래스 설계와 관련된 습관이 애초에 없는 경우가 많다.
- 일이 바쁘면 구현을 빨리 끝내고 싶은 마음이 앞서게 되고, 그냥 동작하기만 한다면 코드를 어떻게든 구현해 버린다.
- 이러한 환경에서는 클래스 다이어그램조차 그려보지 않는 등 설계 품질을 무시하기 쉽다.
- 하지만 소프트웨어는 한 번 만드는 것으로 끝나지 않는다. 이후에 사양 변경이 계속 이루어지고, 기능도 점점 확장될 것이다.
- 초반에는 빠른 구현을 할 수 있지만 시간이 지날수록 구현 속도가 느려지고 버그 수정을 하게될 것이다.
16.2.2 나쁜 코드를 작성하는 것이 좋은 코드를 작성하는 것보다 오래 걸린다.
- ‘테스트 주도 개발(TDD)를 사용해서 구현하는 경우 와 ‘사용하지 않고 구현하는 경우’ 중에 TDD를 사용해서 개발하는 편이 더 빠르다는 결론이 나왔다.
16.2.3 클래스 설계와 구현 피드백 사이클 돌리기
- 사양을 변경할 때 최소한 메모라도 적어 클래스 다이어그램을 그려보자
- 구현하다 보면 예상하지 못했던 요소들을 발견하는데 이때마다 클래스 다이어그램에 반영하면 설계 품질이 향상될 것이다.
16.2.4 한 점에 완벽하게 설계하려고 들지 말고, 사이클 돌리며 완성하기
- 사양을 대규모로 변경할 때는 그만큼 확실한 클래스 설계가 필요하다.
- 단 한번의 설계로 완벽한 구조를 만들어 낼 수 없다.
- 완벽하다고 생각해도, 구현하다 보면 결국 동작에 필요한 요소들을 추가로 발견하게 될 것이다.
- 설계 품질은 설계와 구현 피드백 사이클을 계속 돌리면서 조금씩 향상된다.
16.2.5 ‘성능이 떨어질 수 있으니 클래스를 작게 나누지 말자’는 맞는 말일까?
- 클래스 인스턴스 생성은 비용이 발생하여 성능을 떨어뜨릴 수 있으므로 클래스를 많이 만들면 안된다’라고 생각하는 사람이 꽤 많다.
- 클래스가 많아지면 비용이 발생하는 것은 맞으나 무시할 수 있는 정도이다.
- 성능에 지배적인 영향을 미치는 부분은 실제로 측정해 보기 전까지는 제대로 알 수 없다.
16.2.6 설계 규칙을 다수결로 결정하면 코드 품질은 떨어진다.
- 코드 품질을 향상시키기 위해 코딩 규칙과 설계 규칙을 정하는 경우가 있다.
- 이때 팀 전체의 합의를 이루고자 규칙을 다수결로 결정하는 경우가 있는데 일반적으로 결과가 좋지 않다.
- 설계 기술이 미숙한 팀원이 제안된 규칙의 좋고 나쁨을 제대로 판단할 수 없어 조악한 규칙이 채택될 수도 있고 규칙 자체가 만들어지지 않을 수도 있다.
16.2.7 설계 규칙을 정할 때 중요한 점
- 설계 역량이 뛰어난 팀원이 중심이 되어 규칙을 만들어 나가는 것이 좋다.
- 또한 각각의 설계 규칙에는 이유와 의도를 함께 적는 것이 좋다.
16.3 구현
16.3.1 깨진 유리창 이론과 보이스카우트 규칙
- 범죄학에는 깨진 유리창 이론이 있다. 다음과 같은 과정을 거쳐 치안이 악화된다는 이론이다.
- 건물에 깨진 유리창 하나가 생긴다.
- 깨진 유리창이 오래 방치되면, 아무도 신경쓰지 않는 건물이라는 인식이 퍼진다.
- 다른 문을 깨기도 하고, 쓰레기를 버리는 등의 경범죄가 추가로 발생해서 치안이 조금씩 나빠진다.
- 상황이 더욱 악화되어 흉악 범죄까지도 일어나게 한다.
- 이 이론은 소프트웨어 개발에도 적용된다. 조악하고 복잡하고 질서없는 코드가 방치되면, 소프트웨어 전체가 점점 더 무질서해집니다.
- 코드를 변경할 때, 자신이 변경하기 전보다 더 깨끗한 상태로 만들어 커밋하다보면 이러한 작은 개선이 코드의 전체적인 질서가 점점 더 좋아질것이다.
16.3.2 기존의 코드를 믿지 말고, 냉정하게 파악하기
- 레거시 코드를 박멸하려면, 기존의 코드를 맹신하지 않는 마음가짐이 중요하다.
- ‘이코드는 무엇을 해결하고 싶은 코드일까?’, ‘이 코드가 달성하려는 목적은 무엇일까?’를 분석한다.
- 이상적인 설계를 다시 하기 위해서는 넘어야 할 장애물이 있다.
- 앵커링 효과
- 처음 제시한 수치와 정보가 기준이 되어, 이후의 판단을 왜곡하는 인지 편향을 의미한다.
- 기존의 클래스 이름과 메서드 이름이 기준이 되어서, 개발자 판단을 왜곡시키는 경우가 굉장히 많다.
- 이름이 없거나, 이름을 모르는 것은 인지하기 어렵다.
- 예를 들어 ‘매매 계약’ 이라는 이름이나 개념을 모르면 관련된 조건의 존재도 알기 힘들다.
- 관계자를 찾아 대화하거나, 관련된 글을 읽고 그곳에서 쓰이는 용어를 파악하고 이해해야한다.
- 앵커링 효과
- 이러한 두 장애물을 극복하면 냉정하게 정체를 파악하고 클래스와 메서드에 정체를 표현하는 이름을 붙일 수 있을 것이다.
16.3.3 코딩 규칙 사용하기
- 코딩 규칙이란 코드의 가독성과 유지 보수성 향상, 문제가 있는 코드를 미연에 방지하기 위한 목적 등으로 코딩 스타일과 명명 규칙 등을 정해 놓은 것이다.
- 코딩 규칙을 잘 준수하면, 코드의 구조와 이름에 질서가 생기고 읽기 쉬워진다.
16.3.4 명명 규칙
- 명명 규칙이란 변수 이름, 클래스 이름, 메서드 이름을 정하는 규칙이다.
요소 규칙 예
클래스 | 어퍼 카멜 케이스 | Customer |
메서드 | 로어 카멜 케이스 | payMoney |
상수 | 모두 대문자, 구분자로 _를 사용 | MAX_NAME_LENGTH |
- 어퍼 카멜 케이스는 단어의 앞글자를 모두 대문자로 하는 규칙
- 로어 카멜 케이스는 두 번째 단어부터 앞글자를 대문자로 하는 규칙
- 이외에도 모든 글자를 소문자로 사용하고 단어 구분자를 _로 사용하는 스네이크 케이스등이 있다.
- 중요한 점은 팀 전체에서 통일된 규칙을 정하고 이를 활용해 가독성을 높이는 것이다.
16.4 리뷰
16.4.1 코드 리뷰 구조화하기
- 레거시 코드가 작성되는 현장이라면, 코드 리뷰를 안하는 경우가 많다. 동작만 가능하도록 작성된 난잡한 코드가 누구의 확인도 받지 않고 병합된다.
- 이런 코드는 결국 품질이 떨어져 버그가 빈번하게 발생한다. 버그만 고쳐보려고 해도 비슷한 버그가 또 발생할 것이다.
- 깃허브에는 다른 팀원이 승인한 풀 리퀘스트(PR)만 병합(merge)할 수 있는 기능이 있다. 그 외에도 코드 품질 분석과 단위 테스트와의 연동, 자동 실행 등의 CI 기능이 다양하게 제공되므로 꼭 활용해보길 바란다.
- 코드의 히스토리와 경위를 알고 있는 사람이나 설계를 자세하게 아는 사람이 리뷰하는 것이 좋다.
- PR 작성 시 템플릿 텍스트에는 리뷰 관점을 명시하는 것이 좋다. 보이스카우트 규칙 확인 항목, 설계 규칙과 관련된 링크를 포함하는 것도 좋다.
16.4.2 코드를 설계 시점에 리뷰하기
- 많은 사람이 코드 리뷰를 로직이 기능 요건을 만족하는지, 결함이 존재하는지, 코딩 스타일을 지키고 있는지 리뷰하는 것이라고 생각하지만 이보다는 설계적 타당성을 중심으로 리뷰해야 한다.
- 이 책에서 언급했던 여러 설계 관점과 비교해 보면서 리뷰하기 바란다.
16.4.3 존중과 예의
- 코드 리뷰 시 기술적 올바름을 두고 공격적인 코멘트를 다는 사람이 있다. 아무리 옳은 말이라도 공격적 코멘트는 안된다. 이러한 리뷰는 사람에게 상처를 주고, 생산성을 저하시키는 것은 물론, 코드를 좋게 만든다는 본래의 목표도 저해한다.
- 리뷰에서 가장 중요한 것은 존중과 예의이다. 리뷰를 받는 사람에 대한 존중을 먼저 생각하자. 기술적 올바름과 유용성보다도 함께 일하는 동료에 대한 존중이 먼저다.
- 다음은 구글 크로미움 프로젝트의 리뷰 지침, 존중하는 코드 리뷰이다.
해야 하는 것 설명
능력과 선의를 갖고 있다고 생각하기 | 개발자는 능력이 있고 선의를 갖고 있다고 생각하세요. 실수는 정보 부족으로 인해 발생하는 것이라고 생각하세요. |
만나서 이야기하기 | 리뷰 도구만으로 의견이 모이지 않는 경우, 직접 만나 의견을 교환하세요. |
이유를 설명하기 | 왜 잘못되었는지, 어떤 변경이 더 좋은지 설명하세요. 이렇게 하면 안된다는 말만으로는 상대에게 의견이 전달되지 않습니다. |
이유 듣기 | 상대방의 의도를 모르겠다면 주저하지 말고 변경 이유를 물어보세요. |
잘 끝맺기 | 완벽을 위해 너무 철저하게 리뷰하다 보면, 리뷰 받는 사람이 너무 힘들어집니다. 완벽을 찾으려고 하기보다 이렇게 하는 것이 더 좋을 것 같다라는 의견으로 리뷰를 적절하게 끝맺는 것이 좋습니다. |
적절한 시간 내에 답변하기 | 리뷰를 계속 방치하지 마세요. 24시간 내에 답변할 수 없다면, 언제까지 답변할 수 있는지 코멘트를 달아 주는 등 적절한 방법으로 대응하세요. |
긍정적인 부분 이야기하기 | 리뷰는 모든 잘못된 부분을 찾겠다는 비판적인 마음으로 임하지 말고, 긍정적인 부분을 인정하는 자세로 임하세요. 억지로 칭찬할 필요는 없지만, 어려운 일을 맡은 사람과 좋은 변경을 한 사람에게 감사하는 마음을 표현해 보세요. |
하지 말아야 하는 것 설명
나쁜 말 사용하지 않기 | 상대방이 최선을 다하고 있다는 것을 전제로 합니다. 왜 신경쓰지 못했죠? 처럼 공격적인 말은 달아선 안 됩니다. |
극단적이고 부정적인 표현 사용하지 않기 | 일반적인 사람이라면 이러지 않는다, 끔찍한 알고리즘이다 라는 부정적인 표현을 사용해서는 안 됩니다. 사람을 공격해서 움직이려고 하면 안 됩니다. 사람이 아니라 코드에 대해서 이야기해야 합니다. |
도구 사용을 단념 시키지 말기 | 작성자가 코드 포매터 등 자동화 도구를 사용했다면, 일단 그 자체에 감사해야 합니다. 도구 사용에 대해 시비를 걸거나, 도구에 대한 취향을 강요해서는 안 됩니다. |
사소한 것으로 시간 오래 끌지 않기 | 어떻게 해도 괜찮을 것 같은 경우, 리뷰에서 둘 중 하나를 결정하려 하지 마세요. 리뷰의 목적은 이기고 지는 것이 아닙니다. |
16.4.4 정기적으로 개선 작업 진행하기
- 구현이나 코드 리뷰 중간에 좋지 않은 코드를 발견했는데, 스케줄 문제로 대처하지 못하는 경우가 있을 수 있다. 이때 일반적으로 나중에 고치자하고 넘어가곤 한다.
- 하지만 이렇게 넘어간 결함은 대부분 대책 없이 방치된다. 왜냐하면 새로운 업무가 계속해서 할당되기 때문에, 새로운 업무에 정신이 팔려서 잊어버리기 때문이다.
- 좋지 않은 코드에 대처하는 일은 작업 관리 도구에 개선 작업으로 추가해두고 정기적으로 이런 작업을 모아 개선 작업을 진행해서 확실하게 대처하는 것이 좋다.
- 예를 들어 주 1회 팀 회의에서 이번 주에 진행할 개선 작업에 대한 논의를 한다든지 하면 좋을 것이다.
- 작업 관리에는 깃허브의 이슈를 활용하면 좋다. 소스 코드, PR과 연동되기 때문에 편리하다.
16.5 팀의 설계 능력 높이기
- 이 장에서 지금까지 다룬 개발 프로세스는 설계 역량이 뛰어난 팀원이 어느 정도 있을 때의 이야기다.
- 그런데 팀에 따라서는 설계를 잘 아는 팀원이 아예 없을 수도 있다. 이런 환경에서는 리뷰뿐만 아니라 설계와 구현 개선 제안도 힘들다.
- 팀 전체의 설계 능력이 부족하면, 설계 능력을 높이기 위한 활동이 필요하다.
16.5.1 영향력을 갖는 규모까지 동료 모으기
- 혼자서 품질 문제를 깨닫고, 설계를 개선하려고 했다고 생각해보자. 혼자 힘으로는 효과가 거의 나지 않는다. 오히려 남들은 지시한 대로 일하지 않고, 쓸데없이 다른 일을 한다고 생각할 수도 있다.
- 설계뿐만 아니라 일의 방식을 상향식으로 개선하려면, 주위의 협력이 반드시 필요하다.
- 협력이 왜 필요할까? 서로 협력해야 일하는 방식을 바꿀 만큼 큰 영향력이 생기기 때문이다. 우선은 영향력을 가질 수 있을 만큼 동료를 모으는 게 중요하다. 영향력을 발휘할 수 있는 규모는 어느 정도 일까?
- 시장 점유율의 목표를 정의하는 쿠프만 목표라는 것이 있는데 쿠프만 목표치는 점유율 10.9%이다. 이 수치를 엔지니어 팀에 적용해서 생각해 보자. 만약 팀이 20명이라면 약 2명이다. 그렇게 많은 수는 아니다. 팀이 20명 정도라면, 자신 이외의 동료를 한 명만 끌어들여도 진행할 수 있다는 이야기이다.
16.5.2 천리길도 한 걸음부터
- 동료를 발견하면 곧바로 이 책의 내용들을 한꺼번에 전달하고 싶은 충동이 생길 수도 있다.
- 매일매일 조금씩 설계 지식을 공유하도록 하자.
16.5.3 백문의 불여일견
- 동료와 설계 지식을 어느 정도 공유했다면, 함께 클래스를 설계하고 구현한 뒤 리뷰해 보자.
- 백문이 불여일견이라는 말처럼 사물의 모습은 말로 설명을 듣는 것보다, 실제로 보고 실감할 때 확실히 알 수 있다. 설계도 마찬가지이다.
- 실제로 손을 움직여서 코드의 가독성이 좋아지고, 중복 코드가 줄어드는 모습을 동료들과 실감하고 공유해 보자.
16.5.4 팔로우업 스터디 진행하기
- 처음에는 독서 모임 느낌으로 설계 관련 서적을 읽으면서 진행하는 것도 좋다. 하지만 이전에 언급했던 것처럼 역시 실제로 코드를 개선해 보는 것이 효과적이다. 인풋보다 아웃풋이 학습 효과가 높다고 한다.
- 추천하는 스터디 흐름
- 책에 적혀 있는 노하우를 1~2개 정도 읽어 본다.
- 프로덕션 코드에서 노하우를 적용해 볼 수 있는 부분을 찾는다.
- 노하우를 사용해 코드를 개선해 본다.
- 어떻게 개선했는지 비포&애프터를 비교할 수 있게 발표한다.
- 발표 내용에 대해 질의 응답과 논의를 한다.
- 스터디는 한 번에 한 시간 정도, 스몰 스탭으로 반복한다. 이렇게 하면 인풋, 아웃풋, 피드백을 빠르게 반복할 수 있어서, 효과적으로 공부할 수 있다.
16.5.5 스터디 그룹에서 발생할 수 있는 문제 해결 노하우
- 스터디 방식에 따라 효과를 아예 얻지 못하고, 오히려 설계에 대한 인식을 나쁘게 만드는 경우도 있으므로 주의해야 한다.
- 일단 단순하게 책을 읽기만 하는 스터디는 추천하지 않는다. 아웃풋이 동반되지 않으므로 학습 효과가 낮다. 그리고 한 번에 많이 인풋해도 사람들은 업무가 바빠 관련된 내용을 금방 잊어버린다.
16.5.6 리더와 매니저에게 설계의 중요성과 비용 대비 효과 설명하기
- 조직 차원에서 설계 품질을 향상시키려면, 개발 프로세스 흐름에 설계를 추가해야 한다. 그러려면 리더와 매니저도 설계의 필요성을 공유해야 한다.
- 매니저에게 비용 대비 효과를 중심으로 이야기 하자.
- 개발 효율 저하 문제를 이야기하고, 이런 문제를 해결할 수 있는 설계 업무가 있음을 알리자. 그리고 설계에 비용을 투자해야 하는 이유를 설명하자.
- 매니저에게 설명할 때는 혼자가 아니라, 동료와 함께하는 것이 바람직하다. 동료들과 했던 설계 활동과 그 실적을 함께 설명하면 설득력이 더 높아질 것이다.
16.5.7 설계 책임자 세우기
- 개발 팀원 대부분이 설계 품질을 좋게 만드는 데 적극적이라면, 품질 향상 작업이 자연스럽게 이루어진다. 하지만 그렇지 않은 경우, 설계 책임자를 내세우는 것이 좋다.
- 설계 책임자는 변경 용이성 품질 향상을 위해, 다음과 같은 내용을 추진한다.
- 설계 품질과 관련된 규칙이나 개발 프로세스 수립
- 규칙을 반복적으로 알리고 교육
- 리더와 매니저에게 효과 공유
- 품질 시각화
- 설계 품질 유지
- 설계 규칙, 코딩 규칙, 리뷰 방법 등 설계 품질과 관련된 규칙과 개발 프로세스를 수립하도록 하자.
- 규칙을 정하면 팀원들에게 확실하게 인지시키고 필요하다면 스터디를 하는 등 교육도 진행하자.
- 추가로, 개발 팀원뿐만 아니라 리더와 매니저에게도 평소 설계와 개발 비용 관련 내용을 계속해서 공유해야 한다.
- 설계 품질 향상에 도움을 주는 도구를 도입하는 것도 좋다. 품질을 시각화하고, 품질 향상을 효율화할 수 있다.
'내 코드가 그렇게 이상한가요?' 카테고리의 다른 글
15장 설계의 의의와 설계를 대하는 방법 (0) | 2024.04.13 |
---|---|
14장 리팩터링: 기존의 코드를 성장시키는 기술 (0) | 2024.04.12 |
13장 모델링: 클래스 설계의 토대 (0) | 2024.04.12 |
14장 리팩터링: 기존의 코드를 성장시키는 기술 (0) | 2024.04.12 |
12장 메서드(함수): 좋은 클래스에는 좋은 메서드가 있다 (0) | 2024.04.04 |