클래스 체계
클래스 내부에서는 다음과 같은 순서가 보통의 컨벤션이다.
class A {
public static 상수
private static 변수
private 인스턴스 변수
public 메서드
public 메서드에 딸린 priavet 메서드
}
변수나 메서드는 보통 캡슐화를 하여 구현을 뒤로 숨기는 것이 좋다.
우리는 항상 캡슐화를 푸는 것을 신경써야 한다.
하지만 때로는 테스트 코드에서 접근하기 위해 protected 로 선언하기도 한다.
테스트는 매우 중요하기 때문이다.
클래스는 작아야 한다
클래스의 이름은 해당 클래스의 책임을 기술한다.
좋은 클래스 이름을 짓게 되면, 해당 클래스가 맡은 책임이 분명해진다.
- Processor, Manager, Super 과 같이 모호한 단어가 이름에 있다면 여러가지 책임을 지고 있다는 뜻.
- if, and, or, but 을 사용하지 않고 25자 내로 클래스의 설명이 가능해야함
단일 책임의 원칙 (SRP)
SRP : 클래스를 변경할 이유가 단 하나여야 한다.
즉, 책임을 하나만 가진 클래스를 만들기 위해 고민해야 한다.
책임이 하나인 클래스를 설계하다보면, 재사용성이 좋은 추상화를 하기가 쉬워진다.
큰 클래스 몇개보다, 작은 클래스 여러개가 더 바람직하다. 작은 클래스는 책임이 하나고, 변경할 이유가 하나며, 다른 작은 클래스와 협력해 시스템의 동작을 수행한다. 작은 클래스는 보기 좋고, 찾기 좋으며 결과적으로 변경도 쉽다.
응집도
클래스는 인스턴스 변수의 수가 적어야 한다.
클래스의 인스턴스를 많이 사용하는 클래스의 메소드는 클래스와 응집도가 높다고 할 수 있다.
또한 모든 인스턴스를 모든 메서드가 모두 사용한다면, 그 클래스는 응집도가 높다.
클래스의 모든 메서드가 모든 인스턴스 변수를 사용하는 것은 불가능하지만, 가능한 응집도가 높은 클래스를 만들도록 노력해야 한다.
응집도가 높은 클래스라는 것은 메서드와 변수가 논리적으로 묶인다는 것이고, 하나의 책임을 위해 일하고 있다는 뜻이다.
따라서,
인스턴스 변수가 많다는 것은 책임을 많이 가진 클래스일 확률이 높다는 것이고, 클래스를 분리할 대상이 된다.
응집도를 유지하면 작은 클래스 여럿이 나온다
클래스를 쪼개는 과정
1. 큰 함수가 있다.
2. 큰 함수의 일부를 작은 함수로 빼낸다.
3. 작은 함수가 큰 함수에 정의된 지역변수를 사용한다면?
4. 인수로 넘기는 것이 아니고, 지역변수를 클래스의 인스턴스 변수로 만들면 된다.
5. 인스턴스 변수가 많아지면, 클래스를 분리한다.
물론 클래스나 메소드명을 지으면서도 클래스를 분리할 건덕지를 잡을 수 있다.
변경하기 쉬운 클래스
책의 SQL 예제에서 SRP 의 전형적인 형태를 볼 수 있다.
SQL 클래스의 경우,
1. 새로운 SQL 문을 추가하고 싶을 때
2. 기존 (예를 들면 select) 를 수정해야 할 때
이렇게 두가지의 변경할 이유가 있으므로 SRP 를 위반한다.
리펙토링 한 버전에서는 SQL 클래스를 추상 클래스로 만들고, 이를 상속한 클래스들이
각 select, create, Insert 들을 표현하고 있다.
기존 기능을 수정하고 싶다면, 해당 클래스를 수정하면 된다.
클래스가 하나의 책임을 가지게 된 것이다.
또한 새로운 기능을 추가하고 싶으면, SQL 을 상속받는 새로운 클래스를 만들면 될 것이다.
이는 OCP 의 원칙을 지키게 된다는 뜻이다.
새 기능에 개방적이고, 다른 클래스에 대해 폐쇄적이다.
또한 함수 하나하나가 짧아지면서, 가독성도 좋아졌다.
변경으로부터 격리
concrete : 구체 클래스 , abstract : 추상 클래스
이 장에서는 의존성 주입을 설명하고 있다.
인터페이스와 추상 클래스를 통해 구현에 미치는 영향을 격리한다.
이렇게 되면 여러 장점이 있다.
- 스텁 객체를 생성하여 테스트에 용이하다.
- 결합도가 낮아져서 유연성과 재사용이 높아진다.
- 결합도가 낮다는 것은 변경으로부터 잘 격리되었다는 뜻.
- DIP 를 따르는 클래스가 됨 (Dependency Inversion Principle) (상세한 구현이 아니라 추상화에 의존해야 한다.)
- 추상화를 통해 구체클래스를 숨기고 캡슐화를 실현할 수 있다.