1. null이 아닌 길이가 0인 배열을 리턴하라.
메소드나 클래스나 좋은 디자인의 제 1원칙은 자신 보다는 호출자를 배려한 코드이다. 결국 좋은 메소드 디자인이란 메소드 그 자체에 있다기 보단 그 메소드를 호출하는 쪽에서 판단하는 것이다.

# Bad
public Cheese[] getCheeses() {
   if (cheeseInStock.size() == 0) return null ;
   .......
}
위 코드가 좋지 못한건 호출하는 쪽에서는

# Bad 호출하는 쪽
Cheese[] cheeses = shop.getCheeses() ;
if (cheese != null) {
    for (int i=0 ; i < cheeses.length ; i++) {

    }
}

와 같은 별도의 확인 작업을 해야하는 문제가 있다.

# Good
public Cheese[] getCheeses() {
   return (Cheese[]) cheesesInStock.toArray(new Cheese[0]) ;
}

만약 메소드를 위와 같이 작성했다면

# Good 호출하는 쪽
Cheese[] cheeses = shop.getCheeses() ;
for (int i=0 ; i < cheeses.length ; i++) {

}

null은 가능하면 리턴값으로 사용하지 않는게 좋다
.. 라는건 사실 아주 조그마한 것이지만 좋은 디자인이란 Outer에서 판단된다는 걸 잊어서는 안된다.





2. 디미터 함수 법칙

Case 1)
public void plotDate(Date aDate, Selection aSelection) {
    TimeZone tz = aSelection.getRecorder().getLocation().getTimeZone() ;
    ......

}

언뜻 별다를게 없어 보이는 위 코드는 디미터 함수의 관례를 위반하였다.

디미터 함수 법칙은 최소 지식의 원칙(Principle of Least Knowledge) 이라고도 불린다.(프로그램에서 모듈간 결합도를 최소화하려 시도한다.) OO 프로그래밍 연구 프로젝트(Demeter Project)에서 나온 법칙으로 흔히 '친한 친구들 하고만 이야기 하여라(Only talk to your immediate friends)' 라는 이야기로 요약된다. 친구는 클래스 정도로 해석하면 되며, getA().getB().getC() 하는 식으로 '여러 객체에 물어물어 가는 식으로 정보를 찾아내는 스타일은 자제하는 것이 좋다'라는 법칙이다. 

재미있는 것은 다른 법칙과 달리 디미터의 법칙은 장/단점이 생기는 법칙으로, 디미터의 법칙을 잘 따를 경우 메소드(=함수)가 많이 생기게 되면서 복잡도가 증가 할 수 있다. 하지만, 전체적으로는 잘 따르는 것이 좋은 법칙이다. 현재 디미터의 법칙이라 불리는 법칙은 디미터 프로젝트의 OO 프로그래밍 스타일 가이드 중 함수와 메소드(Law of Demeter for Functions/Methods) 부분의 가이드를 말한다.


사실 소프트웨어에서 법칙이라고 말하는게 조금 웃기긴 하지만
디미터 함수 법칙에 따르면 모든 메서드는 다음에 해당하는 메소드만을 호출해야 한다.

class Demeter {
   private A a = new A();

   private void func() {...}

   public void example(B b){
      C c = new C();
      Int f = func() ;     // 자신의 메소드
      b.invert() ;         // 메소드에 넘어온 인자
      a.setActive() ;   // 자신이 생성한 객체
      c.print() ;          // 직접 포함하고 잇는 객체
   }
}

디미터 함수 법칙을 가능한 지키려고 하면서 한 서브 프로젝틀를 리팩토링한 경험이 있는데 생각보다 훨씬 효과가 좋았다. 최근의 툴은 .을 누르면 해당 객체의 메소드가 대부분 자동으로 완성되기 때문에 무심코 사용하곤 하는데 aSelection.getRecorder().getLocation().getTimeZone() ; 식의 방법은 불필요한 관계를 맺음으로써 유지보수 하기 어려게 만들곤 한다. 




3. 인자의 유효성을 검사

public void AnonyMethod(AnonyClass ac) {
   Assert.notNull(ac) ;


    ac.fn() ;
    .............
}

이러한 방식을 방어적인 프로그램이라고 할 수 있다.

다만 일반적으로 봤을때 인자의 유효성을 호출자가 체크해야 하는가 아니면 위처럼 메소드 자체가 체크해야 하는가에 대해서는 개인적으로 아직 결론을 내리지 못했다.(섞어 쓰고 있다-ㅅ-) 위와 같은 방어적 프로그램은 메소드를 본래 의도와 상관없이 복잡하게 만들 가능성이 있기 때문이다.

에펠같은 계약에 의한 프로그래밍(PBC) 언어에서는 선조건과 후조건을 설정 가능하도록 되어 있는데 자바도 그 특징을 조금씩 도입하고 있다. 앞에서 말한바와 같이 좋다라는 판단은 호출자가 내리지만 잘못 사용하는건 내탓이오 라는 걸까.. 왠지 사회운동을 보는 것 같아 우습다 -ㅅ-











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

Class Design  (0) 2009.03.07
나쁜 디자인의 징후  (0) 2009.02.22
Design Principle - SRP  (0) 2009.02.22
몇가지 프로그래밍 조언  (0) 2009.02.10
Bleujin Framework 활용 : HTML Parsing  (0) 2009.01.16
Posted by bleujin