레코드 캡슐화하기 (Encapsulate Record)

• public 필드 아무데서나 접근 가능한 것을 메소드를 통해 감추는 것

컬렉션 캡슐화하기 (Encapsulate Collection)

• 클래스가 가지고 있는 컬렉션에 접근하는 자체를 캡슐화하는 방법입니다. 컬렉션 자체를 캡슐화하는 것. 컬렉션을 외부에 그대로 노출하면 캡슐화를 할 수 없습니다. 그 컬렉션이 외부에서 계속 바뀔 수 있습니다. 컬렉션의 복사본을 전달하거나 컬렉션에 추가하거나 뺄 수 있는 메소드를 제공합니다.

기본형을 객체로 바꾸기 (Replace Primitive with Object)

• 일반, white, silver, gold, vip, vvip 등 기본형(숫자 또는 문자열)로 표현한 데이터가 나중에는 해당 데이터와 관련있는 다양한 기능을 필요로 하는 경우 클래스로 감싸고 필요한 기능을 추가합니다.

임시 변수를 질의 함수로 바꾸기 (Replace Temp with Query)

• 변수를 사용하면 반복해서 동일한 식을 계산하는 것을 피할 수 있고, 이름을 사용해 의미를 표현할 수도 있습니다 • 긴 함수를 리팩토링할 때, 그러한 임시 변수를 함수로 추출하여 분리한다면 빼낸 함수로 전 달해야 할 매개변수를 줄일 수 있습니다. ex) rate 계산 로직을 통해 얻은 rate 변수 temp를 getRate 함수(Query)로 빼내기

클래스 추출하기 (Extract Class)

  • 클래스가 코드가 많아지고 할 일이 많아지면서 메서드 필드가 늘어나는데 divergent change 뒤엉킨 변경 다양한 이유로 하나의 클래스가 계속해서 바뀌는 일이 생깁니다. 클래스가 커질수록 테스트가 어려워지고 해당 클래스를 이해하는 것이 어려워집니다. 클래스에 들어있는 필드 메서드들이 다른 것들에 비해 밀접한 경우, 일부 필드나 메서드를 변경할 때 그 데이터와 관련 있는 메서드나 또 다른 관련 데이터를 바꿔야하는 경우가 있는데 이럴 경우 따로 추출할 수 있습니다. 일부 필드나 메서드를 빼내보고 어떻게 바뀌어야하는지 생각할 수 있습니다. 하위 클래스를 만들어서 책임을 분산시킬 수도 있습니다. ex) 지역코드, 지역번호 필드 및 getter setter 등의 메서드에 대해 TelephoneNumber 클래스로 추출

클래스 인라인하기 (Inline Class)

  • Inline Class의 경우 클래스 전체의 필드와 메서드를 다른 클래스로 옮기는 것입니다. 리팩토링 하다보면 클래스가 감당해야할 역할이 옮겨다닙니다. 어떤 클래스가 단순히 위임 validation 되어있는 경우가 있는데 한 곳으로 모으는게 응집도를 높일 수 있겠다고 판단하면 Inline Class를 쓸 수 있습니다. 2개로 나누어진 클래스를 한 곳으로 모은다음 다시 여러 클래스로 추출할 수도 있습니다. Inline function도 다른 function들을 하나의 큰 거대한 function으로 모은 후 다시 extract function을 할 수 있습니다. ex) Shipment 클래스가 TrackingInformation 클래스를 필드로 두고 위임하는 경우에서 TrackingInformation의 필드 및 메서드를 추출하여 직접 사용하는 방식으로 변경함으로써 단일 클래스로 합치고 응집도를 높입니다

위임 숨기기 (Hide Delegate)


  • 어떤 모듈이 알고 있는 정보를 최소한으로 관리할수록 나중에 무언가가 변경됐을 때 그 변경에 뒤따라서 변경되야하는 부분이 줄어들기 때문에 캡슐화가 중요합니다. 클라이언트가 최소한의 정보만 알고 코드를 사용할 수 있도록 변경하는 것이 이 리팩토링의 주요 목적입니다. person.department().manager(); -> person.getManager(). 클라이언트가 department라는 정보를 가지고 있어야 manager를 가져올 수 있구나라고 알 필요 없이 manager가 필요하다면 person이 가진 getManager만 호출하는 방식으로 변경합니다.

중재자 제거하기 (Remove Middle Man)

  • 메서드를 만들고 메서드 체인에 해당하는 호출을 메서드 안으로 숨겨서 캡슐화를 했다면 이 리팩토링은 반대로 메세지 체인을 만드는 리팩토링입니다. 필요로 하는 캡슐화의 정도는 시간이나 상황에 따라 달라집니다. 왜 자꾸 중간에 있는 객체를 통해서 저 객체를 사용하지? 의문이 많아진다면 중재자 제거하기(remove middle man)을 적용할 수 있습니다. 디미터 법칙(Law of Demeter) 가장 가까운 객체만 사용한다. 어떤 메서드 안에서 그 메서드가 포함되어잇는 클래스에 있는 다른 메서드 호출은 괜찮다. 메서드 파라미터로 받은 다른 객체나 레코드를 직접 호출하는 것은 괜찮다. 그 호출도 거쳐서 다른 객체를 호출하면 안되고 오로지 딱 그 작업만 하는것. 본인이 가진 필드에 속한 메서드 호출은 괜찮다. 등 가까운 객체. 그 이외에 . 찍어서 메서드 체인을 하는 것은 좋지 않다. 이 법칙을 지나치게 따를 경우 Middle man에 해당하는 메서드들이 많이 생기고 심각하게 캡슐화를 많이 했다고 느끼는 순간이 올 수 있습니다. 그 때 remove middle man을 적용합니다.

알고리즘 교체하기 (Substitute Algorithm)

모듈화를 잘해놓으면 알고리즘 교체하기 리팩토링 적용이 수월해집니다. 함수가 가진 날짜 계산, 월세 계산 등 특정 알고리즘 계산식 로직 자체를 바꿀 수 있습니다. encapsulation이 잘되어있을 때 얻을 수 있는 이점들입니다.

참고자료