티스토리 뷰

JAVA

나머지 자바 공부

세댕댕이 2022. 8. 1. 01:02

* 이펙티브 자바 2/E를 읽고 공부하기 위해 기록한 게시글입니다.

 

45. 지역변수의 유효범위를 최소화하라

* 메서드의 크기를 줄이고 특정한 기능에 집중하라.

- 두 가지 서로 다른 기능을 한 메서드 안에 넣어두면 한 가지 기능을 수행하는데 필요한 지역 변수의 유효범위가 다른 기능까지 확장되는 문제가 발생한다. 이러한 문제를 막기 위해서는 각 기능을 나눠 별도 메서드로 구현하라.(SRP)

 

* 지역변수의 유효범위를 최소화하는 가장 강력한 기법은, 처음으로 사용하는 곳에서 선언하는 것이다.

- 사용하기 전에 선언하는 것은 코드를 읽는 사람만 혼란스럽게 만든다.

- 지역변수를 너무 빨리 선언하면 유효범위가 너무 앞뒷쪽으로 확장되게 된다. 지역변수의 유효범위는 선언된 지점으로부터 해당 블록 끝까지다. 어떤 블록 밖에서 선언된 변수는 프로그램이 해당 블록 수행을 끝내고 나서도 계속 사용가능하다.

-> 어떤 변수를 원래 사용하려 했던 곳 외의 장소에서 사용할 수도 있고, 이는 끔찍한 결과를 가져온다.

 

* 거의 모든 지역변수 선언에는 초깃값(initalizer)가 포함되어야 한다.

- 변수를 적절히 초기화하기에 충분한 정보가 없다면, 그때까지 선언을 뒤로 미뤄라.

 

* 순환문(루프)를 잘 쓰면 변수의 유효범위를 최소화할 수 있다.

- while문 보다는 for문을 사용하는 것이 좋다. (순환문 내부 변수의 내용은 반복 이후에는 필요없다는 가정 하.)

-> for문이나 for-each문은 순환문 변수를 이용해 반복문 블록 안에서만 사용되는 변수를 이용할 수 있기 때문.

 

 

46. for문 보다는 for-each문을 사용하라

* 성가신 코드를 제거하고 반복자나 첨자 변수를 완전히 제거해 오류의 가능성을 없앤다. 또한 배열 첨자가 이동할 수 있는 한계를 딱 한번만 계산하기에 성능 면에서도 더 유리하다.

 

* for-each문은 컬렉션과 배열 뿐만 아니라 Iterable 인터페이스를 구현하는 어떠한 객체도 순회할 수 있다.

 

* for-each 문을 사용할 수 없는 경우

1. 필터링: 컬렉션을 순회하다가 특정한 원소를 삭제하고자 할 경우

2. 변환: 리스트나 배열을 순회하다가 일부 또는 전체 원소의 값을 수정/변경해야 할 경우

3. 병렬 순회: 여러 컬렉션을 병렬적으로 순회해야 하고, 모든 반복자나 첨자변수가 발맞춰 나아가도록 구현해야 하는 경우.

 

 

47. 어떤 라이브러리가 있는지 파악하고 적절히 활용하라.

"발명된 바퀴를 다시 발명하지 말라(Don't reinvent the wheel)"

최고의 전문가들이 만든, 이미 충분히 검증된 라이브러리를 적극!사용해라.

- 실제로 하려는 일과 큰 관련도 없는 문제에 대해 전혀 시간낭비를 할 필요가 없다.

- 라이브러리를 개발한 전문가의 지식 및 경험도 적극 활용할 수 있다.

- 개발자가 별 다른 노력을 하지 않아도 성능이 점차 개선된다 (라이브러리 공급 조직이 성능을 계속 개선해주기 때문)

 

하지만! 자바 개발자라면 java.lang, java.util 패키지에 대한 내용 정도는 기본적으로 숙지하고 있어야 한다.

 

 

48. 정확한 답이 필요하다면 float과 double은 피해라

float과 double은 돈과 관계된 계산에는 적합하지 않다

