개발놀이터

리팩토링 (1) : 의미있는 이름 본문

리팩토링

리팩토링 (1) : 의미있는 이름

마늘냄새폴폴 2023. 7. 22. 12:51

우리는 이름을 정말 많이 짓습니다. 클래스, 변수, 인터페이스, 추상 클래스, JAR파일, WAR파일 모두 이름을 붙이게 됩니다. 

 

그러므로 이름을 잘 붙이는 것은 의미있습니다. 그리고 잘 못지은 이름은 가독성을 떨어뜨리기 마련이죠. 

 

이번 포스팅에선 의미있게 이름을 붙이는 방법에 대해서 설명해보도록 하겠습니다. 

 

의미있는 이름

의도를 분명히 밝혀라

우리는 가끔 변수명을 이렇게 짓곤 합니다. 

int d;

하지만 개발할 때 당시만 기억나고 한참 뒤에 이 변수를 보면 무슨 변수인지 헷갈릴 때가 많습니다. 

 

그러므로 우리는 아래와 같이 바꿔야합니다. 

int daysSinceModification;

 

이에 조금 연장선상의 코드들을 한번 보시죠. 

    public List<int[]> getThem() {
        List<int[]> list1 = new ArrayList<>();
        for (int[] x : theList) {
            if (x[0] == 4) {
                list1.add(x);
            }
        }
        return list1;
    }

이 코드의 문제점은 다음과 같습니다. 

 

  1. getThem이 뭘 가리키는지 모른다. 
  2. theList에 무엇이 들어있는지 모른다.
  3. 값 4는 무슨 의미인지 모른다. 
  4. 함수가 반환하는 list1을 어떻게 사용해야 하는지 모른다. 

 

때문에 우리는 변수를 설정하고 그 변수에 의도를 설명해줄 필요가 있습니다. 

 

위의 상황은 바로 지뢰찾기 게임의 한 부분이었습니다. 그럼 이제 명확히 theList가 게임보드라는 것을 알 수 있겠죠. 배열의 0번째에는 칸의 상태가 들어있고, 4라는 숫자의 뜻은 깃발이 꽂힌 상태를 말합니다. 

 

그럼 아래와같이 코드를 리팩토링할 수 있습니다. 

    private static int STATUS_VALUE = 0;
    private static int FLAGGED = 4;
    
    public List<int[]> getFlaggedCells() {
        List<int[]> flaggedCells = new ArrayList<>();
        for (int[] x : gameBoard) {
            if (x[STATUS_VALUE] == FLAGGED) {
                flaggedCells.add(x);
            }
        }
        return flaggedCells;
    }

 

이렇게 고치면 다른 개발자가 봤을 때 어떤 의도를 가지고 코딩했는지 알 수 있겠죠? 

 

의미있게 구분하라

보통 우리가 아무생각 없이 붙이는 변수명에 큰 의미가 없는 경우가 많습니다. 

 

moneyAccount 와 int money 는 구분이 안된다. 
customerInfo 와 customer 역시 구분 안된다. 
accountData 와 account, theMessage 와 message 구분 X

 

의미없는 미사여구는 변수명만 길어지게 할 뿐 의미가 분명해지진 않습니다. 안티패턴이라 절대 하지말라는 말은 아니지만 명확한 변수명은 아니라는 것이죠. 

 

줄임말을 쓰지 말아라

private Date genymdhms;
private Date modydhms;

여러분 이게 무슨 변수인지 알겠나요? 아마 설명을 듣기 전에는 절대 모를것임에 확신합니다. 

 

private Date generationTimestamp;
private Date modificastionTimestamp;

아마 이렇게 바꾸는게 조금 더 명확할 것입니다. 

 

검색하기 쉬운 이름을 사용하라

        for (int j = 0 ; j < 34 ; j++) {
            s += (t[j] * 4) / 5;
        }

이 역시 앞에서 설명드렸던 의도를 분명히 하라에 어긋납니다. 위에서 말한 내용과 일맥상통하는 말이긴 합니다만 의도가 조금 다른데요. 

 

만약 이 메서드의 for문을 검색할 때 j를 찾는다거나 s를 찾으면 얼마나 많은 j와 s가 등장할까요? 우리는 이런 것을 피하기위해 의도를 나타내면서 검색하기 쉬운 이름을 사용해야합니다. 

 

    private static final int WORK_DAYS_PER_WEEK = 5;
    private static final int NUMBER_OF_TASKS = 34;
    
    public static void main(String[] args) {
        int realDaysPerIdealDay = 4;
        
        for (int j = 0; j < NUMBER_OF_TASKS; j++) {
            int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
            int realTaskWeeks = (realTaskDays / WORK_DAYS_PER_WEEK);
            sum += realTaskWeeks;
        }
    }
    //생략된 변수가 있을 수 있습니다.

 

그릇된 정보를 피하라

만약 한 모듈에서 XYZControllerForEfficientHandlingOfStrings 라는 꽤 긴 이름을 사용하고 있다고 가정해봅시다. 그리고 조금 떨어진 모듈에서 XYZControllerForEfficientStorageOfStrings 라는 이름을 사용하고 있다고 하면 이 둘이 구분이 되시나요? 

 

이 둘은 너무 비슷해서 의미가 흐려집니다. 이런 이름들은 피해야겠습니다. 

 

의미있는 맥락을 추가하라

만약 어떤 모듈에서 아래와 같은 변수를 사용하고 있다고 가정해봅시다. 

 

String firstName;
String lastName;
String street;
String houseNumber;
String city;
String state;
String zipcode;

일련의 변수들을 보고있으니 바로 주소라는 것을 알 수 있겠습니다. 

 

하지만 만약 어떤 메서드에서 state 하나만 사용하고 있다면 어떨까요? 이 state 가 주소의 일부분이라는 것을 알 수 있을까요? 

 

때문에 우리는 이런 상황에서 의미있는 맥락을 추가해주는 것이 좋습니다. 

 

String addrFirstName;
String addrLastName;
String addrStreet;
String addrHouseNumber;
String addrCity;
String addrState;
String addrZipcode;

 

마치며

여기까지 의미있는 이름 부분이 끝났습니다. 아무래도 이름을 짓는 부분은 크게 어려운 것 없이 잘 지나간 것 같습니다. 조금 더 신경써야 할 부분들이 몇개 보이긴 하네요. 

 

모든 파트를 포스팅하고 제 프로젝트에 이 부분들을 녹여가면서 깨끗해질 제 코드들을 기대해보며 마무리짓도록 하겠습니다. 

 

긴 글 읽어주셔서 감사합니다. 오늘도 즐거운 하루 되세요~