본문 바로가기

Design Patterns

패턴 중독

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
패턴 중독에 관해 풍자 해 놓은 글이 있어서 읽어 보았다. (출처 : http://developers.slashdot.org)

Of course those GoF patterns can make life hell for the maintenance developer or app framework user, when people turn it into a contest to see how many design patterns they can fit into a single project. The overall "Design Patterns" philosophy is really "how can I defer as many decisions as possible from compile time to run time?" This makes the code very flexible, but the flexibility is wasted when a consultant writes code using lots of patterns to puff up his ego and then leaves without leaving adequate comments or documentation. Without insight into how the system works, the configurability and flexibility that these patterns offer is lost. The system hardens into an opaque black box.

당연히 이런 GoF 패턴들은 사람들이 패턴을 단일 프로젝트에 얼마나 많은 디자인 패턴들을 끼워 맞출 수 있는지를 경쟁하는 것으로 바꿀 때 개발이나, 프레임웍 유저 유지를 위한 지옥 같은 삶을 만들 수 있죠. 전체적인 디자인 패턴의 철학은 어떻게 내가 컴파일 시점에서부터 런 타임 시점까지 가능한 한 많은 결정들은 늦출 수 있는가하는 것입니다. 이 철학은 코드를 아주 유연하게 만들죠. 하지만 이런 유연함은 컨설턴트가 그의 경력을 부풀리기 위한 많은 패턴들을 사용하는 코드를 작성할 때와 적당한 코멘트나 문서 없이 작성할 때 무용지물이 되어버리죠. 어떻게 시스템이 작동하는지에 대한 관점이 없이는, 이런 패턴들이 제공하는 적합성과 유연성을 잃어버리게 됩니다. 따라서 그 시스템은 불분명한 블랙박스 안에서 조장을 하게 됩니다.

Deferring decisions to runtime makes code hard to read. Inheritance trees can get fairly deep, work is delegated off in clever but unintuitive ways to weird generic objects, and finding the code you're looking for is impossible, because when you're looking for the place where stuff actually happens, you eventually come across a polymorphic wonder like

런 타임에 결정을 지연하는 것은 코드의 가독성을 떨어뜨립니다. 상속 구조가 꽤 복잡할 수 있고, 작업은 멋지게 대신 되어 지지만, 이상한 일반화 객체로 직관적이지 않으며, 여러분이 어떤 일이 발생하는 결국 아래와 같이 다양한 형태로 나타날 수 있기 때문에 찾고자 하는 코드를 찾아내는 것이 불가능 할 수 있습니다.

object.work();

and the trail ends there. Simply reading the code doesn't tell you what it does; the subtype of object isn't determined until runtime. You basically need a debugger.

간단하게 말하자면 코드를 읽는 것만으로는 이것이 무엇을 하는지 알지 못하죠. 런 타임까지 객체의 서브타입이 결정되지 않습니다. 기본적으로 디버거가 필요합니다.


You can take a really simple program and screw it up with aggressive elegance like this. Here is Hello World in Java:


public class HelloWorld {

      public static void main(String[] args) {

            System.out.println("Hello, world!");

      }

}


But this isn't elegant enough. What if we want to print some other string? Or what if we want to do something else with the string, like draw "Hello World" on a canvas in Times Roman? We'd have to recompile. By fanatically applying patterns, we can defer to runtime all the decisions that we don't want to make at runtime, and impress later consultants with all the patterns we managed to cram into our code:

하지만 이 코드는 엘레강스 하지 않아요. 만약에 다른 스트링을 출력하고 싶으면 어쩌죠? 아니면, 이 스트링 객체를 Times Roman 폰트로 캔버스에 그리고 싶으면 어떻게 하죠? 재 컴파일 해야 되잖아요... 광적인 패턴 중독을 통해서, 모든 패턴들을 죄다 써서 컨설턴트들에게 인상을 주는 코드를 실행 시점에 만들어지길 원하는 모든 결정을 런 타임 시점으로 미룰 수 있습니다.

public interface MessageStrategy {

      public void sendMessage();

}

public abstract class AbstractStrategyFactory {

      public abstract MessageStrategy createStrategy(MessageBody mb);

}

public class MessageBody {

      Object payload;

      public Object getPayload() {

            return payload;

      }

      public void configure(Object obj) {

            payload = obj;

      }

      public void send(MessageStrategy ms) {

            ms.sendMessage();

      }

}

public class DefaultFactory extends AbstractStrategyFactory {

      private DefaultFactory() {

            ;

      }

      static DefaultFactory instance;

      public static AbstractStrategyFactory getInstance() {

            if (instance == null)

                   instance = new DefaultFactory();

            return instance;

      }

      public MessageStrategy createStrategy(final MessageBody mb) {

            return new MessageStrategy() {

                   MessageBody body = mb;

                   public void sendMessage() {

                          Object obj = body.getPayload();

                          System.out.println((String) obj);

                   }

            };

      }

}

public class HelloWorld {

      public static void main(String[] args) {

            MessageBody mb = new MessageBody();

            mb.configure("Hello World!");

            AbstractStrategyFactory asf = DefaultFactory.getInstance();

            MessageStrategy strategy = asf.createStrategy(mb);

            mb.send(strategy);

      }

}


Look at the clean separation of data and logic. By overapplying patterns, I can build my reputation as a fiendishly clever coder, and force clients to hire me back since nobody else knows what all this elegant crap does. Of course, if the specifications were to change, the HelloWorld class itself would require recompilation. But not if we are even more clever and use XML to get our data and to encode the actual implementation of what is to be done with it. XML may not always be a good idea for every project, but everyone agrees that it's definitely cool and and should be used wherever possible to create elegant configuration nightmares.

데이터와 로직의 명확하게 분리 해 놓은걸 좀 보세요! 과도한 패턴 적용에 의해서 난 스스로의 귀신같이 멋진 코더라고 평가하고, 의뢰인에게 나를 좀 고용해 달라고 압력을 줄 수 있습니다. -_-;; 이 뒤는 뭔가 엄청나게 코드 중복을 비아냥 거리고 있습니다 -_-;; 귀찮아서 패스;;