본문 바로가기
Web development/Books

Refactoring - Bad Smells

by 자몬다 2019. 12. 31.
Martin Fowler - Refactoring을 읽고 정리한 글입니다.(76~79p)

요약

Divergent Change - 분기/갈라짐 하는 변화(확산적 변화)

  • 냄새 : 여러 다른 수정이 필요할때마다, 어떤 하나의 모듈을 매번 수정해야 함.
  • 해결책 : 한 모듈에 하나의 책임, 하나의 이유로 한 모듈의 수정

Shotgun Sergery - 샷건 수술

  • 냄새 : 변경할 때마다, 많은 클래스들에 많은 작은 수정이 필요한 경우.
  • 해결책
    • 데이터 구조를 변경하거나 늘리는 펑션이 있으면 - 펑션을 합쳐서 클래스로 만들거나, 단계를 나눠라.
    • 쪼개진 로직을 합치는 좋은 방법은 인라인 리팩토링이다. - 인라인 펑션, 인라인 클래스
  • 개편을 위한 중간 단계로서 큰 것을 만드는걸 두려워해선 안됨

Feature Envy - 피쳐 질투(기능에 대한 욕심)

  • 냄새 : 메소드가 다른 모듈들에서 수행할 역할을 자꾸 탐냄 - 권한에서 벗어나는 역할을 수행하려 함.
  • 예를들면 게시글 조회 메서드가 유저정보나 댓글 정보까지 직접 가져오려는 경우.
  • 해결책 : 기능에 맞는 역할만 하고, 여의치 않을 경우 가장 많은 비중을 차지하는 모듈에 메서드를 위치시킴.

Data Chumps - 데이터 덩어리

  • 데이터아이템은 몰려다니기를 좋아함.
  • 해결책
    • 자주 뭉쳐다니는 필드나 데이터들이 있으면 클래스로 추출해서 오브젝트로 만들어라.
    • 슬림하게 만들어라 - 데이터 값 중 하나를 삭제했는데 문제없으면 없애도 된단 뜻이다.
    • 단순한 레코드 구조가 아니라 클래스를 만들어라. 그래야 좋은 향기를 만들 기회를 얻는다. 클래스를 사용하면 피쳐 질투 케이스를 찾아 다른 새 클래스에 넣을 수도 있다.

Primitive Obsession - 기본 타입에 대한 집착

  • 신기하게도 도메인에 필요한 고유한 타입들을 만드는데 꺼리는 사람이 많다.
  • 데이터의 특성을 무시하고 그냥 기본 타입으로 처리하는 경우가 많다.
  • 해결책
    • 기본 타입을 오브젝트/서브클래스와 코드/다형성 있는 조건으로 대체하기
    • 이런 케이스는 보통 데이터덩어리 케이스와 같이 발생한다. 클래스로 추출하고 매개변수 오브젝트를 사용하자.

Repeated Switches - 반복되는 스위치문

  • 스위치 조건문이나 if문으로 도배됨
  • 상습적으로 사용되는 것이 아니라 한 메서드 안에서만 그런거라면 굳이 바꿀 필요는 없음

Loops - 반복문

  • 예전엔 더 나은 선택지가 없었지만, 요즘은 좋은 펑션들이 보급되어 있고, pipeline으로 루프문을 대체할 수 있다.

  • pipeline operation - for/if문 중첩같은 코드를 .filter.map 같은 펑션 체이닝으로 대체하는것

    // original code const names = []; for (const i of input) { if (i.job === "programmer") names.push(i.name); }

    // pipeline code const names = input .filter(i => i.job === "programmer") .map(i => i.name);


번역

확산적 변경

한 모듈의 펑션들이 다양한 이유와 방법으로 자주 수정됨. 새 상품이 추가되거나 데이터베이스가 추가될때마다 어떤 모듈을 계속 수정해야 하고, 이 경우 모듈을 분리해야 한다. 모듈이 분리되면, 한 이슈를 수정할 때 그 이슈 관련 맥락만 이해하면 된다. 예전에는 일반적으로 컨텍스트들의 경계가 분명하지 않아서 소프트웨어 시스템 capability를 자주 변경해야 했다. 

데이터를 가져와서 다른 처리를 해야되면 - 페이즈를 분리

여러곳의 데이터를 사용한다면 더 많은 데이터를 부르는 쪽으로 - 펑션 이동

두가지 타입의 처리과정이 섞여 있다면 - 펑션(클래스)으로 분리

하는 것이 좋다.

 

샷건 수술

확산적 변경과 비슷하지만 반대 케이스이다. 변경할 때마다, 많은 클래스들에 많은 작은 수정이 필요한 경우, 변경할 곳을 찾기도 힘들고 중요한 수정을 놓치기도 쉽다. 이 경우 (펑션/필드를 이동시켜) 한 모듈에서 수정할 내용을 모아놓고 싶을 것이다. 비슷한 데이터를 다루는 펑션이 많은 경우 펑션을 합쳐서 클래스로 만들어라. 

