방개
비밀번호를 잊어버리셨나요?

질문

조언 부탁드립니다.

    • 글자 크기

저번 질문들 답변들이 도움이 많이 됐기에 또 다시 도움을 얻고 싶습니다.

 

1. 변수 선언을 할 때, 오류 방지를 위한 초기화 목적의 변수 선언이랑, 함수에서도 쓰기 위한 global변수 선언에서, 저 같은 경우에

현재 Gui, Show 이전에 해당 변수들을 다 선언하고, 초기화 목적으로만 쓰는 경우는 global을 안 쓰는 식으로, 최대한 구분지어주면서 했는데,

코드를 짜다보니 매개변수때 조심만 하면 다 global로 선언하는게 어떨까 하는 생각이 들어서 의견을 듣고 싶습니다.

 

2. 또 Gui 변수 때문인지 모르겠지만 코드를 작성하다보니 global변수가 계속해서 늘어나는데 이게 정상적인 것인지 알고 싶습니다.

 

3. 변수선언을 도입부에 하다보니 중간에 수정할 때, 정확하게 어떤 의미의 변수가 쓰였는지 헷갈릴 때가 있는데, 가장 최초로 필요할 때,

하는 것도 괜찮은 방법인지 궁금합니다.

 

4. 아직 초보자의 입장에서 한글변수가 되는 오토핫키의 장점(?)을 이용해서 최대한 의미전달이 되게끔 한글변수를 사용하고 있는데, 그럼에도

변수의 갯수가 많아지다보니 의미전달이 불명확해지는 경향이 있는데 너무 광범위한 질문이지만 팁이 있는지 궁금합니다.

 

5. 함수에서 매개변수는 의미와 무관하게 최대한 간단하게 사용하고 있는데 (x, y, a) 여기에도 의미를 두는게 좋은지 궁금합니다.

 

6. 픽셀서치에서 아래와 같이 사용중인데, 색값표현이 0x000000가 같이 직관적이지 않다보니 다른 방법에 대한 조언을 얻고 싶습니다.

함수(x, y, a)

{

    PixelSearch, vx, vy, x, y, x, y, a,,Fast RGB    ;초기화면
    if(ErrorLevel = 0)

    {

        if(a = 색값)에 따라 차이를 주고 있습니다.

    }

}

 

7. 제 나름대로는 제 코드에서 혁신적으로 줄인 애증의 부분인데 쪼갤수 있는 여지가 더 있을지 궁금합니다.

반복(x, y, a)
{
	Loop
	{
		if(대기시간 < 5)
		{
			Loop
			{
				PixelSearch, vx, vy, x, y, x, y, a,,Fast RGB	;대기
				if(ErrorLevel = 0)
				{
					Sleep, 500
					if(a = 0x044670)
						return
					else if(a = 0x8C6A57)
					{
						MouseClick, Left, 717, 430
						return
					}	
					else if(a = 0xA40109 || a = 0x291710)
					{
						MouseClick, Left, %vx%, %vy%
						return
					}	
				}
				break
			}
		}
		else
		{
			오류 := 오류확인()
			return
		}
		Sleep, 1000
		대기시간++
	}
}

 

    • 글자 크기
