ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 10. 이름 설계 : 구조를 파악할 수 있는 이름
    Study/내 코드가 그렇게 이상한가요? 2024. 2. 11. 16:55
    반응형

    이름을 짓는 기본적인 방법은 목적 중심 이름 설계이다. 이는 소프트웨어가 달성해야 하는 목적을 기반으로 이름을 설계하는 방법으로, 이름에서 목적과 의도를 읽고 이해할 수 있게 설계해아 한다는 것이다.

    1. 부적절한 이름

    온라인 쇼핑몰을 예로 들어보자. 흔히 볼 수 있는 좋지 않은 이름 설계는 상품을 그대로 '상품 클래스'라고 이름을 붙이는 것이다. 대부분의 로직이 상품을 중심으로 이루어지는 온라인 쇼핑몰 특성상 '상품 클래스'라고 단순하게 이름을 붙이는 순간, 해당 클래스는 수많은 클래스와 관련 있는 로직을 갖게 되고 점점 거대하고 복잡해진다.

    1.1 관심사 분리

    상품은 예약, 주문, 발송 등 다양한 관심사와 연관이 있다. 즉, 상품 클래스는 다양한 관심사와 결합되어, 온갖 것과 관련된 로직을 품게 되는 강한 결합 상태가 된다. 강한 결합을 해소하고, 결합이 느슨하고 응집도가 높은 구조로 만들려면 관심사 분리(separation of concerns)를 할 수 있어야 한다. 따라서 상품 클래스는 관심사에 따라서 각각 클래스로 분할해야 한다.

    1.2 관심사에 맞는 이름 붙이기

    관심사에 따라 각각의 클래스로 분할하면 각각의 이름을 붙여줘야 한다. 주문 목적의 상품은 '주문 상품', 예약에서는 '예약 상품', 발송에서는 '발송 상품' 등으로 이름을 붙일 수 있다. 각각의 관심사에 따라 분할한 후에는 해당 관심사와 관련된 로직을 내부에 캡슐화하면, 결합도를 낮추고 응집도를 높일 수 있다.

    1.3 포괄적이고 의미가 불분명한 이름

    개발 초기에는 포괄적인 이름을 붙이는 경우가 많다. '상품 클래스'와 같이 너무 포괄적인 이름은 내부에 온갖 로직을 구현하게 만든다. 이렇게 이름이 너무 포괄적이라서 목적이 불분명한 목적 불분명 객체는 규모가 커지기 쉽다. 비즈니스 목적에 따라 이름을 붙여 보면서, 관심사 분리를 고려한 이름 설계를 하도록 하자.

    2. 이름 설계하기 - 목적 중심 이름 설계

    프로그래밍에서 이름을 붙이는 것은 가독성을 높이는 역할 뿐 아니라, 결합이 느슨하고 응집도가 높은 구조를 만드는 데 굉장히 중요한 역할을 한다. 목적 중심 이름 설계는 목적에 맞춰 이름을 설계하는 것이다. 즉, 소프트웨어로 달성하고 싶은 목적과 의도를 이름만으로도 알 수 있게 해야 한다.

    1. 최대한 구체적이고, 의미 범위가 좋고, 특화된 이름 선택하기
      • 특정한 목적(소프트웨어로 달성하고 싶은 목적)을 달성하는 데 특화된 의미가 좁은 이름을 클래스에 붙인다. 이는 아래와 같은 효과를 만든다.
        • 이름과 관계없는 로직을 배제하기 쉬워짐
        • 클래스가 작아짐
        • 관계된 클래스 개수가 적으므로, 결합도가 낮아짐
        • 관계된 클래스 개수가 적으므로, 사양 변경 시 생각해야 하는 영향 범위가 좁음
        • 목적에 특화된 이름을 갖고 있으므로, 어떤 부분을 변경해야 할 때 쉽게 찾을 수 있음
        • 개발 생산성이 향상됨
    2. 존재가 아니라 목적을 기반으로 하는 이름 생각하기
      • '사람'과 '사용자'처럼 단순하게 인물이 존재하기 때문에 붙인 이름은 존재 기반 이름이라고 할 수 있다. 온라인 쇼핑의 사용자는 단순한 개인이 아니라 법인일 수도 있으므로 '사용자'는 개인과 법인 모두를 나타내게 되고 이는 쓸데없이 로직을 복잡하게 만들 수 있다.
      • 구체적인 목적을 알 수 있게 목적 기반 이름을 짓는 것이 좋다.
        • 주소 -> 발송지, 배송지, 업무지
        • 금액 -> 청구 금액, 소비세액, 연체 보증료, 캠페인 할인 금액
        • 사용자 -> 계정, 개인 프로필, 직무
        • 사용자 이름 -> 계정 이름, 닉네임(별칭), 본명, 법인명
        • 상품 -> 입고 상품, 예약 상품, 주문 상품, 발송 상품
    3. 어떤 비즈니스 목적이 있는 지 분석하기
      • 비즈니스 목적에 특화된 이름을 만들려면, 어떤 비즈니스를 하는지 모두 파악해야 한다. 소프트웨어가 추구하는 목적과 내용을 화이트보드나 종이에 그려가며 분석해보자.
    4. 소리 내어 이야기해 보기
      • 비즈니스 측면을 잘 이해하고 있는 사람과 이야기하여, 목적과 의도를 잘못 인식하고 있는 부분이 있으면 곧바로 피드백을 받도록 하자. 또한, 이야기를 통해서 좀 더 정확하고 구체적인 비즈니스 목적, 목적에 맞는 이름들을 끌어낼 수 있을 것이다.
        • 고무 오리 디버깅 : 문제가 발생했을 때, 책상 위의 오리 인형에게 문제를 처음부터 차근차근 설명해 보면서 해결하는 방법(실용주의 프로그래머 20주년 기념판, 'Topic 20 디버깅')
        • 즉, 프로그래밍에서 어떤 문제가 발생했을 때, 문제를 누군가에게 설명하다 보면 스스로 원인을 깨닫고 해결할 수 있다는 방법.
    5. 이용 약관 읽어보기
      • 이용 약관에는 서비스와 관련된 규칙이 굉장히 엄격한 표현으로 작성되어 있기 때문에, 이를 활용하면 비즈니스와 관련된 이름을 알 수 있다. '구매자', '판매자', '매매 계약' 등 비즈니스 측면에서 명확한 이름들이 나오기 때문에, 이를 참고하여 명확한 클래스 이름을 붙일 수 있다.
    6. 다른 이름으로 대체할 수 없는지 검토하기
    7. 결합이 느슨하고 응집도가 높은 구조인지 검토하기
      • 목적 이외의 로직이 섞인다면, 이름을 잘못 붙인 것은 아닌지 검토해보자.

    3. 이름 설계 시 주의 사항

    1. 이름에 관심 갖기
      • 이름과 로직이 대응된다는 전제, 이름이 프로그램 구조를 크게 좌우한다는 사실을 명심해야 한다.
    2. 사양 변경 시 '의미 범위 변경' 경계하기
      • 개발 중 계속되는 사양 변경 속에서, 이름이 의미하는 바가 점점 변화하는 경우 이름 설계를 중간중간 다시 검토해야 한다.
    3. 대화에는 등장하지만 코드에 등장하지 않는 이름 주의하기
      • 대화에 등장하는 이름을 신경쓰고, 그 이름을 기반으로 메서드와 클래스를 설계해야 한다.
    4. 수식어를 붙여서 구별해야 하는 경우는 클래스로 만들어 보기
      • 차이를 구분하기 어려운 코드를 '단순하게 수식어를 붙여서 동료에서 설명하는 상황'이 발생한다면, 의미 차이를 확실하게 알 수 있는 이름을 붙이는 것이 좋다.

    4. 의미를 알 수 없는 이름

    1. 기술 중심 명명
      • 프로그래머는 항상 프로그래밍과 관련된 생각을 하기 때문에, 비즈니스 로직의 이름도 프로그래밍과 관련된 용어에서 유래하는 경우가 많다. 이른 방법을 기술 중심 명명이라고 부른다. 이러한 컴퓨터 기술 용어, 프로그래밍 기술 용어는 비즈니스 목적을 나타내는 이름에는 적합하지 않을 수 있으니 주의해야 한다.
    2. 로직 구조를 나타내는 이름
      • isMemberHpMoreThanZeroAndIsMemberCanAct... 와 같은 로직 구조를 그대로 나타내는 이름은 무엇을 의도하는 지 알 기 힘들다. 의도와 목적을 이해하기 쉽게 이름을 붙이자. -> canEnchant
    3. 놀람 최소화 원칙
      • 놀람 최소화 원칙(Principle of least astonishment 또는 Rule of least surprice)는 사용자가 예상하지 못한 놀라움은 최소화하도록 설계해야 한다는 접근 방법이다. 로직에 이름과 관련 없는 로직들이 섞여 들어가 사용자가 놀라게 하는 일을 없게 하자. 로직과 이름 사이에 괴리가 있다면 이름을 수정하거나, 메서드와 클래스를 의도에 맞게 따로 만들도록 하자.

    5. 구조에 악영향을 미치는 이름

    1. 데이터 클래스처럼 보이는 이름
      • ~Info, ~Data(ProductInfo)와 같은 이름의 클래스는 읽는 사람에게 '데이터만 갖는 클래스니까, 로직을 구현하면 안 되는구나'라는 이미지를 심어줄 수 있다. 이러한 이미지는 응집도가 낮은 구조가 되기 쉽기 때문에, 이러한 데이터만 갖는다는 인상을 주는 이름은 피하는 것이 좋다.
      • 예외적으로 데이터 클래스를 사용하는 경우도 있다. 단순 데이터 전송 용도로 사용되는 디자인 패턴인 DTO(Data Transfer Object)는 값 변경이 필요 없으므로, 인스턴스 변수는 final로 선언하고 생성자에서는 값만 지정해야 한다. 참조 용도로만 사용되어야 하므로, 값을 변경하는 용도로 사용하지 않는다.
    2. 클래스를 거대하게 만드는 이름
      • ~Manager와 같은 이름은 클래스를 점점 더 거대하고 복잡하게 만든다. 예를 들어 MemberManager라는 클래스를 만들면, 멤버의 사양이 변경되거나 추가될 때 무의식적으로 '일단 MemberManager에 로직을 추가하면 된다'고 생각하기 쉽다. 단순하게 '관련이 있으니까 거기에 두었다'가 되는 것이다. Manger, Processor 등과 같이 의미가 넓게 해석되어 클래스를 거대하게 만들 수 있는 이름은 주의가 필요하다. 책무가 다른 로직은 다른 클래스로 정의하자.
    3. 상황에 따라 달라질 수 있는 이름
      • 'Account'는 금융 업계에서는 '계좌', 컴퓨터 보안에서는 '로그인 권한'을 뜻한다. 이처럼 상황에 따라 달라질 수 있는 이름을 사용한다면 상황(컨텍스트)에 따라 서로 다른 패키지로 선언하여 사용한다.
    4. 일련번호 명명
      • Class001, method001, method002, ... 등과 같은 일련번호를 붙이는 이름은 지양하자.

    6. 이름을 봤을 때, 위치가 부자연스러운 클래스

    다른 클래스로 이동시켜야 자연스러운 메서드가 있다. 이처럼 '있어야 할 곳'에 있지 않은 부자연스러움은 이름을 통해 판단할 수 있다.

    1. '동사 + 목적어' 형태의 메서드 이름 주의하기
      • 클래스 내에서 메서드에 '동사+목적어' 형태의 이름이 있다면, 다른 곳으로 이동시켜야 할 지 생각해봐야 한다. '목적어'가 필요하다는 것 자체가 해당 클래스 외에 다른 목적지가 필요하다는 것이고 이는 이름과 관계없는 책무를 가진 메서드일 가능성이 있다.
      • 예를 들어, 적을 의미하는 Enemy 클래스에 addItemToParty라는 메서드가 있을 때, 이 메서드는 Party라는 목적어가 있으므로 Party에 무언가 조작을 가하는 메서드라는 것을 짐작할 수 있고, 이 메서드는 Party 클래스로 이동되어야 한다는 것을 알 수 있다.
    2. 가능하면 메서드의 이름은 동사 하나로 구성되게 하기
      • 관심사가 다른 메서드가 섞이지 못하게 막으려면 되도록 메서드의 이름이 동사 하나로 구성되게 설계하는 것이 좋다.
      • '동사 + 목적어' 형태 -> 목적어의 개념을 나타내는 클래스를 따로 만들고, 해당 클래스에 '동사 하나' 형태의 메서드를 추가한다.
        • 'addItemToParty'라는 메서드는 파티의 인벤토리에 아이템을 추가하는 메서드이다. 이는 관심사가 섞인 형태이기 때문에, '파티의 인벤토리'라는 개념을 변도의 클래스로 만들고(PartyItems), 인벤토리에 아이템을 추가하는 add 메서드를 정의한다.
    3. 부적절한 위치에 있는 boolean 메서드
      • boolean 자료형을 리턴하는 메서드도 적절하지 않은 클래스에 정의되어 있는 경우가 많다. 메서드가 정의되어 있는 클래스 위치가 적절한지 쉽게 확인하려면, 간단하게 영어로 바꾸어보자.
        • Common 클래스에 isMemberInConfusion : Common is member in confusion.
        • Member 클래스로 이동된 isInConfusion : Member is in confusion. -> 의미적으로 이게 자연스러움을 알 수 있다.

    7. 이름 축약

    축약된 이름이 무엇인지 파악하기 위해서 주변의 로직을 읽고 유추하는 등의 시간이 들어가는 것은 낭비다. 기본적으로 이름은 축약하지 않는다. 다만, 이름 생략을 완전히 금지해야 한다는 것은 아니고, 일반적으로도 축약한 이름이 통용된다면 괜찮다. (for 문에서 i, j등 카운터 변수, SNS, VIP 등 관습적으로 사용되는 축약한 형태 등)

    반응형
Designed by Tistory.