킹머핀의 제작 일지
부정형 함수와 긍정형 함수 중 문자열 유효성 판단에 무엇이 더 합리적일까 본문
이런 사소한 문제에 발목을 잡혀 혼자 기 쪽쪽 빨리는 내가 별로다.
이것 또한 당장은 넘어가서 나중에 해결해도 될 문제인데, 내 성격 상 도저히 절대로 그냥은 넘어갈 수가 없나보다..
이미 많은 시간을 날려보냈지만.. 이제라도 블로그에 정리를 좀 해보려 한다..
진짜 사소하다..
문제
문자열이 nil이거나 비어 있는지 확인할 일이 많다. 그래서 나는 다음과 같은 함수를 정의했다.
bool IsNotValidString(string text)
{
if _UtilLogic:IsNilorEmptyString(text) then
_Log:Warning('문자열이 유효하지 않음.')
return true
end
}
그러나 반대로 nil이 아니거나 비어 있지 않은지 확인할 일도 있다. 그러면 다음과 같은 함수를 정의할 것이다.
bool IsValidString(string text)
{
if _UtilLogic:IsNilorEmptyString(text) then
--_Log:Info('문자열이 유효함.')
return true
end
}
그런데 이 때, 다음 두 가지 코드가 중복된 기능을 한다.
if _MasterLogic:IsNotValidString(text) then return end
if not _MasterLogic:IsValidString(text) then return end
한 가지 다른 점은, 로그 출력 여부다.
만약 문자열이 유효하지 않다고 출력하고 싶지 않을 때는 두 번째 코드를 사용해야 한다.
그렇다고 해도, 함수 이름만으로 로그 출력 여부를 직관적으로 알 수는 없다. (나는 이 코드를 처음 보는 사람처럼 판단했다.)
그렇다면 어떤 코드가 가장 직관적일까?
시도1
IsNotValidString을 없애고, 그 기능을 그대로 IsValidString으로 옮겨보았다.
bool isValidStirng(string text)
if not _UtilLogic:IsNilorEmptyString(text) then
--_Log:Info('문자열이 유효함.')
return true
else
_Log:Warning('문자열이 유효하지 않음.')
return false
end
그러면 문자열이 유효하지 않을 때 의도하지 않아도 로그가 출력될 수 있다.
그래서 IsValidString 함수의 매개변수로 bool printLog를 추가하면? 이 인수가 비어 있을 때는 로그를 출력하고, false일 때만 출력하지 않는 식이다.
그렇다면 인수가 true일 때는 출력해야 하나? 그건 아니다. 왜냐면 문자열이 유효하다는 로그를 출력해야 할 때 이용해야 하니까.
bool isValidStirng(string text, bool printLog)
if not _UtilLogic:IsNilorEmptyString(text) then
if printLog then -- true일 때
_Log:Info('문자열이 유효함.')
end
return true
else
if printLog == nil or printLog then -- nil이 아닌 false일 때
_Log:Warning('문자열이 유효하지 않음.')
end
return false
end
그러면 사용 용도를 떠올리기 복잡해진다. 인수가 비어 있으면 로그를 출력 안 하고, true면 유효함을 출력하고, false면 유효하지 않음을 출력하게 된다. 만약 이 복잡함을 없애려면 유효함 출력을 포기해야 한다.
bool isValidStirng(string text, bool printWarning)
if not _UtilLogic:IsNilorEmptyString(text) then
return true
else
if printWarning == nil or printWarning then
_Log:Warning('문자열이 유효하지 않음.')
end
return false
end
만약 문자열이 유효한지 확인하고 싶을 뿐이고, 유효하지 않더라도 로그를 출력할 필요가 없다면 다음과 같이 쓰면 된다.
if _MasterLogic:IsValidString(text, false) then end
보통 문자열이 유효하지 않은지 확인해햐 한다. 그렇다면 다음과 같이 써야 한다.
if not _MasterLogic:IsValidString(text) then return end
시도2
그럴 바엔 IsValidString을 없애고, IsNotValidString 함수의 매개변수로 bool printLog를 추가하면 어떨까?
bool IsNotValidString(string text, bool printLog)
if _UtilLogic:IsNilorEmptyString(text) then
if printLog == nil or printLog then
_Log:Warning('문자열이 유효하지 않음.')
end
return true
end
보통 문자열이 유효하지 않을 때 오류일 테므로, 이를 판단하는 함수는 목적을 알기 쉽다.
만약 문자열이 채워져 있는지만 알고 싶다면 다음과 같이 코드를 작성해야 할 것이다.
if not _MasterLogic:IsNotValidString(text, false) then end
부정형이 두 번 쓰였다.
문자열이 유효하지 않은지가 목적이면 결국 다음과 같이 쓰일 것이다.
if _MasterLogic:IsNotValidString(text) then return end
비교
그렇다면 두 가지 시도의 결과는 기능적으로 전혀 차이가 없다.
하지만 역시 부정형이 두 번 쓰이는 건 괴상한 일이다.
1번이 더 낫다. 그런데 여기서 끝이 아니다.
내가 고른 이 방식이 처음 코드보다 나은가?
처음 코드대로라면 어떤 함수를 사용하는지에 따라 인수로 로그 출력 여부를 정하지 않아도 되고, 직관성을 지키지 위해 문자열이 유효함을 포기하지 않아도 된다.
맞다, 내 판단 기준은 직관성이었다. 그런데 로그를 출력하지 않기 위해 추가한 인수가 직관성을 해치고 있었다.
여기서 더 고민하면 난 진짜 구제불능이다. 허비한 시간을 돌아보아라.
결론
if _MasterLogic:IsNotValidString(text) then return end
if not _MasterLogic:IsValidString(text) then return end
이게 바로 6시간 정도 고민한 결과다. 믿겨지는가?
그냥 처음 상태에서 다른 함수 하나 없애고, 매개변수 하나 추가했다가, 다시 처음으로 돌아왔다.
재결론
22년 9월, 원래 고민한 두 방식에 차이가 없다고 이 글에 결론을 내렸었는데, 막상 유효한지 확인할 일이 많아지고나서 다시 읽어 보니 부정형이 두 번 쓰이는 단점이 치명적이어서 내용을 수정했다.
6시간 고민 왜 함..? 그냥 이렇게 쓰다 보면 알게 되는데..?
게다가 직관성이 중요하다면서 왜 처음 방식대로 하자는 결론을 내린 거지?
긍정형 함수에 not을 붙이면 로그를 출력하지 않을 수 있다는 게 진심으로 직관적이냐?
그래서 지금은 이렇게 쓴다.
if _Str:IsValid(text) then return end
if _Str:IsNotValid(text) then return end
if _Str:IsNotValid(text, false) then return end
나는 정말 어찌해야 좋은가..
어차피 학식 깊지 않으면 오래 고민해봤자 최선에 도달할 수 없다고..
'인디 게임 개발 > 개발 일지' 카테고리의 다른 글
로우레벨 텍스트 프로그래밍이 적폐인 이유 (0) | 2023.07.31 |
---|---|
리듬 노트 생성 시점 (0) | 2022.09.12 |
스프레드 시트를 Construct 3 에디터로 옮기는 과정 (0) | 2021.07.03 |
습관 오답 노트 (0) | 2021.07.01 |
로그) 작성법 변경 (0) | 2021.03.22 |