[Refactoring] 냄새 5. 전역 데이터
30 Sep 2022해당 포스트는 inflearn의 백기선님의 강의인 리팩토링 을 듣고 정리한 글입니다.
냄새 5. 전역 데이터
- 전역 데이터 (예, 자바의 public static 변수)
- 전역 데이터는 아무곳에서나 변경될 수 있다는 문제가 있다.
- 어떤 코드로 인해 값이 바뀐 것인지 파악하기 어렵다.
- 클래스 변수 (필드)도 비슷한 문제를 겪을 수 있다.
- “변수 캡슐화하기 (Encapsulate Variable)”를 적용해서 접근을 제어하거나 어디서 사용하는지 파악하기 쉽게 만들 수 있다.
- 파라켈수스의 격언, “약과 독의 차이를 결정하는 것은 사용량일 뿐이다.”
리팩토링 17. 변수 캡슐화하기
- 메소드는 점진적으로 새로운 메소드로 변경할 수 있으나, 데이터는 한번에 모두 변경해야 한다.
- 데이터 구조를 변경하는 작업을 그보다는 조금 더 수월한 메소드 구조 변경 작업으로 대체할 수 있다.
- 데이터가 사용되는 범위가 클수록 캡슐화를 하는 것이 더 중요해진다.
- 함수를 사용해서 값을 변경하면 보다 쉽게 검증 로직을 추가하거나 변경에 따르는 후속 작업을 추가하는 것이 편리하다.
- 불변 데이터의 경우에는 이런 리팩토링을 적용할 필요가 없다.
예제 코드
- Home
public class Home {
public static void main(String[] args) {
System.out.println(Thermostats.targetTemperature);
Thermostats.targetTemperature = -1111600;
Thermostats.fahrenheit = false;
}
}
- Thermostats
public class Thermostats {
public static Integer targetTemperature = 70;
public static Boolean heating = true;
public static Boolean cooling = false;
public static Boolean fahrenheit = true;
}
Home
은 집의 온도를 설정한다. 간단한 로직이며,Thermostats
은 온도에 대한 전역변수들이 모인 클래스이다.
Home
클래스에서 Thermostats
클래스의 targetTemperature
변수를 직접적으로 호출해서 값을 변경해주는데 이것은 정말 위험하다.
자칫 잘못하면, 예제코드에 나와있는 것처럼 -1111600같은 말이 안되는 값을 넣어도 해당 값이 적용되기 때문이다.
이러한 경우를 피하기 위해서는 메소드로 변수를 감싸서 validation을 적용하거나, final로 선언하여 불변하게 만들어야 한다.
메소드로 감싸는 대표적인 예시는 Getter/Setter
이 있다.
모두가 잘 아는 예시라고 생각된다.
public class Thermostats {
public static Integer targetTemperature = 70;
public static Boolean heating = true;
public static Boolean cooling = false;
public static Boolean readInFahrenheit = true;
public static Integer getTargetTemperature() {
return targetTemperature;
}
public static void setTargetTemperature(Integer targetTemperature) {
Thermostats.targetTemperature = targetTemperature;
}
public static Boolean getHeating() {
return heating;
}
public static void setHeating(Boolean heating) {
Thermostats.heating = heating;
}
public static Boolean getCooling() {
return cooling;
}
public static void setCooling(Boolean cooling) {
Thermostats.cooling = cooling;
}
public static Boolean getReadInFahrenheit() {
return readInFahrenheit;
}
public static void setReadInFahrenheit(Boolean readInFahrenheit) {
Thermostats.readInFahrenheit = readInFahrenheit;
}
}
이렇게 Getter/Setter
를 만들었다면, Home
에서는 아래와 같이 전역변수들을 호출 및 변경할 수 있을 것이다.
public class Home {
public static void main(String[] args) {
System.out.println(Thermostats.getTargetTemperature());
Thermostats.setTargetTemperature(68);
Thermostats.setReadInFahrenheit(false);
}
}
여기서 더 안전하게 간다면 각 메소드에 validation을 추가한다던지 또는 변수의 이름을 변경하는 대책을 추가할 수 있다.
public static void setTargetTemperature(Integer targetTemperature) {
if(targetTemperature <= 100&&targetTemperature > -101) Thermostats.targetTemperature = targetTemperature;
}