함수의 적정 최대 라인수가 얼마냐 하는 것은 아직까지 논의가 되고 있는 문제인데 보통의 경우 모니터의 화면을 넘기지 않을 정도라는 대체적인 합의는 있다. (대략 20라인 이내) 

Max는 그렇다 치고 Minimum은 어떨까? 
한줄짜리 함수는 가치가 있을까? 이전의 강의에서 나는 종종 그건 지나친것 같다라는 질문을 받곤 했다. 



한줄짜리 함수의 첫번째 유용성은 리팩토링 책에서 소개하듯이 가독성때문이다. 

1. if (date.before(SUMMER_START) || date.after(SUMMER_END))를

2. if (notSummer(date)) 와 같이 바꾼다면 (Decompose Conditional)

Reading하기가 좀더 쉽다. 아마도 notSummer는 private 함수일것이고 함수명으로 좀더 의미를 명확하게 전달하기 때문에 굳이 함수를 들여다봐야 해서 복잡해지진 않는다.(이런 가독성에 대해서는 이전글에서 언급했듯이 동전의 양면이다. 만약 함수명이 적절하게 지어지지 않는다면 좀더 복잡해질 것이다. Framework에서 구조의 문제도 마찬가지이다. )

그럼에도 한줄짜리 함수를 싫어하는 사람들은 꽤 있었지만 현재는 그 수가 많이 줄었다. 이는 툴의 발전에도 많이 영향을 받았다. 이전에 text editor에서 코드를 작성하던 쥬라기 시대에는 툴에 함수 바로가기 등의 assist 기능이 없어서 text search로 함수 내용을 확인해야 하던때라 가능한 하나의 함수에서 해주는게 미덕인 시절이 있었다. 

한줄 함수를 싫어하는 다른 이유로는 C 시절에는 Function Call Stack이 쌓이게 됨으로써 발생하게 되는 비효율을 이유로 들었으나 자바에서는 C와 달리 이러한 비효율이 성능상에서 차지하는 부분이 아주 작다. 이미 자바 라이브러리 자체가 수십개의 Function Stack Call을 하고 있으므로 거기에 몇개쯤 더한다고 거의 영향이 없다. (그러나 C나 C++은 영향이 있다. 그 영향 자체는 상대적이기에 많다 적다고 할수 없지만 확실히 자바보다는 영향이 많다.)




잘 알려지지 않는 한줄 함수의 두번째 유용성은 일종의 중개자로서의 역할인데
예컨데 System.out.println()을 예로 들어보자. 

최근에는 Unit시리즈의 유닛테스트를 많이 사용하고 있긴 하지만 그럼에도 유닛테스트하기 어려운 Swing이나 Persitence가 있고 또 가끔은 System.out.print으로 Debugging을 할때가 있다. 문제는 코드 중간중간에 써 놓은 System.out.println은 확인이 끝나고 처치가 곤란할때가 종종 있다. 

그렇다고 Logger를 쓰자니 잠깐 확인을 위해서 jar도 path에 걸어야 하고 설정도 해야하니 웬지 배꼽이 더 커 보인다. 

그럴때 Debug.debug() 클래스를 선언해서 쓰면 유용하다. 

예컨데 
public class Debug extends OutputStream{

private static void out(String message) {
System.out.println("   : " + message) ;
}

public static void error(Class cls, Object...objs) {
debug(cls, objs) ;
}

public static void debug(Object... objs) {
out(Arrays.deepToString(objs)) ;
}
public static void debug(Class cls, Object... objs) {
debug(Arrays.deepToString(objs) + " at " + cls.getName()) ;
}

public void write(int b) throws IOException {
System.out.print(b) ;
}
public static void happy(Object... objs) {
// TODO Auto-generated method stub
}
public static void happy(Class cls, Object... objs) {
// TODO Auto-generated method stub
}

}}
와 같이 별거 없는 클래스이다.(함수도 하나였는데 자꾸 쓰다보니 늘어났다.)

System.out.println() 대신 Debug.debug() 한줄함수로 바꾸면 생기는 이득은 멀까?

첫번째로 Reading이 쉬워지는 것외에 툴의 Call Hierarchy 기능을 통해 사용되고 있는 곳을 알수 있다. (System.out.println의 Call Hierachy를 찾으면 지나치게 많은 것을 찾는다.) 또는 잠깐의 조작을 통해 특정 메시지만 다른 outted message와 다르게 보이게 만들수도 있다. (System.out.println 함수를 바꿀수는 없지만 debug함수는 수정이 가능하다.)

둘째로 언제든 Logger 클래스를 사용하는 걸로 변신할수 있다. 이를테면 error() Method만 Logger 클래스를 사용하도록 이후에 수정에 가능하다. 시점이 나중이라는 것이 중요하다. 처음에는 그냥 쉽게 화면에 print 하는 방식으로 사용하다가 필요가 생기면 해당 함수를 수정하면 그만이다. 

한줄짜리 함수에 이런 장점이 생기는 근본 이유를 들여다 보면 좀더 흥미롭다. 왜 Debug.debug() 함수가 유용성을 가지는가? 그것은 우리가 System.out.print를 수정할 수 없기 때문이다. 만약 우리가 System.out.print를 컨트롤 할 수 있었다면 debug함수를 작성해서 수정할 필요없이 out class의 println 함수를 직접 수정하면 그만이다. 

앞서(4달전에:) 변화의 속도에 대해서 말한적이 있는데 현재 작성하고 있는 코드와 자바의 java.lang 패키지는 변화의 속도가 다르다. 그리고 그 변화의 속도가 다를때 부동산 중개인의 존재이유와 마찬가지로 우리는 중개자 클래스 혹은 함수가 필요하다. 다시 말해서 단 한줄짜리 함수라고 하더라도 해당 함수의 변화의 속도가 다르다면 그 함수는 유용성을 가질때가 많다. 

사실 대부분의 프레임워크와 마찬가지로 마치 빅뱅이론처럼 Logger Framework는 이러한 한줄짜리 함수에서 출발했다. 누군가 System.out.println으로 화면에 메시지를 보여주는게 관리상 효율이 좋지 못하다는 걸 깨달았고 한줄짜리 함수를 만들었는데 거기에 기능을 덧붙이고 유연성을 더하고 예외도 고려하고 등등을 하다보니 이게 Logger Framework가 되었다. 

그러나 그렇다고 해서 우리는 처음부터 System.out.println과, 보다 설정하기도 귀찮고 사용하기 어려운 Logger Framework 두가지중에서 꼭 하나를 결정해야 할 필요는 없다. 그런 선택은 미루다가 나중에 고를수 있거나 혹은 제 3의 길의 선택할 수 있는 방향을 열어두는게 좋다.

즉 한줄짜리 함수는 변화의 속도가 다른 Layer사이에서 그 속도의 조정과 완충을 담당하는 중재자 역할을 할때 새로운 효용성을 발견할 수 있다. 자신이 컨트롤 할수 없는 함수(System.out, Logger 등등)을 5번 이상 호출해야 한다면 이런 한줄짜리 중개자 함수를 고려해 보자. 



'Framework > 아키텍쳐 일반' 카테고리의 다른 글

여섯번째 계  (0) 2009.07.14
호출의 빈도  (0) 2009.07.08
예언?  (0) 2009.06.12
패키지의 설계 원칙  (0) 2009.06.08
양화 구축  (2) 2009.06.08
Posted by bleujin