Clean Code

[Clean Code] Chapter 8 경계

로드태환 2022. 2. 15. 09:02

외부 API를 호출하거나 인터페이스를 사용할 때 제공자와 사용자 간의 입장 차이 때문에 문제가 많이 생긴다.

인터페이스 제공자는 최대한 범용성을 제공하려하고 사용자는 자신의 상황에 딱 맞는 인터페이스를 원한다.

Java의 Map을 예로 들어보자

Map은 다양한 기능을 제공하고 유연한 인터페이스지만 이러한 이점이 위험하기도 하다.

Map을 parameter로 여기저기 넘긴다고 가정해 보자. Map 인터페이스는 인자를 넘기는 쪽에서 의도하지 않은 clear()함수를 제공해 언제든 내가 넘긴 객체가 삭제 될 수 있다.

또한 자바5 이전에 제네릭이  없을 당시에는 특정 객체만 담고 반환하도록 제한 하지 못해 일일이 원하는 객체로 형 변환 해줘야 했다.

제네릭을 사용한다고 해서 필요 없는 메서드를 제공하는 단점까지 커버하지는 못하므로 다음과 같이 해보자.

public class Sensor {
	private Map sensor = new HashMap();

	public Sensor getById(String id) {
		return (Sensor) sensor.get(id);
	}
	//...
}

 

경계 인터페이스인 Map을 Sensor클래스 안에 숨겨 Sensor 객체를 사용하는 사용자는 Map이 바뀌어도 코드를 수정하지 않아도 된다.

Map은 Http 통신때도 문제다 
@RequestMapping("/service/review/list")
	public ResponseObject<Object> getReviewList(@RequestParam Map<String, Object> paramMap){
		ResponseObject<Object> ret = new ResponseObject<>();

		if(!paramMap.containsKey("posSeq") || paramMap.get("posSeq") == null) {
			ret.setReturnCode(StatusCode.ERROR_PARAMETER);
			return ret;
		}

		// ...
	}

가장 먼저 이 코드를 짠 사람이 아니면 무엇을 받고 무엇을 넘기는지 명확하지  않다.

다음으로 posSeq 라는 키값을 내가 알고 있어야 코딩이 가능하다. (이 부분이 결합도가 높은건가..?)

쓸데 없는 null 검사를 해야한다. (필수로 있어야 할 값이 늘어나면 *N 번 조건을 걸어야 한다)

Map 같은 경계 인터페이스는 공개 API의 인수로 넘기거나 반환받지 말자

 

경계 살피고 익히기

외부 코드를 사용하면 적은시간에 더 많은 기능을 만들 수 있다는 것은 분명한 장점이다.

하지만 해당 라이브러리를 처음 사용하는 상황이라면 버그가 있을 때 우리쪽 버그인지 라이브러리 버그인지 알 수 없어 디버깅이 쉽지 않다.

이럴 때 사용하는 것이 학습 테스트이다.

우리 프로젝트에서 바로 라이브러리를 사용하는 것이 아니라 간단한 테스트 케이스를 통해 외부 코드를 익히는 방법이다

학습테스트는 들이는 노력대비 얻는게 크다. API의 필요한 부분만 학습할 수 있고 이해도를 높여준다.

또한 패키지가 업데이트 되었을 때 내 코드와 호환되는지도 바로 확인할 수 있다. 그렇게 되면 새 버전으로 이전이 쉬워진다.

 

아직 존재하지 않는 코드 사용하기

경계의 또 다른 유형은 아는 코드와 모르는 코드를 분리하는 경계이다.

아직 개발이 되지 않은 인터페이스나 API등을 이용하여 개발해야 할때 시간이 넉넉하다면 필요한 것이 개발되고 우리가 개발에 착수하면 되지만 현실은 그렇지  않다.

 

그럴 때는 우리가 아는 것과 모르는 것의 경계를 잘 정한 후 우리에게 필요한 인터페이스를 자체적으로 정의한고 모의(Fake) 구현체를 개발한다.

그러면 미 개발 API에서 컨트롤러를 분리해 먼저 개발할 수 있게 되고 후에 API 가 개발 되었을 때 Adaptor를 개발해 인터페이스에 장착하기만 하면 된다. Fake 구현체를 적절히 구현했다면 Controller 테스트도 용이하다.

결론

경계에서는 변경이 자주 일어 나므로 통제하지 못하는 코드는 변경 비용이 너무 커지지 않도록 신경써야 한다.

경계에 위치하는 코드는 깔끔하게 분리하고 통제 가능한 우리 코드에 의존하는 편이 좋다.

외부 패키지를 호출하는 코드는 한번 감싸 의존성을 줄여 외부 패키지 변화에 준비하자.