일급 컬렉션이 뭔가요?
- 일급 컬렉션이란, Java의 콜렉션을 포함한 클래스는 다른 멤버변수가 없도록 정의한 클래스입니다.
- 사용하려는 콜렉션을 하나의 클래스로 정의해 놓으면서, 해당 콜렉션과 관련한 동작을 모아 놓을 수 있습니다.
왜 일급 컬렉션을 사용했나요?
- 사실 일급 컬렉션을 사용한 이유는 객체지향 생활체조에 명시되어 있기 때문입니다.
- 이는 일급 컬렉션을 통해 유지/보수/확장에 유리한 객체지향적 설계를 할 수 있다는 반증인데요,
- 저 역시 일급 컬렉션을 사용하면서 코드가 객체 지향적으로 변한 것을 느낄 수 있었습니다.
- 우선 일급 컬렉션의 가장 큰 장점은 "컬렉션의 상태와 하고자 하는 행위"를 한 곳에 모아둔다는 것인데요.
- 이는 곧 하나의 역할을 하는, 즉 하나의 책임을 가지는 클래스를 만들기 수월해집니다.
- 단일 책임을 가지는 객체를 설계함으로써, 클래스가 응집도가 높도록 설계할 수 있습니다.
- 왜 응집도가 높으면 객체지향적이죠?
- 하나의 클래스가 다양한 책임을 가지면 유지/보수/확장에 불리해지기 때문입니다.
- 하나의 클래스가 다양한 책임을 가진다는 것은, 요구 사항의 변화에 따라 같이 변동되야할 부분이 많다는 것을 뜻합니다.
- 또한 객체들의 협력으로 구성된 객체지향 프로그래밍에서 하나의 객체가 많은 책임을 들고있다면,
- 해당 클래스에 의존하고 있는 다른 클래스에게도 영향을 주는데요.
- 여러개의 책임을 하나의 클래스가 들고있다면, 요구사항의 변화에 따라 주구장창 많은 클래스를 고치는 결과로 이어지고,
- 이는 곧 절차지향적인 코드로 변화시킵니다.
일급 컬렉션의 장단점이 무엇인가요?
- 우선 비즈니스에 종속된 자료구조를 만듭니다.
- 주어진 조건으로만 생성할 수 있는 자료구조를 만들어 Validation을 클래스에서 처리해줄 수 있고,
- 의도에 맞게 자료구조를 제어하는 메서드를 통해 개발자 본인이 필요한 자료구조를 쉽게 만들어낼수 있습니다.
- 이는 또한, 불변성을 쉽게 보장할 수 있도록 합니다.
- 불변성을 보장함으로써, 멀티스레드 환경에서 개발자의 의도와 다르게 코드가 돌아가는 사이드 이펙트를 최소화 하는데요.
- 컬렉션의 값을 변경할 수 있는 메서드가 없는 컬렉션을 만들면 일급 컬렉션을 불변 컬렉션으로 만들 수 있습니다.
- 또한 추가적으로 컬렉션에 이름을 붙여 가독성을 높일 수 있습니다.
정적 팩토리 메서드가 뭔가요?
- 객체 생성을 담당하는 역할을 클래스 메서드로 따로 분리해 놓은 것을 뜻합니다.
생성자로 잘 객체 생성할 수 있는데 왜 필요하죠?
- 저는 클래스를 객체의 관리자라고 생각하고 접근하는 것이 좋다고 생각합니다.
- 하지만 생성자는 이를 100프로 수행해 내지 못하는 경우들이 있었습니다.
- 체스 Team 예시
- 또한 캐싱 기법을 적용하여, 매번 new를 통해 메모리 공간을 차지시켜 객체를 반환하는 것이 아닌, 필요한 객체만 반환하도록 할 수 있습니다.
- 또한 하위 자료형 객체를 반환하게 할 수도 있습니다.
정적 팩토리 메서드의 장단점이 뭔가요?
- 장점
- 우선 이름을 가집니다.
- 이는 생성자에서는 할 수 없었던 것으로 코드의 가독성을 높입니다.
- 호출시 마다 새로운 객체를 생성할 필요가 없다.
- 이것도 클래스가 객체의 관리자
- 프로그램 내에서 필요한 객체를 미리 생성해두고, 이를 반환하는 것이 가능하다.
- Java의 Integer?
- 하위 자료형 객체를 반환할 수 있음
- 하위 자료형 객체를 반환할 수 있는게 뭐가 좋죠?
- 다형성을 제공하기 때문
- 객체 생성을 캡슐화 할 수 있음
- 생성자를 클래스 메서드안으로 숨겨, 내부 상태를 외부에 드러내지 않고 객체 생성을 가능케 한다.
- 단점
- 생성자를 private으로 만들고 정적 팩토리 메서드만 있다면, 상속이 불가능
왜 객체 생성을 캡슐화 시켰을까요?
- 객체 생성을 생성자가 아닌, 정적 팩토리 메서드를 통해서 할 수 있어요.
- 저는 이렇게 함으로써, 클래스를 객체를 찍어내는 틀이 아닌, 객체의 관리자로써의 역할을 더 수행할 수 있다고 생각해요.
- 예를 들어서 체스 미션에서 Team이라는 클래스에서 Team 객체를 만들어낼때, 저는 WhiteTeam과 BlackTeam 두가지 팀만 필요했어요.
- 이를 정적 팩토리 메서드로 제공하여, 생성자를 감추어, 의도에 알맞지 않은 Team이 생성되는 것을 미연에 방지할 수 있었어요.
캡슐화는 애초에 뭘까요?
- 데이터의 은닉을 말해요.
- 생성자를 클래스의 메서드 안으로 숨기면서 내부 상태를 외부에 드러낼 필요 없이 객체 생성 인터페이스를 단순화 시킬 수 있어요.
응집도와 결합도에 대해 설명해주세요
- 응집도란, 모듈 내부의 요소들이 하나의 책임/목적을 위해 연결되어있는 집중 정도입니다.
- 결합도란, 모듈과 모듈간의 상호 의존 정도입니다.
- 독립적인 모듈이 되기 위해서는 응집도는 강하고, 결합도는 약해야 합니다.
응집도가 높고, 결합도가 낮으면 왜 좋은 객체이죠?
- 객체 지향 프로그래밍을 지향해야 하는 이유는, 대규모 소프트웨어의 유지/보수/확장에 유리하기 때문이라고 생각합니다.
- 객체 지향 프로그램은 각자의 역할과 책임이 있는 객체들이 상호 협력을 하면서 작성되어지는데요.
- 여기서 각 객체들은 각자의 역할을 충실히 해낼 의무가 있습니다.
- 응집도는 모듈 내부의 기능적인 집중 정도로써, 응집도가 높은 객체를 작성한다면, 단일 책임 원칙에 굉장히 잘 부합되는 코드를 작성할 수 있어요.
- 단일 책임 원칙이 뭐죠?
- 클래스는 단 한개의 책임을 가져야 한다는 SOLID 원칙 중의 SRP를 의미합니다.
- 하나의 객체가 하나의 책임을 들고 있음으로써, 해당 클래스의 변화로 인한 다른 객체의 수정을 최소화 할 수 있어요.
- 아무래도 하나의 객체가 여러 역할을 수행하고 있으면, 더 많은 객체와 의존관계를 맺거든요.
- 결합도는 모듈과 모듈간의 상호 의존 정도에요.
- 의존이란 것은 양면성이 있어서 하나가 바뀌면, 다른 것도 변해야할 소지가 많아져요.
- 결합도를 최대한 낮추면, 하나의 클래스의 변화가 또다른 클래스로 이어지는 것을 최소화 할 수 있어요.
SOLID원칙 중 LSP는 뭔가요?
- LSP는 리스코프 치환 원칙으로써, 정의는 "상위 타입의 객체를 하위 타입의 객체로 치환해도, 상위 타입을 사용하는 프로그램은 정상 작동 해야한다" 입니다.
LSP는 왜 중요한가요?
- LSP는 OCP를 지원하는 원칙입니다.
- 개방폐쇄 원칙을 준수함으로써, 확장에 유리한 코드를 만들 수 있었습니다.
- 기능을 사용하는 코드는 최대한 건들지 않은 상태에서, 기능들을 확장해 나갈 수 있었죠.
- OCP는 다형성과 추상화를 통해서 구현해 낼 수 있는데요.
- LSP는 다형성을 강조한 원칙입니다.
- 하위 타입의 객체를 상위 타입을 대신하여 사용함에 있어서 프로그램에서 에러가 발생하지 않도록 해야한다는 것이에요.
- 이를 만족시키기 위해,
1. 하위 타입 객체에서 오버라이딩 된 메서드는, 상위 타입 객체에서 지정한 매개변수를 받아야 한다는 것과,
2. 하위 타입 객체에서 오버라이딩 된 메서드는, 상위 타입 객체에서 지정한 리턴 값의 범위 내에 있어야 한다는 것을 준수해야 해요.
SOLID 설명해봐요
- SOLID는 객체 지향 설계의 가이드라인 역할을 해줄 수 있는 원칙이라고 생각합니다.
- 객체 지향 설계란, 유지/보수/확장에 유리한 설계를 뜻하는데요.
- SRP/ISP는 객체가 커지지 않도록,
- OCP/LSP/DIP는 변화에 유연한 코드를 작성하도록 도와줍니다.