프로그래밍 안티 패턴 프로그래밍

Programming AntiPatterns라는 블로그 글이 올라와서 정리해 본다. 항상 말하지만, 정리는 참조만 하고 원문을 볼 것.

안티 패턴이란? - 문제에 대해 자주 사용되는 해결책이지만 안 좋은 결과를 가져오는 것.
안티패턴을 사용하는 이유는 관리자나 프로그래머가 더 나은 지식이 없고, 특정 타입의 문제에 대해 지식과 경험이 부족하거나 혹은 완벽한 패턴을 잘못된 상황에 적용할 때 발생하게 된다.

◆ 바퀴의 재발명

이미 있는 라이브러리나 프레임워크를 다시 만들지 말라.
유용한 프레임워크나 라이브러리의 존재를 잘 몰라서 발생하는 안티패턴. Apache Commons Lang 혹은 Commons Collections는 모든 자바프로젝트에서 포함되어야 한다. 리플렉션이 필요하면 Apache Commons Beanutils나 스프링의 BeanUtilsBeanWrapper를 사용하라.
권남 주 : 요즘에는 Google Guava가 Apache Commons를 대체하는 중.


화물 숭배(Cargo Cult) 프로그래밍

화물 숭배
왜 그런지 이유도 모르면서 특정 방식이나 패턴을 사용하지 말라.
보통 스킬과 경험이 부족한 프로그래머들이 복사해서 붙여넣기하면서 발생한다.

안티패턴 예:

  • 스스로 설명하는 코드(self-explanatory code)에 불필요한 주석달기
  • 문제 없이 가비지 컬렉션되는 객체에 삭제 코드 추가하기
  • 간단한 객체를 생성하려고 팩토리 만들기

예외에 기반한 코딩/예외 처리(Exception Handling)

어떤 사람들은 값의 특별한 형태(null 같은)를 검사하지 않고 catch블록에서 NullPointerException을 검사하여 로직을 수행하게 짠다(예외 처리).
예외는 정말로 나쁜 상황이 발생했다는 것을 알려주려고 존재하는 것이며, 자주 발생하면 안된다. 그래서 "예외(exception)"이라고 부르는 것이다. 예외는 주의깊게 다뤄야하고, 과용하면 안된다.
간단한 if-else 검사로 수행할 수 있는 로직을 예외를 사용해 처리하지 말라.

예외 삼키기

예외가 발생했다는 것은 무언가 기대치 않은 사건이 발생했다는 것이다. 예외의 정보를 가지고 처리를 하는 대신 예외를 삼켜버리는 것이 안티패턴이다.
예외는 먹는게 아니다. 삼키지마.

권남 주: finally 블록에서 return 구문을 써도 예외가 먹힌다. finally에서는 절대로 return하면 안된다.

상속의 지옥

상속은 매우 주의해서 다뤄야 한다. 상속이 비대해졌다면 뭔가 잘못된 것이다. 단 하나의 특별한 경우 때문에 추상 클래스를 만들지 말라.
상속 대신 구성(composition)을 사용하라. 전략 패턴(strategy pattern)이 도움이 될 것이다.

권남 주: 자바의 아버지 제임스 고슬링이 어느 컨퍼런스에서 "자바를 다시 만든다면 뭘 바꾸겠습니까?" 물었을 때 클래스의 상속을 없애겠다고 했다한다(정확히는 클래스를 없애겠다고 말했다가, 다시 고쳐서 구현의 상속-클래스 상속-을 없애고 싶다 했다고 한다). 가능하면 구현 상속보다는 인터페이스 상속을 사용하라.

금 도금과 너무 이른 최적화(Gold Plating & Premature Optimization)

사용자가 요청하지도 않은 요구사항을 구현하는 행위를 금 도금(gold plating)이라고 한다. 헛된 짓이로다.

금 도금의 일종으로 너무 이른 최적화도 있다. 너무 이른 최적화는 당장은 아무 문제도 없지만 미래에 발생할지도 모르는 이슈를 미리 고민하는 것이다. 미래의 언젠가 필요한 것 말고 요청 받은 것 필요한 것만 생각하라. 자주 일어나는 너무 이른 최적화로는 너무 이른 성능 최적화가 있다. 지금 현재 성능 이슈가 없다면 최적화는 문제가 발생할 때까지 미루라.

권남의 주관적 해석 : 너무 이른 최적화를 잘못 해석할 수도 있어보인다. 너무 이른 성능 최적화를 하지말라는 것은 성능 측정을 하지말라는 것과는 다르다. 현재의 요구 사항을 만족하는지 성능 측정을 하고 그것을 만족시키는 최적화를 해야한다. 그러나 현재의 요구 사항을 넘어서는 측정을 진행하고 최적화를 하는 것은 "너무 이른 성능 최적화"에 해당한다.


http://en.wikipedia.org/wiki/Anti-pattern#Programming_anti-patterns 에서 더 볼 수 있다.