데이터 구조를 변경하거나 풍성하게 하는 펑션이 있으면 - 펑션을 합쳐서 클래스로 만들거나, 단계를 나눠라. 로직의 소모적 단계를 위해(?) 일반적인 펑션들의 결과를 조합할 수 있다.

샷건으로 형편없이 쪼개진 로직을 합치는 좋은 방법은 인라인 리팩토링이다. - 인라인 펑션, 인라인 클래스처럼

우리가 작은 펑션, 작은 클래스를 지나치게 좋아하긴 하지만, 개편을 위한 중간 단계로서 큰 것을 만드는걸 두려워해서도 안된다.

 

피쳐 질투

우리는 프로그램을 모듈화할 때, 영역 내부의 상호작용을 최대화하고 영역 간 상호작용을 최소화하기 위해 코드를 영역으로 분리한다.

한 모듈의 함수가 다른 모듈에 있는 함수/데이터와 소통하는데 더 많은 시간을 쓸 때 발생한다.

해결법은 명확하다. 펑션은 데이터와 함께 하므로 많은 데이터를 쓰는 쪽으로 펑션을 이동시킨다.

특정한 부분만 다른 모듈의 기능이 많이 필요한 경우, 펑션으로 분리해라. 그리고 펑션을 이동시켜서 가고싶어하는 고향집으로 데려다 줘라ㅋㅋ

모든 케이스가 딱 맞아떨어지진 않는다. 어떤 펑션은 여러 모듈의 기능들을 사용하기도 한다. 그럴땐 다 찢어서 다른데 두는것보다 펑션으로 분리(추출)해서 제일 데이터 많이 쓰는곳에다 두는게 낫다.

 

Data Chump - 데이터 덩어리

데이터아이템은 몰려다니기를 좋아한다. 자주 뭉쳐다니는 필드나 데이터들이 있으면 클래스로 추출해서 오브젝트로 만들어라.

파라미터 오브젝트나 전체 오브젝트 보존해서 데이터 덩어리를 슬림하게 만들 수 있다.

데이터 값 중 하나를 삭제했는데 문제없으면 없애도 된단 뜻이다.

단순한 레코드 구조가 아니라 클래스를 만들어라. 그래야 좋은 향기를 만들 기회를 얻는다. 클래스를 사용하면 피쳐 질투 케이스를 찾아 다른 새 클래스에 넣을 수도 있다. 유용한 클래스는 중복을 제거해서 데이터 생산성이 좋아지고, 미래에 개발도 빨리 될 수 있도록 한다.

 

Primitive Obsession - 기본 타입에 대한 집착

기본 타입은 벽돌과 같다.

신기하게도 도메인에 필요한 고유한 타입들을 만드는데 꺼리는 사람이 많다.

금액, 좌표, 범위(연령대 등의 특정 범위) 

길이나 화폐 단위도 특성을 무시하고 그냥 정수로 처리하는 경우가 많다.

String은 특히나 이런 냄새의 배양소다. 전화번호는 그냥 문자열 집합이 아니다.

기본 타입을 오브젝트/서브클래스와 코드/다형성 있는 조건으로 대체하기

이런 케이스는 보통 데이터덩어리 케이스와 같이 발생한다. 클래스로 추출하고 매개변수 오브젝트를 사용하자.

 

Repeated Switches - 반복되는 스위치문

객체지향 전도사들은 곧 스위치 조건문의 악마가 된다.

아니면 if문으로 도배하기도 한다.

switch문을 볼땐 항상 다형성을 생각

상습적으로 사용되는 것이 아니라 한 메서드 안에서만 그런거라면 굳이 바꿀 필요는 없음

 

Loops - 반복문

프로그래밍에 있어서 반복문은 언어 초기 단계부터 핵심 파트였다.

하지만 이젠 나팔바지나 촌스러운 벽지보다도 부적절하다.

그 시대의 언어들은 더 나은 선택지가 없었다.

하지만 요즘은 좋은 펑션들이 보급되어 있고, pipeline으로 루프문을 대체할 수 있다.

pipeline operation - for/if문 중첩같은 코드를 .filter.map 같은 펑션 체이닝으로 대체하는것

'Web development > Books' 카테고리의 다른 글

Refactoring - Inline Class  (0) 2019.12.31
Refactoring - Encapsulate Collection  (0) 2019.12.31
Refactoring - Introduce Parameter Object  (0) 2019.12.31
Refactoring - Rename Variable  (0) 2019.12.31
Refactoring - Building Test  (0) 2019.12.31

댓글