노트

플래그 인수

Flag Argument

설계#refactoring · 연결된 개념 7개

쉽게 말하면

플래그 인수는 함수에 참·거짓 값 하나를 넘겨 무슨 일을 할지 고르게 하는 거예요. 호출하는 곳에 '참'만 덩그러니 보이면 뜻을 알 수 없어서, '빠른 배송 날짜', '일반 배송 날짜'처럼 이름이 다른 함수로 나누는 게 읽기 쉬워요.

비유가 깨지는 곳 참·거짓 값을 넘기는 게 다 문제는 아니에요. 리터럴로 넘길 때가 문제고, 데이터에서 계산된 isRush 같은 값을 넘기는 건 괜찮아요. 플래그가 여럿이면 함수가 너무 많은 일을 한다는 신호예요.

호출하는 쪽이 함수 안에서 실행할 로직을 고르려고 넘기는 인수. 호출문만 봐서는 무슨 뜻인지 알기 어렵고, 함수가 어떤 기능들을 제공하는지도 숨긴다.

// before
deliveryDate(order, true) // true가 뭐지?
 
// after
rushDeliveryDate(order)
regularDeliveryDate(order)
  • 문제는 불리언 자체가 아니라 리터럴로 넘긴다는 점이다. deliveryDate(order, isRush)처럼 데이터에서 계산된 값을 넘기는 건 괜찮다
  • 분기가 함수 맨 위에서 갈린다면 함수를 둘로 나눈다. 안쪽 깊이 얽혀 있다면 rushDeliveryDate = o => deliveryDate(o, true) 같은 감싸는 함수를 만들고 원래 함수는 직접 부르지 못하게 한다
  • 플래그가 둘 이상이면 조합 수만큼 함수를 만들기 어려워 플래그를 쓸 핑계가 되지만, 그 자체가 함수가 너무 많은 일을 한다는 신호이기도 하다
  • 반대 방향 리팩터링도 있다. 리터럴 값만 다른 비슷한 함수들(tenPercentRaise, fivePercentRaise)은 값을 매개변수로 받는 하나의 함수로 합친다(함수 매개변수화하기, Parameterize Function)

React 컴포넌트의 isPrimary, isLarge 같은 불리언 prop이 늘어날 때도 같은 냄새가 난다. variant 같은 값 하나나 컴포넌트 합성으로 바꾸는 편이 낫다. 긴 매개변수 목록의 다른 처방은 매개변수 객체 만들기.

출처: 『리팩터링 2판』 마틴 파울러 (원서 Refactoring, 2nd Edition) · refactoring.com: Remove Flag Argument · Martin Fowler: Flag Argument · Refactoring.Guru: Replace Parameter with Explicit Methods

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 임시 변수를 질의 함수로 바꾸기

    계산 결과를 담아 두던 임시 변수를 그 값을 돌려주는 함수로 바꾸는 리팩터링. 긴 함수를 쪼개기 전 단계로 특히 쓸모 있다.

  • 함수 선언 바꾸기

    함수의 이름이나 매개변수 목록을 바꾸는 리팩터링. 가장 자주 쓰는 리팩터링이 이름 바꾸기인 것은, 이름이 코드를 명료하게 하는 가장 큰 도구이기 때문이다.

  • 반복문을 파이프라인으로 바꾸기

    for 반복문을 filter·map·reduce 같은 컬렉션 연산의 연쇄, 즉 컬렉션 파이프라인(Collection Pipeline)으로 바꾸는 리팩터링. 각 원소가 어떤 단계를 거치는지가 위에서 아래로 읽힌다.

  • 함수·필드 옮기기

    함수나 필드를 더 자연스러운 맥락(모듈·클래스)으로 옮기는 리팩터링. 좋은 설계의 핵심인 모듈성(Modularity), 즉 어딘가를 고칠 때 관련된 작은 부분만 이해하면 되게 하는 능력을 키운다.

  • 조건문 분해·통합

    복잡한 조건문의 조건식과 각 분기 본문에 의도를 드러내는 이름을 붙이는 리팩터링(분해, Decompose Conditional), 그리고 결과가 같은 여러 조건 검사를 하나로 묶는 리팩터링(통합, Consolidate Conditional Expression). 조건 코드는 무엇이 일어나는지는 말하지만 왜 그런지는 잘 말하지 않는데, 이름이 그 "왜"를 채운다.

보기 옵션