- float과 double은 0.1을 비롯한 음의 거듭제곱 수를 정확히 나타낼 수 없다.

-> 정확한 답을 요구하는 문제, 특히 소숫점이 포함된 경우에는 float이나 double을 사용하면 안된다.

 

돈 계산을 할 때는 BigDecimal, int 또는 long을 사용하라.

* BigDecimal은 기본 산술연산 자료형보다는 느리고, 사용이 불편하다는 단점이 있긴 하다. 그래도 뭐 정확하면 그걸로 된거지 않을까?



49. 객체화된 기본 자료형 대신 기본 자료형을 이용하라

reference type(Integer, Character, Double 등..) 보다는 primative type(int, char, double 등...)을 사용하라

- 모든 기본 자료형에는 대응되는 참조 자료형이 존재하고, 이를 객체화된 기본 자료형(boxed primitive type), 그냥 boxing 됐다고 하기도 한다.

- 자바 1.5부터 autoboxingauto-unboxing 기능이 언어의 일부가 되었고, 기본 자료형과 객체 표현형간의 관계를 희미하게 만든다. 하지만 이 둘 간의 차이를 알고 어떤 것을 사용할지 신중하게 결정하는 것이 필요하다.

(autoboxing, auto-unboxing 과정에서 불필요한 객체들이 만들어지면 성능 저하를 일으킬 수 있다.)

 

<차이점>

1. 기본 자료형은 값만 가지지만, 객체화된 기본 자료형은 값 외의 신원(identity)를 가진다

-> 객체타입 자료형 객체가 두 개 있을 때, 값은 같더라도 신원은 다를 수 있다.

 

2. 객체타입 자료형은 null이 들어갈 수 있다.

 

3. 기본 자료형이 시간이나 공간 요구량 측면에서 일반적으로 객체타입 자료형보다 효율적이다.

 

* 객체타입 자료형에 == 연산자를 사용하는 것은 거의 항상 오류라고 봐야한다.

- 객체타입 자료형을 서로 == 으로 비교하는 것은 값을 비교하는 것이 아니라 서로의 참조(주소)값을 비교하는 것이다. 이는 개발자의 예상과는 전혀 다르다.

 

* 기본 자료형과 객체타입 자료형을 한 연산 안에 섞어놓으면 객체타입 자료형은 자동으로 기본 자료형으로 변환된다

- auto-unboxing이 이뤄질 때 NPE 발생 가능

 

* 객체타입 자료형은 그럼 언제 사용하면 좋은가?

=> 컬렉션의 요소, 키, 값으로 사용해야 할 때

- 형인자 자료형의 인자로는 객체화된 기본 자료형을 사용해야 한다. 기본 자료형을 쓸 수 없다.

 

 

50. 다른 자료형이 적절하다면 문자열 사용은 피하라

문자열(String) 클래스는 참 잘 만들어놨기 때문에 원래 설계된 목적 이외의 용도로도 사용되는 경우가 있다.

문자열로 해서는 안되는 일을 알아보자..

 

1. 값 자료형을 대신하기에는 부족하다

2. enum 자료형을 대신하기에는 부족하다

3. 혼합 자료형을 대신하기에는 부족하다

 

= 더 좋은 자료형이 있으면 그걸 써라

 

 

51. 문자열 연결 시 성능에 주의하라

문자열을 연결(concatenation)하는 것은 여러 문자열을 합치는 편리한 수단이나, 연결이 많아지면 성능이슈가 생길 수 있다.

- n개의 문자열에 연결 연산자를 반복 적용해서 연결하는데 걸리는 시간은 n^2에 비례한다. 문자열이 변경 불가능하기 때문이다. (문자열 두 개를 연결할 때 그 두 문자열의 내용은 전부 복사된다)

 

* 문자열 연결은 StringBuilder를 사용하라!!

- 단순히 두 문자열을 + 로 합치는 것에 비해 성능 차이가 어마어마하다

- 이외에도 문자 배열(char[])을 사용하는 것도 고려할 수 있음

 

 

52. 객체를 참조할 때는 그 인터페이스를 사용해라

