Programming AntiPatterns라는 블로그 글이 올라와서 정리해 본다. 항상 말하지만, 정리는 참조만 하고 원문을 볼 것.
안티 패턴이란? - 문제에 대해 자주 사용되는 해결책이지만 안 좋은 결과를 가져오는 것.
안티패턴을 사용하는 이유는 관리자나 프로그래머가 더 나은 지식이 없고, 특정 타입의 문제에 대해 지식과 경험이 부족하거나 혹은 완벽한 패턴을 잘못된 상황에 적용할 때 발생하게 된다.
◆ 바퀴의 재발명
이미 있는 라이브러리나 프레임워크를 다시 만들지 말라.
유용한 프레임워크나 라이브러리의 존재를 잘 몰라서 발생하는 안티패턴. Apache Commons Lang 혹은 Commons Collections는 모든 자바프로젝트에서 포함되어야 한다. 리플렉션이 필요하면 Apache Commons Beanutils나 스프링의 BeanUtils와 BeanWrapper를 사용하라.
권남 주 : 요즘에는 Google Guava가 Apache Commons를 대체하는 중.
◆ 화물 숭배(Cargo Cult) 프로그래밍
화물 숭배
왜 그런지 이유도 모르면서 특정 방식이나 패턴을 사용하지 말라.
보통 스킬과 경험이 부족한 프로그래머들이 복사해서 붙여넣기하면서 발생한다.
안티패턴 예:
◆ 예외에 기반한 코딩/예외 처리(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 에서 더 볼 수 있다.
안티 패턴이란? - 문제에 대해 자주 사용되는 해결책이지만 안 좋은 결과를 가져오는 것.
안티패턴을 사용하는 이유는 관리자나 프로그래머가 더 나은 지식이 없고, 특정 타입의 문제에 대해 지식과 경험이 부족하거나 혹은 완벽한 패턴을 잘못된 상황에 적용할 때 발생하게 된다.
◆ 바퀴의 재발명
이미 있는 라이브러리나 프레임워크를 다시 만들지 말라.
유용한 프레임워크나 라이브러리의 존재를 잘 몰라서 발생하는 안티패턴. Apache Commons Lang 혹은 Commons Collections는 모든 자바프로젝트에서 포함되어야 한다. 리플렉션이 필요하면 Apache Commons Beanutils나 스프링의 BeanUtils와 BeanWrapper를 사용하라.
권남 주 : 요즘에는 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 에서 더 볼 수 있다.
덧글
외눈박이 동네에선 두눈 뜬 사람이 병신.
exception의 경우도 로직이 간단하냐 아니냐보다, 예외 상황을 어디서 처리하고 싶은가가 더 중요한 듯. 해당 메서드에서 한 번만 검사하고 나서 끝난다면 if-else도 괜찮으나, 처리할 위치를 바꿀 가능성이 높거나, 공통적인 처리를 해야 한다면 exception이 좋죠. 예로 든 null 같은 경우도 null이 그 자체로 의미가 있는 값이 아니라 예외상황이라서 온 null이라면 if-else로 처리하면 안되고 NullPointerException이 발생하게 두고, 다른 곳에서 처리하는 것이 맞겠죠. 사실은 if-else는 그 자체로 해악이 크기 때문에 exception을 오용하는 해악 정도는 차라리 괜찮은지도.
Reinventing the wheel도 요즘은 상황이 많이 바뀌어서, 요즘은 혁신의 도구로 what if I reinvent the xxx?와 같은 질문을 사용하기도 하니까요. git가 대표적인 사례죠.
저는 git이 버전관리시스템이라는 바퀴를 재발명한 것이라고 보지 않습니다. 즉, "바퀴의 재발명"이라는 말에 대한 정의가 저와 영록님이 약간 다른 것 같네요.
git이 다른 버전관리시스템의 재발명이다 이런식으로 생각을 한다면 "세상의 모든 자동차는 세계 최초의 자동차의 재발명이다" 이런 말이 될 것 같네요.
본문에서 말하고자 하는 바는 이미 존재하고 사용하는데 아무 문제가 없는 모듈을 "그보다 못하거나 그와 동등한 수준으로" 다시 짜지 말라라고 이해됩니다.
Google Guava 라이브러리도 Apache Commons를 흉내낸 개선 버전입니다만, 저는 Guava가 Commons의 재발명이라고 생각하지 않습니다. "개선된 새로운 것"이라고 보지요.
이것은 단어 정의를 어떻게 하느냐의 문제가 될 것 같네요.
딱 클라이언트가 원하는 수준까지 해주고 여가를 즐기라는 깊은 뜻이 있을지도 모르겠습니다.
자기만족과 장인정신 사이에서 묘한 줄타기가 이뤄지게 되는데요.
그걸 지나치지 않게 조정할 수 있어야겠죠.
저는 가끔, 그 자기만족 때문에 오히려 시스템의 유지보수성을 떨어뜨리는 프로그래머들도 봅니다. 저 자신이 그럴때도 있구요.
뜨끔하게 만드는 글..
좋은 글 감사합니다. :D
제 북마크에 추가하고, 종종 들리겠습니다. ^^