구현하기 쉬운 테스트부터 시작하기 구현이 쉬운 테스트 케이스부터 시작한다. 한 번에 많은 부분을 수정해서 테스트하지 않는다. 테스트에 통과한 즉시 리팩토링 한다. 새로 추가한 코드에서 리팩토링이 필요한 부분이 있는지 즉시 검토한다. 코드가 추가되고, 테스트를 통과(버그x)할 때마다 리펙토링을 하면, 많은 코드를 한꺼번에 리팩토링해서 발생하는 side effect을 최소화 할 수 있다. 예외 테스트 케이스에서 정상적인 케이스로 테스트 진행 다양한 예외 상황은 복잡한 if-else 블록을 양산할 수 있다. 예외 상황을 고려하지 않고, 개발된 코드에 나중에 예외 상황을 반영하려면 코드의 구조를 바꿔야 하는 경우가 생기거나, 코드 중간에 예외 사항을 처리하기 위한 if 블록이 추가되면서 복잡도가 증가하게 된다...
TDD는 테스트부터 시작한다. 먼저 테스트를 하고 그 다음에 구현을 한다. TDD 개발 순서 테스트 코드를 먼저 작성한다. 개발하고자 하는 기능이 올바르게 동작 했을 때의 결과를 확인 가능한 테스트 코드를 먼저 작성한다. 테스트 코드에 올바르게 동작하는 기능을 개발한다. 비밀번호 복잡도 평가 로직 개발 /** * 비밀번호 보안 수준 테스트 * [보안 수준 조건] * -길이 8글자 이상 * -0~9 사이의 숫자를 포함 * -대문자 포함 * * 위의 세 가지 조건을 충족하면 암호는 강함. * 2개의 조건을 충족하면 보통. * 1개 이하의 조건을 충족하면 약함. * 비밀번호가 공백(Empty)이거나, 없으면 인식불가. */ 비밀번호 복잡도의 테스트 로직을 아래와 같이 만든다. 테스트 대상 클래스명 테스트 대상..
IntelliJ에 Java 프로젝트 생성 [File] -> [New] -> [Project...] 아래와 같이 [Java], [Java 1.8]을 선택 후 Next 클릭 템플릿 선택하지 않고, [Next] 클릭 Project name과 경로를 입력 후 [Finish] Junit 5 라이브러리 추가 [File] -> [Project Structure...] 실행 좌측에서 [Modules] 선택 후 우측에서 [Dependencies] 탭 선택 [+]버튼 클릭 후 [Library...] -> [From Maven...] 클릭 검색창에 "org.junit.jupiter:junit-jupiter:5.5.0" 입력 -> [OK] 클릭 org.junit.jupiter:junit-jupiter:5.5.0 Configu..
프로그램 코드를 작성하다보면 기존에 만들어진 인스턴스의 내용을 일부 수정하여 사용하고 싶을 때가 있다. 그런 경우 객체를 새로 생성할 때는 사용하는 new Object() 메서드보다 [그림 5-31]처럼 clone() 메서드를 이용해 기존의 것을 복사하여 일부만 바꿔 인스턴스를 생성할 수 있다. 이런 개념을 확장하여 처음부터 일반적인 prototype(원형)을 만들어놓고, 그것을 복사한 후 필요한 부분만 수정하면 new Object() 메서드로 객체를 생성하는 것보다 편리하다. prototype 패턴은 이처럼 인스턴스를 복제하여 사용하는 구조이다. 따라서 생성할 객체의 원형을 제공하는 프로토타입 인스턴스로부터 생성할 객체들의 타입이 결정되도록 한다. 이 패턴은 객체를 생성할 때 갖추어야 할 기본 형태가 ..
메멘토 패턴은 객체를 이전 상태로 되돌릴 수 있는 기능을 제공하는 디자인 패턴이다. 메멘토 패턴은 3개의 객체로 구현된다: 오리지네이터(originator), 케어테이커(caretaker), 메멘토(memento). 오리지네이터는 내부 상태를 보유하고 있는 일부 객체이다. 케어테이커는 오리지네이터에 대해 어떤 상태 변경을 처리하지만, 변경에 대한 실행 취소(원복) 하기를 원한다. 케어테이커는 먼저 오리지네이터에게 메멘토 객체를 요청한다. 그 뒤 예정된 일련의 명령을 수행한다. 이전의 상태로 되돌리기 위해 메멘토 객체에게 기존 상태를 요청해서 오리지네이터에 반환한다. 메멘토 패턴은 본래의 클래스(Originator)의 복잡도는 증가시키지 않으면서 객체의 저장 및 복구 기능은 구현하는 것으로 상태의 보관,..
M개의 object 사이에 N개의 관계가 형성되어 있어 아주 복잡하게 얽혀있을때 이를 M:1 관계로 바꿔주기 위해 중재자 패턴을 사용한다. M개의 object 사이에 이들의 관계를 control 하는 Mediator를 하나 넣어서 Mediator가 모든 object들의 communication을 관리하도록 한다. objects들 사이에 Mediator를 넣어 연결관계를 캡슐화한다. class들을 loose coupling 상태로 유지할 수 있다. (서로 알 필요 없고 Mediator가 모두 관리하므로) 장점 : 전체적인 연결관계를 이해하기 쉽다 (communication의 흐름을 이해하기 쉽다) 단점 : 특정 application 로직에 맞춰져있기 때문에 다른 application에 재사용하기 힘들다 (..
공통으로 사용하는 클래스를 만드는 팩토리 클래스를 두고 사용 클래스의 인스턴스가 팩토리 클래스 내에 있을 시에는 꺼내서 사용하고, 없을 시에는 새로 생성해서 사용하는 패턴 플라이 웨이트 패턴을 통해 메모리 공간을 절약할 수 있다. 기본 설계 FlyWeight를 다루는데 Client가 직접적으로 다루지 않고, FlyWeightFactory를 통해 다루는 것을 볼 수 있다. public class FlyWeightObject { private String name; public FlyWeightObject(String name) throws InterruptedException { System.out.println(name + " : 객체 생성에 걸리는 시간 1초"); Thread.sleep(1000); t..
정의 클라이언트에게 어떠한 요청이 들어왔을 때, 요청을 받은 객체가 해당 요청을 해결할 수 없을 경우 연결된 다음 객체들에 전달하고 해당 요청을 해결할 수 있는 객체가 처리하는 방식입니다. 요청 객체와 처리 객체를 분리하거나 요청을 처리할 수 있는 객체가 여러 개인데 하나의 객체에 요청을 보낼 때 책임 연쇄 패턴을 적용할 수 있습니다. 즉, 요청을 처리할 수 있는 객체가 여러개이고 이러한 처리를 하는 객체가 명시적이지 않을 때 사용할 수 있는 패턴입니다. 쉽게 설명하면 어떤 요청이 그 요청을 담당하는 객체에 들어오면 각각의 요청에 대해서 특정한 객체가 담당하는 것이 일반적이지만 객체를 연결리스트와 같은 사슬 방식으로 연결한 후에 요청을 수행하지 못하는 객체라면 다음 객체에 넘기며 책임을 넘기는 형태의 패..
[용도] 빌더 패턴은 생성해야 되는 객체가 Optional한 속성을 많이 가질 때 생성자의 복잡도를 낮추면서 객체의 속성이 final 특성을 가지도록 만들어야 할 때 [생성 방법] 빌더 클래스를 Static Nested Class로 생성합니다. 이때, 관례적으로 생성하고자 하는 클래스 이름 뒤에 Builder를 붙입니다. 빌더 클래스의 생성자는 public으로 하며, 필수 값들에 대해 생성자의 파라미터로 받습니다. 옵셔널한 값들에 대해서는 각각의 속성마다 메소드로 제공하며, 이때 중요한 것은 메소드의 리턴 값이 빌더 객체 자신이어야 합니다. 마지막 단계로, 빌더 클래스 내에 build() 메소드를 정의하여 클라이언트 프로그램에게 최종 생성된 결과물을 제공합니다. 이렇듯 build()를 통해서만 객체 생성..
구조 패턴(Structural Pattern)이란? 구조 패턴이란 작은 클래스들을 상속과 합성을 이용하여 더 큰 클래스를 생성하는 방법을 제공하는 패턴입니다. 이 패턴을 사용하면 서로 독립적으로 개발한 클래스 라이브러리를 마치 하나인 양 사용할 수 있습니다. 또, 여러 인터페이스를 합성(Composite)하여 서로 다른 인터페이스들의 통일된 추상을 제공합니다. 구조 패턴의 중요한 포인트는 인터페이스나 구현을 복합하는 것이 아니라 객체를 합성하는 방법을 제공한다는 것입니다. 이는 컴파일 단계에서가 아닌 런타임 단계에서 복합 방법이나 대상을 변경할 수 있다는 점에서 유연성을 갖습니다. 브릿지 패턴 이해 및 예제 디자인 패턴의 교과서인 GoF에서는 브릿지 패턴에 대해 다음과 같이 정의하고 있습니다. 추상화(a..