객체를 참조할 때는 클래스보다는 인터페이스를 사용해라. 

- 적당한 인터페이스 자료형이 있다면 인자나 반환값, 변수, 그리고 필드의 자료형은 클래스 대신 인터페이스로 선언해라.

-> 프로그램이 훨씬 유연해진다. 다형성 굿

 

* 다만 적당한 인터페이스가 없는 경우는 객체를 클래스로 참조하는 것이 당연하다. 필요한 제기능을 제공하는 클래스 가운데 가장 일반적인 클래스를 클래스 계층 안에 찾아서 사용해라.

 

 

 

55. 신중하게 최적화 하라

<명언>

"맹목적인 어리석음을 비롯한 다른 어떤 이유보다도, 효율성이라는 이름으로 저질리지는 죄악이 더 많다"

"작은 효율성에 대해서는 잊어버려라. 섣부른 최적화는 모든 악의 근원이다"

"최적화를 할 때는 아래의 두 규칙을 따르라. 1. 하지마라 2. 완벽히 명료한, 최적화되지 않은 해답을 얻을 때 까지는 하지마라"

 

최적화는 좋을 때보다 나쁠 때가 더 많다. 섣불리 시도하면 더더욱 그렇다.

1. 빠른 프로그램이 아닌 좋은 프로그램을 만들려고 노력하라

- 성능 때문에 구조적인 원칙을 희생하지 마라

- 좋은 프로그램은 정보 은닉의 원칙을 지키고 설계에 관한 결정은 각 모듈 내부적으로 내려진다. 덕분에 그 설계는 시스템의 다른 부분에는 영향을 주지 않으면서 독립적으로 변경될 수 있다.

 

2. 설계를 할 때 성능을 제약할 가능성이 있는 결정들은 미리 피해라

- 성능 문제가 발견되고 난 시점은 이미 코드를 수정하기 어렵거나 불가능한 상황이다.

3. API를 설계할 때 내리는 결정들이 성능에 어떤 영향을 끼칠 지 생각해라

 

4. 좋은 성능을 내기 위해 API를 급진적으로 바꾸는 것은 바람직하지 않다.

 

5. 최적화를 시도할 때마다 전후 성능을 측정하고 비교하라

 

최적화를 검토할 때 가장 먼저 해야할 일은 구현에 쓰인 알고리즘을 검토하는 것

- 저수준의 최적화를 아무리 해봐야 알고리즘을 잘못 골랐다면 성능을 만회할 수가 없다.

 

 

56. 일반적으로 통용되는 작명 관습을 따라라

네이밍 컨벤션을 따라라!! 기본이야 기본!

https://google.github.io/styleguide/javaguide.html

 

Google Java Style Guide

1 Introduction This document serves as the complete definition of Google's coding standards for source code in the Java™ Programming Language. A Java source file is described as being in Google Style if and only if it adheres to the rules herein. Like ot

google.github.io

 

 

 

57. 예외는 예외적 상황에만 사용하라

말 그대로. 예외는 정말 예외적 상황에만 사용해라. 평상시 제어 흐름에 이용되서는 안된다.

- 잘 설계된 API는 클라이언트에게 평상시 제어흐름의 일부로 예외를 사용하도록 해서는 안된다.

 

 

58. 복구 가능 상태는 점검지정 예외를 사용하고 프로그래밍 오류에는 실행시점 예외를 이용하라

복구할 수 있을것으로 생각되는 상황에 대해서는 Checked Exception을 던져라.

- 체크 예외를 던지는 메서드를 호출한 클라이언트는 해당 예외를 catch절 안에서 처리하든지, 계속 밖으로 던지든지 해야한다.

-> 메서드를 호출하면 해당 예외와 관계된 상황이 발생할 수 있음을 알리는 구실을 한다.

 

* API 사용자에게 체크 예외를 준다는 것은 그 상태를 복구할 수 있다는 권한을 준 것이다. 

- 사용자는 그 권한을 무시할 수 있다. (catch로 잡은 다음 삼키기. 아무 처리도 안함) = 매우 곤란한 방법. 

 

