- 고정된 메모리 영역을 얻으면서 한번의 new로 인스턴스를 사용하기 때문에 메모리 낭비를 방지
- 싱글톤으로 만들어진 클래스의 인스턴스는 전역 인스턴스이기 때문에 다른 클래스의 인스턴스들이 데이터를 공유하기 쉽다.
- 의존관계상 클라이언트가 구현체에 의존하면서 DIP를 위반하게 된다. DIP를 위반하면 자연스럽게 OCP를 위반할 가능성도 높아진다.
- 싱글톤 패턴을 적용하기 위해 구현할 코드양이 많아지면서 비용이 늘어난다.
- 테스트가 어려워진다.
⇒ 인스턴스를 미리 다 받아서 설정이 끝난 상태이기에 유연한 테스트가 힘들다.- 내부 속성을 변경하거나 초기화가 어렵다.
- private생성자로 자식 클래스를 만들기 어렵다.
- 유연성이 떨어진다.
- 안티패턴으로 불리기도 한다.
상태를 유지하지 않는 객체를 설계하기 위해서는
- 특정 클라이언트에 의존적인 필드가 있으면 안된다.
- 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.
- 가급적 읽기만 가능해야 한다.
- 필드 대신 자바에서 공유되지 않는, 지역변수, 파라미터, ThreadLocal등을 사용해야 한다.
package hello.core.singleton;
public class StatefulService {
private int price; // 상태를 유지하는 필드
public void order(String name, int price) {
System.out.println("name = " + name + " price = " + price);
this.price = price;
}
public int getPrice() {
return price;
}
}
스프링 싱글톤은 클래스 자체에 의해서가 아니라, 스프링 컨테이너(Bean Factory/Application Context)에 의해 구현된다.
스프링에서는, 컨테이너 내에서 특정 클래스에 대해 @Bean이 정의되면, 스프링 컨테이너는 그 클래스에 대해 딱 한 개의 인스턴스를 만든다. 이 공유 인스턴스는 설정 정보에 의해 관리되고, bean이 호출될 때마다 스프링은 생성된 공유 인스턴스를 리턴 시킨다.
공유인스턴스의 생성시점은 스프링 컨테이너에 따라 달라지는데, 빈팩토리는 최초 호출시점에서 인스턴스를 생성하고(Lazy loading), 애플리케이션 컨텍스트는 미리 모든 공유인스턴스를 다 초기화해 두었다가 호출될때 바로 리턴시켜준다.
bean 관리의 주체인 스프링 컨테이너는 그 어떤 호출에도 단일 공유 인스턴스를 리턴시키므로 thread safety도 자동으로 보장
좋은 테스트의 원칙 FIRST 🥇
다른 함수가 실행을 끝낸 뒤 실행(call back)되는 함수(⇒ 나중에 호출되는 함수)
=> 코드를 통해 명시적으로 호출하는 함수가 아니라, 함수를 등록해 놓은 후 어떤 이벤트가 발생했거나 특정 시점에 도달했을 때 시스템에서 호출하는 함수.
(동적으로 이벤트 정의 ? )
class MyClass {
void myMethod(PrintB printB) {
a();
printB.b();
c();
}
void a() {
System.out.println("A");
}
void c() {
System.out.println("C");
}
}
interface PrintB {
void b();
}
public class Main {
public static void main(String[] args) {
MyClass myClass = new MyClass();
myClass.myMethod(()-> System.out.println("B1"));
myClass.myMethod(()-> System.out.println("B2"));
}
}
https://wwlee94.github.io/category/study/toby-spring/template-callback/
Mutable한 객체는 생성된 이후에 상태가 변경될 수 있는 객체이고, Immutable한 객체는 생성된 이후에 상태가 변경되지 않는 객체
public class ImmutableTest {
private final String userName;
ImmutableTest(String userName){
this.userName = userName;
}
@Override
public String toString(){
return this.userName;
}
}
결과 값은 immutable로 만들었던 userName(홍길동)은 변하지 않고, 새로운 객체 둘리가 userName에 할당된다.
Immutable 장점
Immutable 단점
객체의 값을 다른 메소드에서 변경하게 되면 코드를 예상을 빗나가는 코드가 된다.
또한 외부에서 값을 변경함으로 인해 변경에 취약해지고 OCP를 어기게 된다. 이를 막기 위해 모든 객체의 상태값 변경은 private으로 정의 하고 객체 내부에서 메소드 콜을 이용하여 이루어 져야 한다.
돈을 넣는다
1-1. 돈을 인식한다.
1-2. 돈을 받는다.
1-3. 받은 돈만큼 코스트를 올린다.
버튼을 누른다.
2-1. 버튼에 맞는 음료수가 있는지 확인한다.
버튼에 맞는 음료수를 반환한다.
3-1. 음료수를 반환한다.
3-2. 음료수를 다시 채운다.
음료수 재고를 변경한다.
3~4 반복
잔돈 반환을 누른다.
6-1. 잔돈을 확인한다.
6-2. 남은 금액을 반환한다.
https://junspapa-itdev.tistory.com/44
Spring REST Docs의 가장 큰 장점은 테스트가 성공해야 문서을 작성할 수 있기 때문에, 테스트를 강제한다.
https://tecoble.techcourse.co.kr/post/2020-08-18-spring-rest-docs/
https://cobbybb.tistory.com/16
https://jojoldu.tistory.com/226
https://tw-you.tistory.com/5
https://www.hyojae.info/7d876a64-c2a8-4e88-b007-a28e18a82f4f
화이트박스 테스트의 종류
기초 경로 검사(Base Path Testing)
제어 구조 검사
화이트 박스 테스트의 검증 기준
블랙박스 테스트의 종류
상속은 자식과 부모클래스의 결합도를 높이게 된다. 이로인해 중복을 위한 상속은 자식 클래스가 변경에 취약해지고 OCP를 위반하게 됩니다.
상속은 대표적으로 다음과 같은 단점을 가지고 있다.
https://mangkyu.tistory.com/199
oop 320p
자바의 대표적인 마커 인터페이스로는 위에서 언급한 Serializable, Cloneable 이 있다
컴파일러와 JVM은 이 마커 인터페이스를 통해 객체에 대한 추가적인 정보를 얻을 수 있게 함이 목적 => 단순한 타입 체크를 하기 위해 사용한다. 클래스에 타입을 부여하기 위한 쉬운 방법중 하나
**자바에서 직렬화는 JVM 메모리에서만 상주되어있는 객체 데이터를 그대로 영속화가 필요할 때 사용
마커 인터페이스의 장점
마커 인터페이스의 단점
public void setValue(String name, int value) {
if ("height".equals(name)) {
height = value;
}
if ("width".equals(name)) {
width = value;
}
}
height 세팅시에는 아래 코드가 필요없는 코드가 된다.
private void setHeight(int height) {
this.height = height;
}
private void setWidth(int width) {
this.width = width;
}
rest api 통신 http를 쓸수 없다면 소켓 통신을 이용한다.
GC 로그를 통해 FULL GC빈도수와 메모리 변경 사항 확인.