본문 바로가기

개발

Effective Java ( 이펙티브 자바 ) - 아이템 73 추상화 수준에 맞는 예외를 던지라 수행하려는 일과 관련 없어 보이는 예외가 튀어나오면 당황스러울 것이다. 메서드가 저수준 예외를 처리하지 않고 바깥으로 전파해버릴 때 종종 일어나는 일이다. 이는 윗 레벨 API를 오염시킨다. 상위 계층에서는 저수준 예외를 잡아 자신의 추상화 수준에 맞는 예외로 바꿔 던져야 한다. ( 예외 번역 - Exception Translation ) try { ... // 저수준 추상화를 이용한다. } catch (LowerLevelException e) { // 추상화 수준에 맞게 번역한다. throw new HigherLevelException(...); } 다음은 AbstractSequentialList에서 수행하는 예외 번역의 예다. 이는 List 인터페이스의 골격 구현이다.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 72 표준 예외를 사용하라 숙련된 프로그래머는 그렇지 못한 프로그래머보다 더 많은 코드를 재사용한다. 예외도 마찬가지로 재사용하는 것이 좋으며, 자바 라이브러리는 대부분 API에서 쓰기에 충분한 수의 예외를 제공한다. 표준 예외를 재사용하면 얻는 게 많다. 그중 최고는 여러분의 API가 다른 사람이 익히고 사용하기 쉬워진다는 것이다. 예외 클래스 수가 적을수록 메모리 사용량도 줄고 클래스를 적재하는 시간도 적게 걸린다. 가장 많이 재사용되는 예외는 IllegalArgumentException이다. 호출자가 인수로 부적절한 값을 넘길 때 던지는 예외로, 예를 들어 반복 횟수를 지정하는 매개변수에 음수를 건넬 때 쓸 수 있다. IllegalStateException도 자주 재사용된다. 이 예외는 대상 객체의 상태.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 71 필요 없는 검사 예외 사용은 피하라 검사 예외를 싫어하는 자바 프로그래머가 많지만 제대로 활용하면 API와 프로그램의 질을 높일 수 있다. 검사 예외는 발생한 문제를 프로그래머가 처리하여 안전성을 높이게끔 해준다. 물론, 검사 예외를 과하게 사용하면 오히려 쓰기 불편한 API가 된다. 어떤 메서드가 검사 예외를 던질 수 있다고 선언되었다면, 이를 호출하는 코드에서는 catch 블록을 두어 그 예외를 붙잡아 처리하거나 더 바깥으로 던져 문제를 전파해야만 한다. 어느 쪽이든 API 사용자에게 부담을 준다. 더구나 검사 예외를 던지는 메서드는 스트림 안에서 직접 사용할 수 없기 때문에 자바 8부터는 부담이 더욱 커졌다. API를 제대로 사용해도 발생할 수 있는 예외이거나, 프로그래머가 의미 있는 조치를 취할 .. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 70 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라 자바는 문제 상황을 알리는 타입으로 검사 예외, 런타임 예외, 에러 이렇게 세 가지를 제공한다. 언제 무엇을 사용해야 하는지 헷갈려 하는 프로그래머들이 종종 있다. 언제나 100% 명확한 것은 아니지만 이럴때 참고하면 좋은 멋진 지침들이 있다. 호출하는 쪽에서 복구하리라 여겨지는 상황이라면 검사 예외를 사용하라 이것이 검사 예외와 비검사 예외를 구분하는 기본 규칙이다. 검사 예외를 던지면 호출자가 그 예외를 catch로 잡아 처리하거나 더 바깥으로 전파하도록 강제하게 된다. 따라서 메서드 선언에 포함된 검사 예외 각각은 그 메서드를 호출했을 때 발생할 수 있는 유력한 결과임을 API 사용자에게 알려주는 것이다. 달리 말하면.. 더보기
Effective Java ( 이펙티브 자바 ) -10장 예외, 아이템 69 예외는 진짜 예외 상황에만 사용하라 try { int i = 0; while(true) range[i++].climb(); } catch (ArrayIndexOutOfBoundsException e) { } 전혀 직관적이지도 않다. 이 코드는 배열의 원소를 순회하는데, 무한루프를 돌다가 배열의 끝에 도달해 Exception이 발생하면 끝을 내는 순회 방식을 사용하고 있다. for (Mountain m : range) m.climb(); 표준적인 관용구는 위와 같다. 그렇다면 왜 예외를 써서 루프를 종료한 걸까? 잘못된 추론을 근거로 성능을 높여보려 한 것이다. JVM은 배열에 접근할 때마다 경계를 넘지 않는지 검사하는데, 일반적인 반복문도 배열 경계에 도달하면 종료한다. 따라서 이 검사를 반복문에도 명시.. 더보기
SRE 18장 - SRE 조직의 소프트웨어 엔지니어링 누군가에게 구글의 소프트웨어 엔지니어링 중 가장 많은 비중을 차지하는 제품이 무엇이냐고 묻는다면, 대부분 지메일이나 지도 같은 사용자 서비스라고 답할 것이다. 하지만, 사실 최종 사용자에게는 드러나지 않는 소프트웨어 엔지니어링의 비중도 엄청나다. 이들 중 상당 부분은 SRE 조직에서 개발한 것이다. SRE는 복잡한 프로덕션 환경을 직접 경험하고, 내부의 문제를 해결하기 위한 적절한 도구를 개발하며, 프로덕션 환경을 지속적이고 안정적으로 운영할 수 있는 다양한 활용 사례들을 만들어내고 있다. 바이너리 배포 메커니즘, 모니터링 또는 동적 서버 조합(dynamic server composition)을 기반으로 한 개발 환경의 구축 등 SRE 조직의 소프트웨어 엔지니어링 역량이 중요한 이유 SRE가 효율적으로 .. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 65 리플렉션보다는 인터페이스를 사용하라 리플렉션을 이용하면 여러 장점과 기능이 있지만, 단점도 있다. 컴파일타임 타입 검사가 주는 이점을 하나도 누릴 수 없다. 리플렉션을 이용하면 코드가 지저분하고 장황해진다. 성능이 떨어진다. 코드 분석 도구나 의존관계 주입 프레임워크처럼 리플렉션을 써야 하는 복잡한 애플리케이션 조차도 리플렉션 사용을 점차 줄이고 있다. 단점이 명확하다. 리플렉션은 아주 제한된 형태로만 사용해야 그 단점을 피하고 이점만 취할 수 있다. 컴파일타임에 이용할 수 없는 클래스를 사용해야만 하는 프로그램은 비록 컴파일타임이라도 적절한 인터페이스나 상위 클래스를 이용할 수는 있을 것이다. 다행히 이런 경우라면, 리플렉션은 인스턴스 생성에만 쓰고, 이렇게 만든 인스턴스는 인터페이스나 상위 클래스로.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 64 객체는 인터페이스를 사용해 참조하라 적합한 인터페이스만 있다면 매개변수뿐 아니라 반환값, 변수, 필드를 전부 인터페이스 타입으로 선언하라. 객체의 실제 클래스를 사용해야 할 상황은 '오직' 생성자로 생성할 때뿐이다. Set sonSet = new LinkedHashSet(); // 좋은 예. LinkedHashSet sonSet = new LinkedHashSet(); // 나쁜 예. 인터페이스를 타입으로 사용하는 습관을 길러두면 프로그램이 훨씬 유연해질 것이다. 단 주의할 점이 하나 있다. 원래의 클래스가 인터페이스의 일반 규약 이외의 특별한 기능을 제공하면, 새로운 클래스도 반드시 같은 기능을 제공해야 한다. 예를 들어, LinkedHashSet을 HashSet으로 바꾸게 되면 순서 정책을 고려해야.. 더보기