정적 팩터리나 생성자를 통한 객체 생성은 선택적 매개변수가 많을 때 적절히 대응하기가 어려운 단점이 있다. 이를 해결하기 위해 책에서는 세가지 패턴을 소개한다. 점층적 생성자 패턴 필수 매개변수만 받는 생성자 부터 시작해 선택 매개변수를 전부 다 받는 생성자까지 매개변수를 늘려나가는 방식 인스턴스를 만들려면 원하는 매개변수를 모두 포함한 생성자 중 가장 짧은 것을 골라 호출 이 경우, 보통 사용자가 설정하길 원하지 않는 매개변수 까지 포함할 수도 있는데, 어쩔 수 없이 그런 매개변수도 값을 지정해줘야 함. 즉, 점층적 생성자 패턴은 매개변수의 개수가 많아지면 클라이언트 코드를 작성하거나 읽기 어렵게 된다. public class NutritionFacts { private final int serving..
Optional은 무엇인가요? Optional는 'T타입의 객체'를 감싸는 래퍼 클래스이다. Optional의 용도 (옵셔널 반환은 신중히 하라, 이펙티브 자바 아이템 55) 자바 8전에는 메서드가 특정 조건에서 값을 반환할 수 없을 때, 예외를 던지거나 null을 반환했다. 두 방법 모두 허점이 있다. 예외는 진짜 예외 상황에만 사용해야 한다. (이펙티브 자바 아이템 69) 또, 예외 생성 시 스택 추적에 비용이 든다. null을 반환할 수 있는 메서드 호출 시, null 처리 코드를 추가해야 한다. 만약, 무시하고 처리하지 않으면 나중에 원인과는 상관없는 곳에서 NPE가 발생할 수 있다. Optional는 null이 아닌 T타입 참조를 하나 담거나, 아무것도 담지 않을 수 있다. 이를 이용해 보통은 ..
클래스를 이용한 타입 계층 구현 타입은 객체의 퍼블릭 인터페이스를 가리킨다. 클래스는 객체의 타입과 구현을 동시에 정의하는 것과 같다고 볼 수 있다. 이러한 점이 객체지향 언어에서 클래스를 사용자 정의 타입(user-defined data type)이라고 부르는 이유다. public class Phone { private Money amount; private Duration seconds; private List calls = new ArrayList(); public Phone(Money amount, Duration seconds) { this.amount = amount; this.seconds = seconds; } public Money calculateFee() { // 생략 } } Phon..
단순히 코드를 재사용할 목적으로 상속을 사용해서는 안된다. 재사용을 위해 상속을 사용할 경우 부모 클래스와 자식 클래스가 강하게 결합된다. 상속을 사용하는 일차적인 목표는 코드 재사용이 아니라 타입 계층을 구현하는 것이어야 한다. 코드 재사용은 상속이 아닌 합성을 사용하는 게 올바르다. 💡 객체지향 프로그래밍과 객체 기반 프로그래밍 객체 기반 프로그래밍이란 상태와 행동을 캡슐화한 객체를 조합해서 프로그램을 구성하는 방식을 가리킨다. 이 정의에 따르면 객체지향 프로그래밍 역시 객체 기반 프로그래밍의 한 종류다. 단 객체 기반 프로그래밍은 상속과 다형성을 지원하지 않는다. 타입 먼저, 프로그래밍 언어 관점에서의 타입과 개념 관점에서의 타입에 대해 알아보자. 개념 관점의 타입 개념 관점에서 타입은 우리가 인지..
상속의 단점을 피하면서 코드를 재사용하기 위해 합성을 사용할 수 있다. 합성은 구현에 의존하지 않고, 퍼블릭 인터페이스에 의존한다. 상속은 부모 클래스에 구현된 코드를 재사용하지만, 합성은 포함된 객체의 퍼블릭 인터페이스를 재사용한다. 이는 구현에 대한 의존성을 인터페이스에 대한 의존성으로 변경시키고, 클래스 사이의 결합도를 낮추는 효과를 준다. 상속을 합성으로 변경하기 10장에서 코드 재사용을 위해 상속을 남용했을 때 생길 수 있는 문제로 3가지 예시를 알아봤었다. 불필요한 인터페이스 상속 문제 메서드 오버라이딩의 오작용 문제 부모 클래스와 자식 클래스의 동시 수정 문제 상속 관계를 합성으로 바꿔서 이 세 가지 문제를 해결할 수 있다. 불필요한 인터페이스 상속 문제 java.util.Properties..
이번 장에서는 클래스를 재사용하기 위해 새로운 클래스를 추가하는 가장 대표적인 기법인 상속과 합성 중 상속과 잘못된 상속으로 인해 발생하는 문제들과 해결방안에 대해 알아보겠습니다. 상속과 중복 코드 DRY원칙 중복 코드는 변경을 방해한다. 중복 코드가 가지는 가장 큰 문제는 코드를 수정하는 데 필요한 노력을 몇 배로 증가시킨다는 것이다. 중복 코드는 수정과 테스트에 드는 비용을 증가시킨다. 만약 요구사항이 변경됐을 때 두 코드를 함께 수정해야 한다면 이 코드는 중복이다. 함께 수정할 필요가 없다면 중복이 아니다. 모양이 유사하다는 것은 단지 중복의 징후일 뿐이다. **DRY는 “반복하지 마라”**라는 뜻의 Don’t Repeat Yourself의 첫 글자를 모아 만든 용어로 간단히 말해 동일한 지식을 중..
개방-폐쇄 원칙 소프트웨어 개체(클래스, 모듈, 함수 등등)는 확장에 대해 여려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다. 확장에 대해 열려 있다 : 애플리케이션의 요구사항이 변경될 때 이 변경에 맞게 새로운 ‘동작’을 추가해서 애플리케이션의 기능을 확장할 수 있다. 수정에 대해 닫혀 있다 : 기존의 ‘코드’를 수정하지 않고도 애플리케이션의 동작을 추가하거나 변경할 수 있다. 컴파일 타임의 의존성을 고정시키고 런타임 의존성을 변경하라 의존성 관점에서 개방-폐쇄 원칙을 따르는 설계란 컴파일 타임 의존성은 유지하면서 런타임 의존성의 가능성을 확장하고 수정할 수 있는 구조라고 할 수 있다. 런타임 의존성 : 실행 시에 협력에 참여하는 객체들 사이의 관계 컴파일 타임 의존성 : 코드에서 드러나는 클래스들..
이번 주 스터디는 8, 9장에 대해 나눈다. 7장은 쉬어가는 파트라고 해서 건너뛰었다. 8장에서는 의존성을 잘 관리하기 위해 의존성을 이해하고 의존성을 관리하는 원칙과 기법에 관해 학습한다. 의존성 이해하기 변경과 의존성 어떤 객체가 협력하기 위해 다른 객체를 필요로 할 때, 두 객체 사이에서는 의존성이 존재하게 된다. 의존성은 실행 시점과 구현 시점에 따라 다른 의미를 가진다. 실행 시점 : 의존하는 객체가 정상적으로 동작하기 위해서는 실행 시에 의존 대상 객체가 반드시 존재해야 한다. 구현 시점 : 의존 대상 객체가 변경될 경우 의존하는 객체도 함께 변경된다. public class PeriodCondition impolements DiscountCondition { public boolean isS..