4. Temporal Coupling
- 함수들이 순서를 지키며 호출되어야 한다.
- passing a block. 파일을 open할 때 close하지 않는 경우가 있으면 메모리 누수가 발생할 수 있는데 open, 파일 사용, close를 클래스로 만들어 접근하게 한다.
5. CQS
- side effect를 관리하는 좋은 방법
- command
- 시스템의 상태 변경 가능, side effect를 갖는다. 아무 것도 반환하지 않는다.
- query
- side effect가 없다. 계산값이나 시스템의 상태를 반환
- CQS 정의. Command Query Separation
- 상태를 변경하는 함수는 값을 반환하면 안된다.
- 값을 반환하는 함수는 상태를 변경하면 안된다.
// user를 사용하려면 로그인을 해야함.
// 로그인을 하면 user 정보를 읽어야 함.
User u = authorizer.login(userName, password);
// 로그인 따로. 유저 정보 따로.
authorizer.login(userName, password);
User u = authorizer.getUser(userName);
6. Tell Don't Ask
// 로그인을 했는지 query를 날리고 command를 날린다.
if(user.isLoggedIn())
user.execute(command);
else
authenticator.promptLogin();
// command를 날리고 execute 내부에서 에러가 나면 catch문에서 command를 날린다.
try{
user.execute(command);
}
catch(User.NotLoggedIn e){
authenticator.promptLogin();
// execute 내부에서 다 처리하도록 만든다. execute에서 command를 실행할 수 있으면 실행하고 안되면 인증을 한다.
user.execute(command, authenticator);
- 다른 객체가 무언가를 하도록 말해라. 그러나 객체가 무슨 상태인지 묻고 가져다 쓰지는 말아라.
- 정보를 가지고 있는 애한테 시키면 된다.
- CQS를 잘 준수하면 query가 없어진다.
- query를 자주 하면 query를 쓰는 곳에서 무슨 짓을 할 지 모른다. 통제 불능
7. Law of Demeter
- 함수가 시스템 전체를 알게 하면 안된다
- 개별 함수는 제한된 지식만 가져야 한다
- 객체는 요청된 기능 수행을 위해 이웃 객체에게 요청해야 한다
- 규칙
- 다음과 같은 객체의 메서드만 호출할 수 있다.
- 인자로 전달된 객체
- locally 생성한 객체
- 필드로 선언된 객체
- 전역 객체
- 이전 메서드의 호출 결과로 얻는 객체의 메서드를 호출하면 안된다.
- o.getX().get()Y.doSomething()
- 다음과 같은 객체의 메서드만 호출할 수 있다.
- ask 대신 tell하면 주변 객체들과 decouple된다.
8. early returns
- 메서드 내에서 return이 있다면 위로 가야 한다.
- 루프 중간에서 리턴하는 것은 문제
- break, 루프 중간에서 리턴은 복잡함
- 코드 동작보다 이해할 수 있게 하는 것이 중요
9. error handling
- 에러 처리 시 최대한 구체적인 이름의 exception을 사용한다.
- checked exception (반드시 예외 처리를 해야 함)
- spring은 예외 페이지 띄우는 설정이 있음..?
- 하위 클래스에서 exception이 발생하면 상위 클래스를 변경해야 하고 사용되는 모든 코드를 변경해야 함. reverse dependency 발생
- public API에서 예외 처리를 하거나, 에러가 났을 때 꼭 해줘야 하는 뭔가가 있으면 에러 처리를 한다
- exception들에 어떤 메시지를 담아야 할까?
- message가 필요 없는 게 가장 좋다.
- exception 이름만으로 명확한 의미가 되도록.
- 코드가 주석을 대신하도록 하라.
10. Special Cases
- capacity가 0인 stack
- exception 추가? 너무 많은 exceptiond은 원치 않는다
- capacity 0인 stack은 정말 오류인가?
- push -> overflow, pop -> underflow, getSize -> return 0. 잘 정의된 행위가 있다.
- Stack 클래스의 모든 메서드에 size가 0인지 판단하는 로직을 추가해야 하나??
- NullObject Pattern
- 원래 있던 클래스에서 인터페이스를 추출
11. Null is not an error
- stack이 empty일 때 StackEmpty Exception을 발생시킨다.
12. Null is a value
- 배열에서 find로 element를 찾으려고 할 때 찾지 못했다면 null 반환
13. try도 하나의 역할/기능이다.
- try 내에도 function처럼 하나의 기능만 있어야 한다.
- finally는 함수의 마지막 블럭이어야 한다. 이후 어떤 라인도 없어야 한다.
- error handling도 하나의 일이다.
'클린 코드' 카테고리의 다른 글
클린 코드 function structure (0) | 2019.12.10 |
---|---|
클린 코드 function 2 (0) | 2019.12.10 |
클린 코드 function (0) | 2019.12.10 |
클린 코드 OOP 2 (0) | 2019.12.10 |
클린 코드 소개 및 OOP (0) | 2019.12.04 |