본문 바로가기

(36)
객체지향 프로그래밍 협력, 객체, 클래스1. 어떤 클래스가 필요한지를 고민하기 전에 어떤 객체들이 필요한지 고민하라.2. 객체를 독립적인 존재가 아니라 기능을 구현하기 위해 협력하는 공동체의 일원으로 봐야 한다. 도메인의 구조를 따르는 프로그램 구조도메인 : 문제를 해결하기 위해 사용자가 프로그램을 사용하는 분야 클래스 구현하기객체 1. 상태와 행동을 함께 가지는 복합적인 존재2. 스스로 판단하고 행동하는 자율적인 존재캡슐화 : 데이터와 기능을 객체 내부로 함께 묶는 것접근 제어(access control) : 외부에서의 접근을 통제할 수 있는 메커니즘(접근 수정자(access modifier)를 제공)퍼블릭 인터페이스(public interface) : 외부에서 접근 가능한 부분구현(implementation) : 내부에..
객체, 설계 변경에 취약한 코드결합도(Coupling) : 객체 사이의 의존성 - 결합도가 높을 수록 함께 변경될 확률이 높아진다. - 결합도를 낮춰 변경이 용이한 설계를 만들어야 한다. 자율성을 높이자캡슐화(encapsulation) : 개념적이나 물리적으로 객체 내부의 세부적인 사항을 감추는 것객체를 인터페이스와 구현으로 나누고 인터페이스만을 공개하자 - 객체 사이의 결합도를 낮추고 변경하기 쉬운 코드를 작성하기 위해 따라야 하는 가장 기본적인 설계 원칙 캡슐화와 응집도응집도(cohesion) : 밀접하게 연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임하는 것 - 자신의 데이터를 스스로 처리하는 자율적인 객체를 만들면 결합도를 낮추고 응집도를 높일 수 있다. 절차지향과 객체지향절차지향 : 프로세스..
직렬화 자바 직렬화의 대안을 찾으라 - 직렬화 위험을 회피하는 가장 좋은 방법은 아무것도 역직렬화하지 않는 것이다. - 차선책은 신뢰할 수 없는 데이터는 절대 역직렬화하지 않는 것이다. - 새로운 시스템에서 자바 직렬화를 써야 할 이유는 전혀 없다. - 객체 역직렬화 필터링(java.io.ObjectInputFilter)를 사용하자. (블랙리스트 보다는 화이트리스트 방식을 추천한다.) Serializable을 구현할지는 신중히 결정하라 - Serialiazable을 구현하면 릴리스한 뒤에는 수정하기 어렵다. - 버그와 보안 구멍이 생길 위험이 높아진다. - 해당 클래스의 신버전을 릴리스할 때 테스트할 것이 많아진다. - Serializable 구현 여부는 가볍게 결정할 사안이 아니다.- 상속용으로 설계된 클래스..
동시성 공유 중인 가변 데이터는 동기화해 사용하라 - 동기화는 배타적 실행뿐 아니라 스레드 사이의 안정적인 통신에 꼭 필요하다. - Thread.stop은 사용하지 말자. - 가변 데이터는 단일 스레드에서만 쓰도록 하자. - 쓰기와 읽기 모두가 동기화되지 않으면 동작을 보장하지 않는다.- 동기화하지 않으면 한스레드가 수행한 변경을 다른 스레드가 보지 못할 수도 있다.- 공유되는 가변 데이터를 동기화하는데 실패하면 응답 불가 상태에 빠지거나 안전 실패로 이어질 수 있다.(디버깅 난이도가 가장 높은 문제에 속한다.) - 배타적 실행은 필요 없고 스레드끼리의 통신만 필요하다면 volatile 한정자만으로 동기화할 수 있다. 과도한 동기화는 피하라 - 응답 불가와 안전 실패를 피하려면 동기화 메서드나 동기화 블록 안에..
예외 예외는 진짜 예외 상황에만 사용하라 - 예외는 오직 예외 상황에서만 써야 한다. 절대로 일상적인 제어 흐름용으로 쓰여선 안 된다. - 잘 설계된 API라면 클라이언트가 정상적인 제어 흐름에서 예외를 사용할 일이 없게 해야 한다. 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라. - 호출하는 쪽에서 복구하리라 여겨지는 상황이라면 검사 예외를 사용하자. - 프로그래밍 오류를 나타낼 때는 런타임 예외를 사용하자. - 구현하는 비검사 throwable은 모두 RuntimeException의 하위 클래스여야 한다. (Error는 상속하지 말아야 할 뿐 아니라, throw 문으로 직접 던지는 일도 없어야 한다.) - 검사 예외도 아니고 런타임 예외도 아닌 throwable은 정의하..
일반적인 프로그래밍 원칙 지역변수의 범위를 최소화하라 - 가장 처음 쓰일 때 선언하자. - 선언과 동시에 초기화해야 한다. - 컬렉션이나 배열 순회for (Element e : c) {...} - 반복자가 필요할 때for (Iterator i = c.iterator(); i.hasNext(); ) {...} - 메서드를 작게 유지하고 한 가지 기능에 집중해라. 전통적인 for문 보다는 for-each문을 사용하라 - for-each문을 사용할 수 없는 상황- 파괴적인 필터링 : 컬렉션을 순회하면서 선택된 원소를 제거해야 하는 경우 (자바 8에서는 Collection의 removeIf 메서드를 사용한다.)- 변형 : 리스트나 배열을 순회하면서 그 원소의 값 일부 혹은 전체를 교체해야 하는 경우- 병렬 반복 : 여러 컬렉션을 병렬로..
메서드 매개변수가 유효한지 검사하라 - 메서드나 생성자를 작성할 때 매개변수들에 어떤 제약이 있을지 생각하고 메서드 코드 시작 부분에서 명시적으로 검사해야 한다. - public과 protected 메서드는 매개변수 값이 잘못됐을 때 던지는 예외를 문서화해야 한다. - 자바 7에 추가된 java.util.Objects.requireNonNull 메서드는 유연하고 사용하기도 편하니, 더 이상 null 검사를 수동으로 하지 않아도 된다.this.stratergy = Objects.requireNonNull(strategy, "전략"); 적시에 방어적 복사본을 만들라 - 클라이언트에서 불변식을 깨뜨리려고 한다고 가정하고 방어적으로 프로그래밍해야 한다. - Date는 낡은 API이니 새로운 코드를 작성할 때는 더 이상..
람다와 스트림 익명 클래스보다는 람다를 사용하라 - 익명 클래스Collection.sort(words, new Compareator() {public int compare(String s1, String s2) {return Integer.compare(s1.length(), s2.length());}} - 람다식을 함수 객체로 사용Collection.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length())); - 타입을 명시해야 코드가 더 명확할 때를 제외하고는, 람다의 모든 매개변수 타입은 생략하자. - 람다는 이름이 없고 문서화도 못 한다. 따라서 코드 자체로 동작이 명확히 설명되지 않거나 코드 줄 수가 많아지면 람다를 쓰지 말아야 한다. - 람다를 직..