[Refactoring] 리팩터링 2판 Chapter.06 part 3 (기본적인 리팩터링)

Date:     Updated:

카테고리:

태그:

변수 캡슐화 하기

변수와 같은 데이터를 다룰 때 유효범위가 짧은 변수들은 대체로 문제를 일으키지 않지만, 전역변수 또는 public 필드와 같이 유효범위가 넓은 데이터들은 문제를 많이 일으키게 됩니다.

해당 문제를 해결하기 위해 캡슐화를 진행 합니다.

캡슐화를 하여 특정 클래스의 데이터를 변경할 때에는 개발자가 지정한 getter/setter 함수를 통해서만 수정할 수 있게 합니다. 이렇게 하면 데이터를 변경하고 사용하는 코드를 감시할 수 있는 확실한 통로가 되어주기 때문에 데이터 변경 전 검증이나 변경 후 추가 로직을 쉽게 끼워넣을 수 있습니다.

제 첫 포폴을 만들 때 하고싶은건 많고 시간은 촉박하여 에라 모르겠다~ 하고 전부 public필드로 다 떼려박았던 기억이 있습니다. 만들때는 쉬웠는데, 만들고 나서 버그가 발생하였을 때 데이터의 유효범위가 너무 넓어 디버깅이 어려운 문제점이 있었습니다. 결국 그 프로젝트는 끝내지 못했던걸로 기억합니다.

아마 여러 고수분들이 말하는 모든 필드들은 private으로 선언해야 한다 라는것이 이러한 문제 때문이 아닐까 싶습니다. private필드로 만들고 캡슐화하여 관리하도록 해야 합니다.

여기서, 생각해봐야 할 것이 유효범위가 넓은것만이 문제일까? 입니다. 물론 유효범위가 넓으면 디버깅할 때 생각해야하는 지점이 많아져 힘든것은 사실입니다. 하지만 여기에 한가지가 더 붙으면 정말 디버깅하기 어려운 코드가 탄생 합니다. 바로 가변 필드 입니다. 유효범위도 넓고, 데이터를 바꿀 수 있다면, 어우.. 생각만 해도 끔찍하군요.

그래서, 캡슐화를 하지 않으려면 해당 데이터를 불변으로 만들어서 사용해야 합니다. 즉, 불변성은 강력한 방부제인 셈입니다.

해당 기법은 객체지향을 공부했다면 굉장히 기본적인 방법이기에, 예제는 생략합니다.

절차

  1. 변수로의 접근과 갱신을 전담하는 캡슐화 함수를 만든다.
  2. 정적 검사를 수행한다.
  3. 변수를 직접 참조하던 부분을 모두 적절한 캡슐화 함수 호출로 바꾼다. 하나씩 바꿀 때마다 테스트 한다.
  4. 변수의 접근 범위를 제한한다.
  5. 테스트한다.
  6. 변수 값이 레코드라면 레코드 캡슐화하기를 적용할지 고려해본다.

변수 이름 바꾸기

함수를 만들다 보면, 매개변수를 많이 만들어야 할 때가 있습니다. 예를들어, 데이터베이스에 접근하여 유저 데이터를 삽입하는 함수가 있다고 생각해봅시다. 유저의 데이터는 Name, Age, PhoneNumber, Address 등등이 있다고 가정합니다. 이 정보들을 받으려면 벌써 매개변수가 4개가 됩니다.

function insertUser(name, age, phoneNumber, address) {
    //insert 로직
}

제가 예전에 재고관리 프로그램을 짤 때 위와같이 코드를 짰습니다. 이렇게하니까 빠지는데이터도 생기고, 해당 매개변수 사이에 다른 매개변수가 끼면 이 데이터들이 무슨역할을 하는거였지? 라고 헷갈릴때도 많았습니다.

이런경우, 데이터들을 담고있는 클래스들을 만들어서 매개변수로 받게 만듭니다.

function insertUser(user) {
    //insert 로직
}

class User {
    constructor(name, age, phoneNumber, address) {
        this.name = name;
        this.age = age;
        this.phoneNumber = phoneNumber;
        this.address = address;
    }
}

이렇게 하면, 데이터 사이의 관계가 명확해진다는 이점을 얻습니다. 게다가 매개변수 수가 줄어들어 코드를 읽기 더 쉬워집니다.

절차

  1. 적당한 데이터 구조가 아직 마련되어 있지 않다면 새로 만든다.
  2. 테스트한다.
  3. 함수 선언 바꾸기로 새 데이터 구조를 매개변수로 추가한다.
  4. 테스트한다.
  5. 함수 호출 시 새로운 데이터 구조 인스턴스를 넘기도록 수정한다. 하나씩 수정할 때마다 테스트한다.
  6. 기존 매개변수를 사용하던 코드를 새 데이터 구조의 원소를 사용하도록 바꾼다.
  7. 다 바꿨다면 기존 매개변수를 제거하고 테스트한다.

여러 함수를 클래스로 묶기

안드로이드 앱 프로그래밍을 할 때, 했던 실수입니다. 마찬가지로 재고관리앱을 만들 때 벌어졌던 실수입니다. 재고관리앱에서 시간을 관리하는 함수, 데이터베이스에 접근하는 함수 등을 필요할 때마다 복사해서 클래스에 붙여 사용했던 기억이 있습니다. 이렇게하니, 하나의 엑티비티에 너무 많은 코드가 들어가게 되고, 시간관리 로직이 바뀔 때 마다 해당 함수들을 다 찾아서 바꿔줘야 하는 단점이 있었습니다.

같은 기능을 하는 함수들을 클래스로 모아서 사용한다 라는것이 지금은 너무나도 당연한데, 이때는 왜 그렇게 생각을 못했는지 모르겠습니다.

이 깨달음을 얻고 난 후, 어떤 프레임워크를 사용하던간에, 프레임워크에서 사용할 수 있는 공용함수, 해당 언어에서 사용하는 공용함수들을 모아서 관리하는 습관이 생기게 되었습니다.

여러 함수를 한번에 관리할 수 있다는 장점, 호출부에서는 별다른 로직없이 함수만을 호출하면 된다는 장점, 다른 프로젝트할때에 같은 로직을 다시 만들 필요가 없다는 장점, 하나의 클래스에서만 의존성을 주입하면 된다는 장점 등을 챙길 수 있었습니다.

해당 기법도 예제는 생략합니다.

절차

  1. 함수들이 공유하는 공통 데이터 레코드를 캡슐화 한다
  2. 공통 레코드를 사용하는 함수 각각을 새 클래스로 옮긴다.
  3. 데이터를 조작하는 로직들은 함수로 추출해서 새 클래스로 옮긴다.

Refactoring 카테고리 내 다른 글 보러가기

댓글 남기기