클린코드에 나오는 코드를 Dart로 수정해보았습니다
중첩 구조가 생길만큼 함수가 커져서는 안된다. 들여쓰기가 1단, 2단 수준이어야 한다. 그렇다면 함수는 얼마나 작아야 하는가?
함수는 한 가지를 해야 한다. 그 한 가지를 잘 해야 한다. 그 한 가지만을 해야 한다.
본질적으로 switch문은 N가지를 처리한다. switch문을 피하기는 어렵지만 다형성을 이용해서 각 switch문을 저차원 클래스에 숨기고 반복하지 않는 방법은 있다.
abstract class Employee {
bool isPayday();
Money calculatePay();
void deliverPay(Money pay);
}
abstract class EmployeeFactory {
Employee makeEmployee(EmployeeRecord r);
}
class EmployeeFactoryImpl implements EmployeeFactory {
@override
Employee makeEmployee(EmployeeRecord r) {
switch (r.type) {
case EmployeeType.COMMISSIONED:
return CommissionedEmployee(r);
case EmployeeType.HOURLY:
return HourlyEmployee(r);
case EmployeeType.SALARIED:
return SalariedEmployee(r);
default:
throw InvalidEmployeeType(r.type);
}
}
}
다음과 같은 경우에 많이 사용한다. 이 경우가 아니면 단항 함수는 가급적 피한다.
인수에 질문을 던지는 경우
boolean fileExists("MyFile")
인수를 뭔가로 변환해 결과를 반환하는 경우
InputStream fileOpen("MyFile")
: String형 파일 이름을 InputStream으로 변환한다 (Java)
이벤트
입력 인수만 있고 출력 인수는 없다. 프로그램은 함수 호출을 이벤트로 해석해 시스템 상태를 바꾼다
passwordAttemptFailedNtiles(int attempts)
쓰지마라. 함수로 bool 값을 넘기는 것은 함수가 한꺼번에 여러 가지를 처리한다고 대놓고 공표하는 셈이다. (Flag가 참이면 이거 하고, 거짓이면 저거 해라)
인수의 순서를 헷갈릴 가능성이 크니 사용하지 말 것을 강조하고 있는데, 여전히 복잡하지만 named parameter를 사용하면 이런 문제는 없지 않을까?
단항 함수는 함수와 인수가 동사/명사 쌍을 이뤄야 한다
write(name)
writeField(name)
이 더 낫다함수 이름에 인수 이름을 넣으면 인수 순서를 기억할 필요가 없어진다
assertExpectedEqualsActual(expected, actual)
그러니깐.. Dart에서는 named parameter를 쓰라고
부수 효과(Side Effects), 즉 부작용(副作用)이다. 아래 Dart 코드는 userName과 password를 확인해서 올바르면 true를 반환하는데, 부수 효과로 Session.initialize()를 호출하고 있다. 함수 이름은 checkPassword인데 세션을 초기화하고 있으므로 사용자 인증 과정에서 기존 세션 정보를 지워버릴 위험이 있다.
class UserValidator {
final Cryptographer cryptographer;
UserValidator(this.cryptographer);
bool checkPassword(String userName, String password) {
User user = UserGateway.findByName(userName);
if (user != User.nullUser) {
String codedPhrase = user.getPhraseEncodedByPassword();
String phrase = cryptographer.decrypt(codedPhrase, password);
if (phrase == "Valid Password") {
Session.initialize();
return true;
}
}
return false;
}
}
함수는 뭔가를 수행하거나 뭔가에 답하거나 둘 중 하나만 해야 한다. 둘 다 하면 안된다
원래 함수는 하나만 하는 거라며? 굳이 안써도 되는 원칙아닌가 싶음
void delete(Page page) {
try {
deletePageAndAllReferences(page);
} catch (e) {
logError(e);
}
}
void deletePageAndAllReferences(Page page) {
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}
void logError(e) {
logger.log(e.toString());
}
먼저 쓰고 읽기 좋게 다듬는다. 처음에는 대충 쓰고 이름을 바꾸고 중복을 제거한다. 메서드를 줄이고 순서를 바꾼다. 이 모든 과정에서 단위 테스트를 통과해야 한다.