Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

아이템5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 #5

Closed
ksy90101 opened this issue Dec 30, 2020 · 4 comments

Comments

@ksy90101
Copy link
Contributor

No description provided.

jiaekim123 added a commit to jiaekim123/book-effective-java that referenced this issue Jan 12, 2021
@ksy90101
Copy link
Contributor Author

왜 의존객체가 불변이 되면 여러 클라이언트가 의존 객체들을 공유할 수 있는지 모르겠어요 ㅠ

@hwanghe159
Copy link
Member

우선 제 생각을 말씀드리기 전에, 제가 발표 자료에서 아래와 같이 준비했는데 오해의 소지가 있어서 정정할게요!! ㅠㅠ

의존 객체 주입 패턴의 장점

  • 자원이 몇개든 의존관계가 어떻든 상관없이 잘 동작한다
  • 불변이므로 여러 클라이언트가 의존 객체들을 공유할 수 있다
  • 유연하고 테스트가 쉽다

위에서 "여러 클라이언트가 의존 객체들을 공유할 수 있다"를 의존 객체 주입 패턴의 장점인 것처럼 썼는데 위 장점은 불변객체의 장점입니다. 그래서 아래처럼 바꿨어요

의존 객체 주입 패턴의 장점

  • 자원이 몇개든 의존관계가 어떻든 상관없이 잘 동작한다
  • 유연하고 테스트가 쉽다

또한, 의존 객체가 불변이라면, 여러 클라이언트가 의존 객체들을 공유할 수 있다


아래 링크가 불변객체와 thread-safe에 대한 좋은 예시를 보여주고 있는 것 같아요.

https://devonce.tistory.com/26

위 링크에서 StringBuilder은 가변이므로 여러 쓰레드에서 접근했을 때 문제가 발생했습니다

-> 의존 객체를 공유할 수 없었습니다 (정확히 말하면 공유 자체는 가능하지만 공유하면 문제가 발생할 수 있습니다)

하지만 String은 불변이므로 여러 쓰레드에서 접근해도 문제가 발생하지 않습니다

-> 의존 객체를 공유할 수 있습니다

위의 예처럼 불변을 보장하면 여러 클라이언트가 의존 객체를 공유할 수 있습니다

@aegis1920
Copy link
Contributor

'의존 객체가 불변이라면, 여러 클라이언트가 의존 객체들을 공유할 수 있다' 의 의미를 좀 더 Deep하게 이야기해보고 싶네요. 제가 생각한 것들이 맞는지도 궁금하고요!

아래 예시를 기준으로 이야기해보겠습니다.

public class SpellChecker {

    private final Lexicon dictionary;

    public SpellChecker(Lexicon dictionary) {
         this.dictionary = Objects.requireNonNull(dictionary);
    }
    
    public boolean isValid(String word) {...}
    public List<String> suggestions(String typo) {...}
}
  1. 인스턴스 변수로 선언된 의존 객체(private final Lexicon dictionary;)는 메모리의 Heap 영역에 생성된다.
  2. 인스턴스 변수이므로 SpellChecker의 객체를 생성할 때마다 새로 생성된다.
  3. '여러 클라이언트'라는 말을 "여러 요청이 들어온다"고 해석했을 때 여러 요청마다 스레드가 생긴다.
  4. 스레드는 각자의 Stack이 생기며 메모리의HeapMethod Area 영역은 공유된다.
  5. Heap 영역은 공유되므로 여러 개의 스레드는 인스턴스 변수로 선언된 의존 객체에 접근할 수 있다.
  6. 의존 객체가 불변이 아니라면 스레드는 의존 객체에 접근해서 상태를 바꿀 수 있다.
  7. 의존 객체가 불변이라면 스레드는 의존 객체에 접근해서 필드값을 바꿀 수 없다.

즉, 의존 객체들은 Heap 영역에 있기 때문에 항상 공유가 됩니다.
의존 객체가 불변이면 공유할 수 있고, 의존 객체가 불변이 아니면 공유를 못하는 게 아닙니다.

개인적으로는 '의존 객체가 불변이라면, 여러 클라이언트가 의존 객체들을 공유할 수 있다'라는 말보다 '의존 객체가 불변이라면 여러 클라이언트가 공유하더라도 문제가 발생하지 않는다'가 맞는 것 같네요.

잘못된 내용이 있다면 피드백해주시면 감사하겠습니다.

@pkch93
Copy link
Contributor

pkch93 commented Jan 16, 2021

저도 호빈님 의견과 같은 생각인데요

Java 언어 자체에서 불변 immutable이 아니라면 의존할 수 없다 프로퍼티나 메서드에서 사용할 수 없다로 해석하면 되겠죠? 라고 강제하지 않았기 때문에 가변 mutable 객체라도 여러 객체에서 공유는 가능하다고 할 수 있을거 같네요.

다만, 가변 객체는 동시성 이슈에서 자유롭지 못하잖아요..! 멀티스레드 환경에서 여러 스레드가 하나의 객체를 동시에 다루는 경우에 데이터 무결성 보장이 쉽지 않죠. 이를 해결할 수 있는 방법 중 가장 간단한 방법이 불변 객체를 사용하는 방법이고 가장 간단하기 때문에 널리 쓰이는게 아닌가 생각을 합니다 ㅎㅎ

ksy90101 added a commit that referenced this issue Jan 16, 2021
[#5] 자원을 직접 명시하지 말고 의존 객체주입을 사용하라
ksy90101 added a commit that referenced this issue Jan 16, 2021
[#5] 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
ksy90101 added a commit that referenced this issue May 16, 2021
[#5][2기] 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants