以下是讀完 Clean code 第三章節(part 2)的筆記:
public class UserValidator {
private Cryptographer cryptographer;
public boolean checkPassword(String userName, String password) {
User user = UserGateway.findByName(userName);
if (user != User.NULL) {
String codedPhrase = user.getPhraseEncodedByPassword();
String phrase = cryptographer.decrypt(codedPhrase, password);
if ("Valid Password".equals(phrase)) {
Session.initialize();
return true;
}
}
return false;
}
}
函數就兩種功能
因此不要混和這兩種功能
看看這個函數
使用情境
如果重構成setAndCheckIfExists, 仍對if的可讀性沒提高
最好是這樣重構, command與query分離
if(attributeExists("username"))
{
setAttribute("username", "unclebob");
}
從command函數回傳錯誤碼, 是一種破壞CQS原則
比如if(deletePage(page) == E_OK), 是一種簡單的情境
但如果更深的nest
if (deletePage(page) == E_OK) {
if (registry.deleteReference(page.name) == E_OK) {
if (configKeys.deleteKey(page.name.makeKey()) == E_OK) {
logger.log("page deleted");
} else {
logger.log("configKey not deleted");
}
} else {
logger.log("deleteReference from registry failed");
}
} else {
logger.log("delete failed");
return E_ERROR;
}
這樣是強迫呼叫者都得立刻處理錯誤碼
透過拋出exception, 簡化錯誤處理
try
{
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}
catch (Exception e)
{
logger.log(e.getMessage());
}
public void delete(Page page) {
try {
deletePageAndAllReferences(page);
} catch (Exception e) {
logError(e);
}
}
private void deletePageAndAllReferences(Page page) throws Exception {
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}
private void logError(Exception e) {
logger.log(e.getMessage());
}
public enum Error {
OK,
INVALID,
NO_SUCH,LOCKED,
OUT_OF_RESOURCES,
WAITING_FOR_EVENT;
}