3. 수정의 산발 Divergent Change

[ 2017-07.18 작성 ]

Symptoms

코드의 이곳 저곳을 돌아다니면서 고쳐주어야 할 것이 많다면 코드는 이미 구조적으로 잘못되었을 가능성이높다.
따라서 이런 코드들은 변경에 의한 버그 발생가능성이 높은 상태라고 볼 수 있다.

Reasons for the Problem

개발자가 지름길을 선택하는 구현 태도에 있다. 즉, 일정에 대한 압력이 높을 경우 기능 추가나 모델 추가와 같은 것을 'Copy & Paste'를 사용해서 처리하기 때문이다.

Treatment

  • 추출 클래스를 통해 클래스의 동작을 분할합니다.
  • 다른 클래스가 동일한 동작을 하는 경우 상속을 통해 클래스를 결합 할 수 있습니다. (Extract Superclass and Extract Subclass)
  • 인터페이스로 단일화 한다.

Payoff

코드의 구조가 좀 더 명확하게 드러나게 됩니다.(상위 Class와 하위 Class라는 계층적인 관계) - 코드 구성 개선
여러군데로 나뉘어진 복제된 코드들을 줄이기에 코드의 중복을 줄어들게 된다. - 코드 중복 제거
코드는 연결이 많을수록의존성이 높아지며 복제된 코드가 많을수록 변경 관리가 어려워진다. 따라서 유지 보수가 편한 코드를 만들기 위해서는 계층적인 구조와 복제된 코드의 제거는 반드시 필요하다. - 지원을 간소화

1. class diagram

Divergent Change.png

공통 메서드를 가진 두 static 클래스가 있습니다.
추출클래스(Extract Class)를 통해 동작을 분할합니다.

2. sample code

OrderDetailBuilderQuery.cs
 public static ListQuery<OrderDetailItem> GetListPartnerOrderSendList(OrderSearchVO searchVO, int joinerId, int startNum, int endNum)
{
   string Condition = OrderDetailQueryHelper.GetWhereQueryByConditons(searchVO);

return new ListQuery<OrderDetailItem>() 
{
  Query = $@"
  SELECT * FROM (
  SELECT ROW_NUMBER() OVER (ORDER BY { OrderDetailQueryHelper.PartnerProductOrderSorting(searchVO.SortOrderValue, searchVO.SortOrderType) }) rownum, a.*, b.strOrderCode 
  ......
 ) a WHERE rownum between {startNum} and {endNum} order by rownum
 "  
OrderDetailQuery.cs
public static ListQuery<OrderDetailItem> GetExcelUseColumn(string orderIds, string sortOrderValue, string sortOrderType)
{
return new ListQuery<OrderDetailItem> 
{
   Query = $@"
  ......
  , dbo.DS_입금파일입고기준_확정시작일(b.intOrderNum) datTradeDate
  FROM OrderItem a
  ......
  WHERE a.intOrderNum IN({ orderIds })
  ORDER BY { OrderDetailQueryHelper.PartnerProductOrderSorting(sortOrderValue, sortOrderType) }",
  };
}
OrderDetailQueryHelper.cs
public static string PartnerProductOrderSorting(string sortOrderValue, string sortOrderType)
{
   if (sortOrderValue.Equals("datTradeDate")) return $"dbo.DS_입금파일입고기준_확정시작일(b.intOrderNum) { sortOrderType }, a.intOrderNum Desc, a.intOrderItemNum Desc";
   if (sortOrderValue.Equals("intOrderNum")) return $" a.intOrderNum { sortOrderType }";
return $"{ sortOrderValue } { sortOrderType }";
}