Notice
Recent Posts
Recent Comments
Link
05-18 11:53
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

킹머핀의 제작 일지

부정형 함수와 긍정형 함수 중 문자열 유효성 판단에 무엇이 더 합리적일까 본문

인디 게임 개발/개발 일지

부정형 함수와 긍정형 함수 중 문자열 유효성 판단에 무엇이 더 합리적일까

KingMUffin 2022. 8. 6. 23:08

이런 사소한 문제에 발목을 잡혀 혼자 기 쪽쪽 빨리는 내가 별로다.

이것 또한 당장은 넘어가서 나중에 해결해도 될 문제인데, 내 성격 상 도저히 절대로 그냥은 넘어갈 수가 없나보다..

이미 많은 시간을 날려보냈지만.. 이제라도 블로그에 정리를 좀 해보려 한다..

진짜 사소하다..

 

문제

문자열이 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

 

나는 정말 어찌해야 좋은가..

어차피 학식 깊지 않으면 오래 고민해봤자 최선에 도달할 수 없다고..