https://www.youtube.com/watch?v=cgiDv1XFWsk&list=PLagTY0ogyVkIl2kTr08w-4MLGYWJz7lNK&index=5
🧐 CQS
Command 와 Query는 구별되어야 한다!!
Command ( 상태를 변경 )
- 시스템의 상태 변경 가능
- Side Effect를 갖는다.
- 아무것도 반환하지 않는다. void형이다.
- Exception은 반환하더라도 어떤 값을 반환하면 안된다!
Query ( 값을 반환 )
- Side Effect가 없다.
- 계산값이나 시스템의 상태를 반환한다.
예시 1
// CQS가 적용안된 상황
User u = authorizer.login(userName, password);
// CQS 적용
authorizer.login(userName, password);
User u = authorizer.getUser(userName);
예시 2
// CQS는 C와 Q를 함께 사용하지 않도록 해라 아래 예제는 별로
// 아래 예제는 Q,C,C 로 나열되어있다.
if(user.isLoggedIn())
user.execute(command);
else
authentication.promptLogin();
/*
Better
예외를 사용하는 것이 더 나아보인다.
*/
try{
// C는 예외는 발생시켜도 되므로
user.execute(command);
}catch(User.NotLoggedIn e){
annuciator.promptLogin();
}
/*
More Better
user 객체가 모든 것을 처리하도록 하는 것이 더 나아보인다.
*/
user.execute(command, annuciator);
- 로그인 여부 상태는 user 객체에 속한다.
- 왜 user 상태를 가져다가, user를 대신해서 결정을 하는것인가
- user가 해당 행위를 수행하는 것이 맞다.
Tell Don't Ask
- 다른 객체가 무엇인가를 하도록 하지 말아라.
- 다른 객체의 상태를 가져다가 무엇인가를 하려하지 마라.
위의 규칙들을 준수하다보면, Query 가 많이 필요없어지고,
이는 매우 좋은 것이다.
Q는 곧 out of control되는 경향이 있다.
내 상태를 다른 객체에 맡기면 컨트롤하기 어렵다.
내 상태는 내 안에서 변경!!!!!!
// Long chain of function BAD!
O.getX()
.getY()
.getZ()
.doSomething();
// GOOD
o.DoSomething();
위에 처럼 바꾸게 되면, 일단 테스트할때도, 디펜던시처리가 줄어들어서 훨씬 편하게 된다. 그리고 최종적으로 처리되기까지 요청이 전파된다.
Law of Demeter
하나의 함수가 전체 시스템의 객체들 간의 네비게이션을 아는 것은 잘못된 설계이다.
O.getX()
.getY()
.getZ()
.doSomething();
/*
o는 X를 갖는다.
X는 Y를 갖는다.
Y는 Z를 갖는다.
Z는 doSomething()를 할 수 있다.
*/
한 라인의 코드가 알아야 하는 것으로 너무 방대한 지식이고,
함수가 시스템에 너무 많은 의존성을 갖는다.
함수가 시스템의 전체를 알게하면 안된다.
개별 함수는 아주 제한된 지식만 가져야 한다.
객체는 요청한 기능 수행을 위해 이웃 객체에게 요청해야 한다.
Early Returns
private boolean nameIsValxxxx{
if(name.equals(""))
return true;
if(WikiWordWidget.xxx)
return true;
return false;
}
early return 이나 guarded return 은 허용된다.
대신 이런 것은 맨 위에 위치하는 것이 좋다.
guarded return 이란 예를 들어, if
else
구문이 있을 때, if에서 다 로직을 수행하고 else에서 return 을 하는 경우가 있는데 반대로 해야한다는 것이다.
// 이게 맞다!!!!!!
if(~~~){
return false;
}else{
/*
Logic
*/
}
루프의 중간에서 리턴하는 것은 문제가 있다.
break, 루프 중간에서의 return은 loop을 복잡하게 한다.
코드가 동작하도록 하는 것보다 이해할 수 있게하는 것이 더 중요하다.
Error Handling
Stack 처리시,
예외 처리를 위해 pop은 null을 반환하고, push는 false를 반환할 수 있다
→ 이 보다는 Exception을 발생시키는 것이 좋다. 대신 이때, Exception의 이름은 최대한 구체적이어야 한다. ex) Stack.Overflow
Exception에는 Message가 필요 없는 것이 가장 좋다.
Exception의 이름을 정확하게 지어서 이름으로 의미가 전달되도록 하는 것이 베스트!
Try 도 하나의 역할/기능이다.
- 함수 내에서 try 문장이 있다면 try 문장의 변수선언을 제외하고는 첫번째 문장이어야 한다.
- try 블럭 내에는 한 문장(함수 호출)만 있어야 한다.
- finally 가 함수의 마지막 블럭이여야 한다. 이후에 어떤 라인도 없어야 한다.
- 함수는 하나의 일만 해야한다.
- error handling은 하나의 일이다.
'강의내용 정리 > Clean Coders - 백명석' 카테고리의 다른 글
4. Function Part2 (0) | 2021.08.12 |
---|---|
3. Function (0) | 2021.08.11 |
2. OOP Part2 (0) | 2021.08.11 |
1. 소개 및 OOP (0) | 2021.08.11 |