덧글

  • 몽몽이 2011/10/16 12:17 #

    안티 패턴이란 용어를 잘 모르는 사람에게 이 말을 썼다가 디자인 패턴 사용에 반항하는 꼴통으로 취급받은 적이 있습죠.
    외눈박이 동네에선 두눈 뜬 사람이 병신.
  • 몽몽이 2011/10/16 12:24 #

    [쓰디쓴 자바]. 옛날 책이지만 추천합니다.
  • 권남 2011/10/16 17:22 #

    예전에 "쓰디슨 자바"를 읽어 보았습니다. 오래전 책인지라 현실과 맞지 않는 내용들도 좀 있지만 한 번쯤은 읽어봐야할 책이라고 생각합니다.
  • 영록 2011/10/16 13:10 # 삭제

    전반적으로 좋은 내용이지만 조금 디테일하게는 이견이 있을 수 있는 듯.

    exception의 경우도 로직이 간단하냐 아니냐보다, 예외 상황을 어디서 처리하고 싶은가가 더 중요한 듯. 해당 메서드에서 한 번만 검사하고 나서 끝난다면 if-else도 괜찮으나, 처리할 위치를 바꿀 가능성이 높거나, 공통적인 처리를 해야 한다면 exception이 좋죠. 예로 든 null 같은 경우도 null이 그 자체로 의미가 있는 값이 아니라 예외상황이라서 온 null이라면 if-else로 처리하면 안되고 NullPointerException이 발생하게 두고, 다른 곳에서 처리하는 것이 맞겠죠. 사실은 if-else는 그 자체로 해악이 크기 때문에 exception을 오용하는 해악 정도는 차라리 괜찮은지도.

    Reinventing the wheel도 요즘은 상황이 많이 바뀌어서, 요즘은 혁신의 도구로 what if I reinvent the xxx?와 같은 질문을 사용하기도 하니까요. git가 대표적인 사례죠.
  • 권남 2011/10/16 17:20 #

    본문에서 exception에 관한 내용은 예외를 발생시킨 그 위치에서 받아서 바로 로직으로 처리할 경우에 대한 것입니다. 영록님이 말씀하신 경우에는 throw된 것을 받아서 처리하는게 맞겠지요.

    저는 git이 버전관리시스템이라는 바퀴를 재발명한 것이라고 보지 않습니다. 즉, "바퀴의 재발명"이라는 말에 대한 정의가 저와 영록님이 약간 다른 것 같네요.
    git이 다른 버전관리시스템의 재발명이다 이런식으로 생각을 한다면 "세상의 모든 자동차는 세계 최초의 자동차의 재발명이다" 이런 말이 될 것 같네요.
    본문에서 말하고자 하는 바는 이미 존재하고 사용하는데 아무 문제가 없는 모듈을 "그보다 못하거나 그와 동등한 수준으로" 다시 짜지 말라라고 이해됩니다.

    Google Guava 라이브러리도 Apache Commons를 흉내낸 개선 버전입니다만, 저는 Guava가 Commons의 재발명이라고 생각하지 않습니다. "개선된 새로운 것"이라고 보지요.

    이것은 단어 정의를 어떻게 하느냐의 문제가 될 것 같네요.
  • 링고 2011/10/16 13:33 #

    자주 사용하지만 좋지 않은 결과를 가져오는 방법을 안티 패턴이라고 부르는군요. 리눅스 패키지 컴파일이 안될 때 라이브러리 파일을 구해서 라이브러리 디렉토리에 복사하는 식으로 해결하는 경우가 많은데 이것도 마찬가지로 안티 패턴이라고 볼 수 있을 것 같네요. 분명 프로그램 실행은 되는데 뭔가 버그가 있다던가 에러가 생긴다던가 예외 상황이 많이 발생하더군요.
  • jkh 2011/10/16 17:37 # 삭제

    안티패턴이라고 해서 뭔가 했더니 '패턴의 안티'가 아니라 '안티인 패턴'이었군요....
  • 몽몽이 2011/10/16 20:56 #

    많은 분들이 오해하는 부분이지요. 저는 그것 때문에 꼴통으로 몰려 곤혹을 치룬 적도;;;
  • SY Kim 2011/10/17 17:14 #

    Gold plating을 열심히 하면 자신의 몸만 축나죠.

    딱 클라이언트가 원하는 수준까지 해주고 여가를 즐기라는 깊은 뜻이 있을지도 모르겠습니다.
  • 권남 2011/10/17 20:50 #

    프로그램을 짜다보면 가끔 사용자가 요청하지 않아도 "아.. 아 기능 넣으면 더 편리할거 같은데..", "아.. 이렇게 추상화를 더 하면 미래에 뭔가 더 추가할 때 더 편해질 것 같은데.." 등등의 생각이 들게 된답니다.
    자기만족과 장인정신 사이에서 묘한 줄타기가 이뤄지게 되는데요.
    그걸 지나치지 않게 조정할 수 있어야겠죠.

    저는 가끔, 그 자기만족 때문에 오히려 시스템의 유지보수성을 떨어뜨리는 프로그래머들도 봅니다. 저 자신이 그럴때도 있구요.
  • 용식 2011/10/19 00:47 # 삭제

    공감이 많이 가는 글...
    뜨끔하게 만드는 글..
    좋은 글 감사합니다. :D
  • 아름프로 2011/10/23 13:00 #

    Gold Plating을 다른 책에서는 기본적으로 요구한(핵심) 요구사항 외에 그이후에 발생한 추가적인 요구사항 (자잘한) 을 처리하다 핵심 요구사항을 제대로 처리 못하는 사항을 이야기 하더군. 이거나 저거나 요구사항 외적(!)인 것에 치우쳐 자칫 핵심을 놓치는 것을 경계하는 측면에서는 비슷한 뜻일 것 같지만... 어쨌든, 참고삼아 올려봄세. ^^
  • 기차나 2012/03/28 08:26 # 삭제

    좋은 글과 댓글 읽고 갑니다.ㅎㅎ
    제 북마크에 추가하고, 종종 들리겠습니다. ^^
  • epicdev 2013/06/19 10:26 # 삭제

    전산학의 대가인 Donald Knuth가 이런 유명한 말을 했죠: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil"
※ 로그인 사용자만 덧글을 남길 수 있습니다.