* 언체크 예외에는 런타임 예외와 오류 두 종류가 있다

- 둘 다 굳이 catch로 처리할 필요가 없으며, 일반적으로는 처리해서도 안된다.

- 프로그램이 언체크 예외를 던진다는 것은 복구가 불가능한 상황에 직면했다는 것으로, 더 진행해봐야 득보다 실이 크다는 뜻이다.

 

* 프로그래밍 오류를 표현할 때에는 Runtime Exception을 던져라

- 사용자 정의 무점검 throwable을 만들 때에도 Runtime Exception의 하위 클래스로 만들어야 한다.

 

* Error의 하위 클래스는 새로 만들지 마라. 걍 건들 일이 없음.

 

(+) https://sedangdang.tistory.com/209

 

스프링 볶음밥 - 4장 - 예외

# 이 게시글은 "토비의 스프링" 책을 보고 정리를 위해 기록해둔 게시글입니다. [이전 글] 더보기 볶음밥 1장 - 1,2,3: 자바빈, 디자인 패턴(템플릿 메소드, 팩토리 메소드, 전략 패턴), 관심사의 분

sedangdang.tistory.com

더보기

런타임 예외 중심 전략을 따르자

 

* 체크 예외를 계속 throws 를 이용해 떠넘기기만 하는 것은 메소드만 지저분해지고 나쁜 습관이다!!

- 어차피 복구 불가능한 예외라면 런타임 예외로 포장해서 불필요한 throws 만들게 하지 말자

=> 런타임 예외 중심 전략!!

==> 복구할 수 있는 예외는 없다고 생각하고 예외가 생겨도 런타임 예외이므로 시스템 레벨에서 알아서 처리하거나, 꼭 필요하다면 직접 잡아서 대응하는 낙관적인 전략 (일단 반드시 잡고 보는 체크 예외와 대비된다)

 

* 그럼 체크 예외는 쓸 일이 없나? 

- 애플리케이션 자체 로직에 의해 의도적으로 발생시키고, 반드시 catch 해서 조치를 취하도록 요구하는 예외인 경우 (이를 "애플리케이션 예외"라고도 함)에는 의도적으로 체크 예외를 사용해야 한다.

- 반드시 대응해야할 예외 상황에 대한 로직 구현을 강제시킬 때 사용

 

 

59. 불필요한 점검지정 예외 사용은 피하라

= 쓸데없는 체크 예외를 던지지 마라

하나 이상의 체크 예외를 던지는 메서드를 호출할 때는 예외를 받아 처리하는 catch 블록을 하나 이상 만들거나 예외를 다시 던진다고 선언하고는 그냥 내비둬야 한다. 참 번거로운 일이고 코드도 지저분해진다.

 

API를 제대로 사용해도 예외상황이 발생하는 것을 막을 수 없을때, 그리고 API 사용자가 이 상황에 대해 조치를 취할 수 있을때는 체크 예외를 사용해도 좋다. (애플리케이션 예외 - 반드시 조치를 취하도록 만드는 경우 포함)

이 경우가 아니라면 언체크 예외(런타임 예외)를 던져라

 

 

60. 표준 예외를 사용해라

프로그래밍 전문가일수록 기존에 있는 코드를 높은 수준으로 재사용한다.

"발명된 바퀴를 다시 발명하지 말라(Don't reinvent the wheel)"

 

예외에 있어서도 마찬가지. 대부분의 API가 필요로하는 언체크 예외는 이미 만들어져있다.

- 배우기 쉽고 사용하기 편리함

- 다른 개발자들도 친숙한, 관습을 따르는 개발 가능 -> 가독성이 좋다

- 예외 클래스 개수를 줄이면 메모리 사용량이 줄어들어 클래스 로딩 시간도 줄어든다

 

 

65. 예외를 무시하지 마라

예외를 무시하는 것은 화재경보를 무시하는 것과 똑같다

비어있는 catch 블록은 제발 사용하지 마라. (예외 삼키기) 주석이라도 남겨라

 

 

 

나머지는... 생략!

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함