댓글 5
  • 2020.3.14 19:04 댓글

    이런 코딩스타일에 관한 글이 너무 좋습니다.. ㅎㅎ

     

    1. (다익스트라의) 구조적 프로그래밍에서 지양하는 요소가 두가지가 있습니다. 그 두개가 goto와 전역변수입니다. 다만 저는 goto보다는 전역변수에 조금 널널한 입장을 가지고있는데, 그렇다고 해서 전역변수를 좋아하는건 아닙니다. 저는 전역변수 또한 "한 번도" 쓰지 않고 코딩이 가능하다고 생각하는 사람입니다. 요즘은 전역변수를 쓰지 않고 코딩하고있습니다. 다만, 제가 보기에도 이건 전역변수를 써주는게 매개변수로 넘겨주는것보다 깔끔하지 않나, 라는 생각이 들 때가 있는데요, 그럴땐 그냥 써주긴 합니다. 

    즉, 전역변수를 지양하는 편입니다. 최대한 안쓸려고 하고요.

     

    2. 1번의 답으로 대체합니다.

     

    3. 네. 실제로 C언어를 제외하면, 보통 사용할 변수를 한쪽에 몰아두진 않습니다. 단, 해당 변수를 사용하는 서브루틴, 함수의 위쪽마다 몰아주는 형태는 고민의 여지가 있습니다. 좋아보이긴 하는데요? 저는 딱히 이거에 신경을 써본적이 없네요.

     

    4. 한글변수는 개인적으로 지양하고 있지만, 그래도 의미전달의 면에선 확실한 강점이라고 생각합니다. 쓰는 것도 좋다고 생각해요. 다만 개인적으로, 프로그래밍이 과도하게 영어를 이용하여 발전해와서 그런진 몰라도요, 영어 변수명이 더욱 의미 전달이 명확한 경우가 많다고 봅니다.

    특히 한글 변수로는 답답하게 느껴질 정도가 있는데요, 한글은 음을 줄여봤다 음절이 그대로 남아있지만, 영어는 그렇지 않다는 점이 축약이 큰 의미를 가집니다.

    ; 예: 문자열을 가공하는 경우에 필요한 임시변수
    
    TempString .= "- " A_LoopField "`n"
    TmpStr .= "- " A_LoopField "`n"
    임시문자열 .= "- " A_LoopField "`n"
    임문 .= "- " A_LoopField "`n" ;줄이면 의미가 퇴색됩니다.
    
    ; 입력된 수가 문자열이면 true, 아니면 false를 담는 변수
    
    isString := true
    isStr := true
    문자열여부 := true
    문여 := true ;줄이면 의미가 퇴색됩니다.

    그렇다고 제가 한글 변수명을 쓰지 않았던것은 아닙니다. 일반적인 상황에선 쓰지 않지만, '모두의 한글'이라는 한글 자소와 관련된 라이브러리를 개발할 땐 라이브러리의 의미에 맞추어 한글 함수명을 사용했습니다. (변수명은 그래도 영어일거예요.)

    https://pnal.kr/pages/every-hangul

     

    5. 네, 함수의 매개변수도 함수 내에선 변수로 쓰니까 의미가 있는게 좋습니다.

     

    6. 7번 답으로 대체합니다.

     

    7. 이건 제가 여쭤보고 싶은게 많네요.

    반복(x, y, delay)
    {
    	Loop
    	{
    		if (delay < 5) ;if와 조건 사이를 띄웠고, 전역변수 "대기시간"을 delay 매개변수로 대체했습니다.
    		{
    			PixelGetColor, outputColor, x, y, RGB ; (x, y)부터 (x, y)까지이면 결국 1px만 검사하는 것이니 PixelGetColor를 사용했습니다.
    			Switch outputColor
    			{
    				case 0x044670:
    					return
    				case 0x8C6A57:
    					MouseClick, left, 717, 430
    					return
    				case 0xA40109, 0x291710:
    					MouseClick, left, x, y ;Mouseclick의 x, y 매개변수는 "표현식"이기 때문에 변수에 %기호를 안씁니다. (써도 되긴 하는데, 정석은 안씁니다.)
    					return
    			}
    		}
    		else
    			return 오류확인() ;원래 있던 오류 변수는 전역변수겠지요? 반환값으로 오류여부를 주는게 나을 것 같습니다.
    		Sleep, 1000
    		delay++
    	}
    	return 0 ;오류가 없으면 0
    }

    제가 여쭙고 싶은건 이겁니다.

    ㄱ. Loop가 두개잖아요. 안쪽 Loop는 소용이 없이 어차피 1번만 도는 Loop 아닌가요? 왜냐하면 Break를 무조건 1회전때 만나기 때문입니다. 그럼 해당 Loop가 가지는 의미가 있나요? 어차피 1회전이라 필요가 없을 것 같아 삭제하긴 했습니다.

    ㄴ. a변수가 필요한지에 대한 여부입니다. 어차피 a에 뭐가 들어오든 0x044670, 0x8C6A57, 0xA40109, 0x291710을 제외하곤 아무 동작도 하지 않게됩니다. a변수가 서치 색상인거 같은데, 서치 색상이 뭐든, 위에서 말한 4가지 색상이 성공해야 MouseClick이든 뭐든 하는 것 아닙니까? 이거에 대해선 제가 스크립트의 상황을 모르니까, 만약 필요하시다고 판단되면 다시 a변수를 사용하시면 될 것 같습니다. (다만, PixelSearch가 아니라 PixelGetColor와 if~else조건문을 이용하여 a변수를 검사하면 됩니다.)

     

    함수 자체는 더 안쪼개도 될 듯 합니다. 이외의 변경해드린 사항으론

    1. 원래 전역변수로 쓰던 "대기변수"값을 delay 매개변수로 받게 했습니다.

    2. 위에서 언급한 Loop 삭제

    3. PixelGetColor를 이용했습니다. PixelSearch 명령어를 1x1 범위에서 사용하는게 곧 PixeGetColor이기 때문입니다. 결국, x = vx, y = vy이기 때문입니다.. ㅎㅎ

    4. if, else if문 대신 일단은 Switch문을 이용했습니다. 블록 구분이 명확하여 '한 구문'이라는게 더욱 강조되는 효과를 주기 때문입니다.

    5. MouseClick에 변수를 쓸 때, 표현식이기 때문에 변수 x, y에 %기호를 없앴습니다.

    6. '오류'변수에 '오류 확인()'함수의 값을 담는 것 보니, 오류 변수에 따라 함수 바깥에서 어떤 동작을 하는 것 같습니다. 전역변수를 안쓰는 편이라 함수 반환값으로 주었습니다. 만약 반환값으로 주기 싫으시면, '오류' 변수를 함수의 byRef 매개변수로 넣으신다음에 (오류 := ""처럼 넣으시면 함수 사용하실 때 생략이 가능합니다.) global 키워드를 지워주면 함수 내에서 변경된 '오류' 변수가 함수 바깥에도 적용이 됩니다! (신기하죠?)

    반복(x, y, delay, byRef 오류 := "")
    {
        ~~~~
        오류 := 오류확인()
        return
    }
    
    => '오류' 변수는 함수 바깥에도 변경된 상태입니다!

     

    7. else의 중괄호는 한 줄이 되어서 제거했습니다.

    8. 함수에 return을 넣어주었습니다. 반환값이 필요하지 않으면 안써도 되지만, 쓰는게 정석이니까요. (반환값으로 0을 주었는데, 안 주시고 그냥 return만 쓰셔도 됩니다.)

     

     

    사실 코드 줄 수 조금 줄이는 것보단 줄 수가 늘어나도 가독성을 챙기는 것이 맞기 때문에, 극단적으로 줄을 줄이거나 하진 않았습니다.

  • 프날님께
    차랑글쓴이
    2020.3.14 19:24 댓글

    답변만 정독해도 가야할 방향성이 명확해지는 거 같아서 너무 감사드립니다. 바꿔주신 부분이 다 개선됐다고 느껴질만큼 특히 가독성부분이 엄청 마음에 들게 바뀐 것 같습니다. 비슷한 류의 다른 부분들도 대폭 수정할 수 있을거 같아요.

     

    Loop를 2번 쓴 것은 명백한 실수네요. 원래 Loop로 장면전환 하듯이 픽셀서치하던 부분이라 loop, break를 같이 쓰면서도 어색함을 못느꼈었네요. 픽셀서치를 픽셀겟컬러로 하는 것도 듣고 보니 너무 당연한건데 아예 사고의 전환을 못했었네요. 바꿔 말하면 개인적으로는 충격적이네요. 서치라는 말에 현혹되어있었습니다. 색값을 변수로 넣은 것 역시 픽셀서치에서는 색값을 넣어야 되니 넣었는데 말씀해주신대로 빼고, 스위치문으로 바꿔주신 부분이 엄청 깔끔한 것 같습니다.

     

    지금부터는 Call by value, reference를 공부해서 전역변수를 줄여보는 연습을 해야 될 것 같습니다. 감사합니다!

     

     

  • 차랑글쓴이
    2020.3.14 19:40 댓글

    코드수정에 대한 부분뿐만아니라 전반적인 코딩스타일에 대한 답변이나 변수설명해주신 부분도 궁금했던 점이 다 해소됐네요.

    답변해주신 것중에 if () 이후에 한칸을 띄워주셨는데 함수()만 붙이고 의외의 소괄호는 띄워주는 걸 권장한다고 보면 될까요?

     

    함수에서 중괄호의 마지막은 return과 같다고 들어서 함수의 종료를 알리는 return이 된 경우 모두 return을 생략했는데 알려주신 부분처럼

    마지막 괄호의 위에 넣는 함수의 끝(종료)을 알리는 return의 경우에도 적어주는게 맞는지, 답변해주신 부분이지만서도 한번더 궁금해서 여쭤봅니다..ㅠ

  • 차랑님께
    2020.3.14 22:53 댓글

    if expression (if나, else나, else if 등등 )을 제외하곤 괄호를 붙여써주는 것 같네요. 이건 저도 습관적으로 이렇게 해서 생각해본적이 없네요.. ㅎㅎ 권장이라고는 못 말씀드리지만, 저는 그렇습니다.

     

    함수의 종료를 알리는 return이라는건 없습니다. 함수는 무조건 return을 만나야 종료되기 때문입니다. 다만, 오토핫키는 return이 없이 함수가 끝나면 아무 반환값 없이 return되는 것과 동일하게 동작하도록 구현되어있습니다.

    정석을 놔두고 굳이 생략할 필요는 없다고 생각합니다. 말씀하신 함수 마지막 return은, 그 위에 쓴 return과 동일한 성격이고요, 반환값이 없으면 return만 써주시면 됩니다.

  • 프날님께
    차랑글쓴이
    2020.3.14 23:16 댓글

    넵. 확인했습니다. 감사합니다. 어설프게 잘못알고 있으니 모르느니만 못했네요.

댓글 달기

서버에 요청 중입니다. 잠시만 기다려 주십시오...