변수 캡슐화하기 Encapsulate Variable

0

리팩터링 카탈로그

목록 보기
6/10

배경


리펙토링은 결국 프로그램의 요소를 조작한느 일이다. 함수는 데이터보다 다루기가 수월하다. 함수를 사용한다는 건 대체로 호출한다는 뜻아고, 함수의 이름을 바꾸거나 다른 모듈로 옮기기는 어렵지 않다. 여차하면 기존 함수를 그대로 둔 채 전달 함수로 활용할 수도 있기 때문이다.(즉, 예전 코드들은 변함없이 기존 함수를 호출하고, 이 기존 함수가 새로 만든 함수를 호출하는 식이다.) 이런 전달 함수를 오래 남겨둘 일은 별로 없지만 리펙터링 작업을 간소화하는 데 큰 역할을 한다.

반대로 데이터는 함수보다 다루기가 까다로운데, 그 이유는 이런 식으로 처리할 수 없기 때문이다. 데이터는 참조하는 모든 부분을 한 번에 바꿔야 코드가 제대로 작동한다. 짧은 함수 안의 임시 변수처럼 유효범위가 아주 좁은 데이터는 어려울 게 없지만, 유효범위가 넓어질수록 다루기가 어려워진다. 전역 데이터가 골칫거리인 이유도 바로 여기에 있다.

그래서 접근할 수 있는 범위가 넓은 데이터를 옮길 때는 먼저 그 데이터로의 접근을 독점하는 함수를 만드는 식으로 캡슐화하는 것이 가장 좋은 방법일 때가 많다. 데이터 재구성이라는 어려운 작업을 함수 재구성이라는 더 단순한 작업으로 변환하는 것이다.

데이터 캡슐화는 다른 경우에도 도움을 준다. 데이터를 변경하고 사용하는 코드를 감시할 수 있는 확실한 통로가 되어주기 때문에 데이터 변경 전 검중이나 변경 후 추라 로직을 쉽게 끼워 넣을 수 있다. 데이터의 유효범위가 넓을수록 캡술화해야 한다. 레거시 코드를 다룰 때는 이런 변수를 참조하는 코드를 추가하거나 변경할 때마다 최대한 캡슐화한다. 그래야 자주 사용하는 데이터에 대한 결합도가 높아지는 일을 막을 수 있다. 객체 지향에서 객체의 데이터를 항상 private으로 유지해야 한다고 그토록 강조하는 이유가 바로 여기에 있다.

절차


  1. 변수로의 접근과 갱신을 전담하는 캡슐화 함수들을 만든다.
  2. 정적 검사를 수행한다.
  3. 변수를 직접 참조하던 부분을 모두 적절한 캡슐화 함수 호출로 바꾼다. 하나씩 바꿀 때마다 테스트한다.
  4. 변수의 접근 범위를 제한한다.
  • 변수로의 직접 접근을 막을 수 없을 때도 있다. 그럴 때는 변수 이름을 바꿔서 테스트해보면 해당 변수를 참조하는 곳을 쉽게 찾아낼 수 있다.
  1. 테스트한다.
  2. 변수 값이 레코드라면 레코드 캡슐화하기를 적용할지 고려해본다.

예시


before

class Owner {
   public String name;
   public int age;
}
Class Main {
	Owner owner = new Owner();
    owner.name = "Alex"
    owner.age = 24;
    
    System.out.println(owner.name);
    System.out.println(owner.age);
}

after

class Owner {
   private String name;
   private int age;
   Owner(){}
   Owner(String name, int age){
   		this.name = name;
        this.age = age;
   }
   public void setName(String name) {
   		this.name = name;
   }
   public void setAge(int age) {
   		this.age = age;
   }
   public String getName(){
   		return name;
   }
   public int getAge(){
   		return age;
   }
}
Class Main {
	Owner owner1 = new Owner();
    Owner owner2 = new Owner("Mike", 22);
    owner1.setName("Alex");
    owner1.setAge(24);
    
    System.out.println(owner1.getName());
    System.out.println(owner2.getAge());
}

출처


마틴 파울러 저 리팩터링 2판

0개의 댓글