Programming/기타

코드 품질올리기, 코드 설계 - 3 성숙한 클래스 만들기 (3/3)

armyost 2023. 8. 30. 23:30
728x90

1) 단일 책임 원칙 : Class가 담당하는 책임은 하나로 제한해야 한다.

책임을 대신지는 Class가 만들어지면 다른 클래스가 제대로 성장할 수 없습니다. 

중복을 제거하다보면 실수로 책무를 생각하지 않고 중복을 제거하는 경우가 있습니다. 그렇게 되면 하나로 모인 로직이 여러 책무를 담당해야 합니다. 모든 지식은 시스템 내에서 한번만 애매하지 않고 권위있게 표현되어야 합니다. 중복이 발생하더라도 중복제거 과정으로 인해 단일 책무가 위협을 받을때는 중복을 허용해야 합니다. 그리고 하나의 로직으로 봐야하는 흐름이 두 클래스에 분산되어 있는 설계는 좋은 설계라고 말할 수 없습니다.

 

2) 슈퍼클래스 의존을 탈피하기 위해서는 상속보다는 컴포지션이 좋습니다. 컴포지션이란 사용하고 싶은 클래스를 private 인스턴스 변수로 갖고 사용하는 것을 말합니다. 

 

잘못된예

class FighterPhysicalAttack extends PhysicalAttack {
	@Override
    int singleAttackDamage(){
    	return super.singleAttackDamage() + 20;
    }
    
    @Override
    int doubleAttackDamage(){
    	return super.doubleAttackDamage() + 10;
    }
}

 

올바른예

class FigherPhysicalAttack {
	private final PhysicalAttack physicalAttack;
    int singleAttackDamage() {
    	return physicalAttack.singleAttackDamage() + 20;
    }
    int doubleAttackDamage() {
    	return physicalAttack.doubleAttackDamage() + 10;   
    }
}

 

상속은 강한 결합과 로직 분산등 여러 악마를 불러들입니다. 따라서 신중하게 사용해야 합니다.

 

3) 건전성을 해치는 습관들

- 특별한 이유없이 public으로 선언하지 않습니다. 불필요한 의존성이 생길수 있습니다.

- 고정된 integer, string이 필요할때는 static final 영문이름 으로 그 의미를 표현하는 게 좋습니다.

- 의미가 다른 여러개의 값을 하나의 String 변수에 무리하게 넣으면 의미를 알기 어렵습니다. 

- null을 '무언가 갖고있지 않은상태', '무언가 설정되지 않은 상태' 가 아닙니다. null은 이러한 상태조차 없는것을 뜻합니다. 값이 없는 것도 상수로 표시하는 것이 좋습니다. 예를 들어 "EMPTY"

- null 체크는 가급적 많이 하는 것이 좋습니다. 이것을 null 을 리턴하지 않는 설계라고 합니다. 

- 예외를 catch하고 별다른 조치가 없으면안됩니다. 오류를 탐지할수 있게 하세요. 최소한 로그로 기록하고 상위 레이어 클래스로 통지하는 것이 좋습니다.