- 클래스 이름은 클래스의 책임을 기술해야 한다.
- 만약, 클래스 이름을 짓기가 애매하다면 내가 클래스에 너무나도 많은 기능을 넣고 있다는 것이다.
- EX : Manager, Processor등과 같이 모호한 단어가 좋지 않은 예이다.
- 클래스 메서드가 클래스 인스턴스 변수를 더 많이 사용하도록 짜라.
- 단지, 인스턴스 변수가 많아야 한다는 소리가 아니다.
- 모든 인스턴스 변수를 각 클래스 메소드마다 쓰면 좋다. => 결국 이게 응집도가 높다는 말이다.
- 응집도를 높이려면 어떻게 해야할까?
- 변수가 아주 많은 큰함수를 찾아보자.
- 큰함수를 작은함수 단위로 쪼개보자. 그러다보면, 빼내려는 작은함수에서 변수 넷을 사용해야 한다. 인수만 많아지고 더러워지자나...
- 인수 X, 클래스 인스턴스 변수 O
- 여기까지만 보면 응집도가 낮아진다. 방금 생성한 클래스 인스턴스 변수는 일부 함수에서만 사용하기 때문이다.
- 그렇다면, 몇몇 함수와 몇몇 클래스 인스턴스 변수를 클래스로 분리하면 된다!
- 1~5번을 반복하다면, 역할에 맞는 클래스를 나눌수 있게 된다.
- 변경하기 쉬운 클래스
- SQL문자열을 만드는 sql 클래스이다.
public class Sql {
public Sql(String table, Column[] columns);
public String create();
public String insert(Object[] fields);
public String select(Column column,String pattern);
// TODO 1.update문 지원할 경우 => Sql class 수정 필요
// TODO 2.select문을 수정해야 할 경우 => Sql class 수정 필요
// FIXME => 변경해야 할 이유가 두가지 이므로 SRP 위반
private String selectWithCriteria(String criteria);
// FIXME 일부 메소드(select문)에서만 사용되는 private 함수 = SRP 위반
// FIXME 파생 클래스 별도 생성
private String columnList(Column[] columns);
private String valuesList(Object[] fields, final Column[] columns)- 하나만 수정해도 전체를 다시 테스트해야 되는 문제점 1
- SRP 위반 ( 위에 주석 설명 )[수정 후]
abstract public class Sql {
public Sql(String table,Column[] columns)
abstract public String generate()
}
public class CreateSql extends Sql{
public CreateSql(String table,Column[] columns)
@Override public String generate()
}
public class InsertSql extends Sql{
public InsertSql(String table,Column[] columns,Object[] fields)
@Override public String generate()
private String valuesList(Object[] fields, final Column[] columns)
}
public class SelectWithCriteriaSql extends Sql {
public SelectWithCriteriaSql(String table,Column[] columns, Criteria criteria)
@Override public String generate()
}
- 클래스가 극도로 단순해짐 => 코드 이해하기가 쉽고, 코드 하나를 수정했다고 다른 코드가 망가지지 않음
- update SQL 문을 추가해야 하는 경우 => 다른 코드가 망가질 일이 없음
- SRP !!!
- update SQL 문을 확장하는 경우 열려 있고, 기존 SQL문은 수정할 일이 없음 => Open-closed Principle 지원
- 변경으로부터 격리
- 코드는 변하기 마련이다..
- 우리는 변경으로부터 격리시키기 위해 인터페이스를 사용한다.
- EX : 코인 값을 받아오는 ETHTokenExchange API를 이용해서 어떤 클래스를 만든다고 가정하자.
- 직접 API를 사용하면 테스트 코드 짜기가 쉽지 않다.
public interface TokenExchange {
Money currentPrice(String coin);
}
public Portfolio {
private TokenExchange exchange;
public Portfolio(TokenExchange exchange){
this.exchange = exchange;
}public class PortfolioTest {
private FixedTokenExchange exchange;
private Portfolio portfolio;
@Before
protected void setUp() throws Exception {
exchange = new FixedTokenExchange();
exchange.fix("ETH",10000);
portfolio = new Portfolio(exchange);
}
@Test
...
}
- 결합도가 낮아짐 : 추상화로 실제 코인 가격을 얻어오는 출처나 얻어오는 방식 등과 같은 구체적인 사실을 모두 숨겨줌
'Clean code' 카테고리의 다른 글
Clean Code 4장 - 주석 (0) | 2020.01.07 |
---|---|
Clean Code 5장 - 형식 맞추기 (0) | 2020.01.07 |
리팩토링 - 12장. 복합 리팩토링 ( 절차코드를 객체로 전환 ) (0) | 2020.01.05 |
Clean Code 9장 - 단위테스트 (0) | 2018.09.18 |
Clean Code 12장 - 우수한 설계를 위한 규칙(창발성) (0) | 2018.09.13 |