본문으로 바로가기

Boolean Trap

category Language/Python 2022. 4. 7. 13:47
728x90
반응형

Boolean Trap

def some(up:bool):
	if up:
		return to_json()
  return to_dict()
  • 위와 같은 코드를 보고 some이라는 메서드의 내용을 문서를 보기 전에 유추할 수 있는가? 아마 그렇지 못할 것이다. Parameter에 bool를 넘김으로써 동작을 제어하려고 시도했지만 코드를 읽는 사람 관점에서는 some이라는 Method의 동작 내용을 문서를 참고하기 전까지는 자세히 모를 것이다. 이를 Boolean Trap이라 부른다(Anti Pattern)

 

Solution

 

Multiple Function

  • 해당 메서드의 내용을 세분화하자
def some_to_json() ...

def some_to_dict() ...
  • 하지만 위 방법에는 메서드의 기능이 거의 없는 경우 쓸 수 있다. 메서드의 기능이 많은 경우에는 몇 가지 단점이 생긴다.
    • 코드를 분해하는 것이 어려울 수 있다.
    • 많은 수의 함수가 필요할 수 있다.

 

Mutually Exclusive Flags

  • bool 값을 Default로 지정하여 사용하자
round_number(x, up=True)
round_number(y, down=True)
  • typing을 이용하면 아래와 같이도 사용할 수 있다고 한다.
from __future__ import annotations

from typing import Literal, overload


@overload
def round_number(
    value: float, *, up: Literal[True], down: Literal[False] = False
) -> float:
    ...


@overload
def round_number(
    value: float, *, up: Literal[False] = False, down: Literal[True]
) -> float:
    ...


def round_number(
    value: float,
    *,
    up: bool = False,
    down: bool = False,
) -> float:
    behaviours = [x for x in [up, down] if x]
    if len(behaviours) != 1:
        raise TypeError("Exactly one rounding behaviour must be specified.")
    ...
  • 하지만 위와 같이 사용할 시에...
    • 코드가 너무 많음
    • 새로운 기능을 추가하려면 overload 케이스를 작성해야 함
    • 다른 모든 케이스에 Literal [False]를 정의하고, 기본 함수에 인수를 추가해주어야 함

 

Enum Argument를 이용하는 방법

from enum import Enum

class RoundingMethod(Enum):
    UP = 1
    DOWN = 2

def round_number(value: float, *, method: RoundingMethod) -> float:
    if method.value == RoundingMethod.UP.value:
        print("True")
    return 0.0

print(round_number(1.5, method=RoundingMethod.UP))

 

String Literal를 이용하는 방법

RoundingMethod = Literal["up", "down"]

def round_number(value: float, *, method: RoundingMethod) -> float:
    if method == 'up':
        return True
    return False

print(round_number(0.0, method="up"))
  • String Literal은 Enum의 동작 내용이랑 차이는 없지만 코드 라인이 더 적다

 

Reference

728x90
반응형