안녕하세요.
이번에는 가독성 떨어지는 코드들 보면서 빡친 것도 있고 이참에 생각하는 것들을 정리해서 적어보자 싶어서 적어보게 되었습니다.
이번 글은 제 개인적인 의견이 많이 담겨있습니다.
프로젝트 혹은 개인에 의해 많이 다를 수 있습니다.
제 글은 참고만 해주시면 감사하겠습니다.
1. 이름 관련 하지 말아야 할 것들
변수명, 함수명, 클래스명 등등 각각 많인 규칙들이 있는데, 과거에 많은 규칙들은 툴에서 지원하지 못해서 개발 편의를 위해 이름에 넣어서 사용한 것들이 많았습니다.
이번에는 이런 것들을 말하고자 하는 것은 아니고 단순히 가독성을 해치거나 협업에 방해가 되는 코드들을 소개하고 하지 말아야 할 이유를 생각해보고자 합니다.
1) 의미없는 이름
이건 두 말할 것도 없고 이유를 설명할 필요도 없다고 봅니다.
아무런 의미 없이 짓는 건 개인적으로는 for문에 들어가는 i, j 까지라고 생각합니다.
2) 모호한 이름
제가 최근이 이걸로 어질어질했었는데요...
일단 예제 코드로 설명드리겠습니다.
public void SendUseMagic(int skillID) { ... }
public void Magic(int skillID) { ... }
public void UseMagic(int skillID) { ... }
public void OnRecvMagic(int skillID) { ... }
이런 이름의 함수들이 있었습니다. 여러분들은 한눈에 어떤 함수인지 알아보시겠어요?
SendUseMagic → [Server] → OnRecvMagic → Magic → UseMagic
사실 이런 식으로 동작하는 코드였습니다.
public void SendUseMagic(int skillID) { ... }
public void OnRecvMagic(int skillID) { ... }
public void ProcessUseMagic(int skillID) { ... }
SendUseMagic → OnRecvUseMagic(이전 OnRecvMagic) → ProcessUseMagic(이전 Magic + 이전 UseMagic)
이렇게 동작하도록 이름만 바꾸어봤습니다.
물론 여러분들은 실력 있는 프로그래머분들이니 참조를 찾아들어가거나 디버깅을 해보면 금방 아실 수 있지만, 그 시간을 들여야 하는 것이 여러모로 손해라고 생각합니다.
3) 약자로 된 이름
이름이 길어지는 게 싫어서 약자로 이름을 짓는 분들이 상당히 많은데요, 그 덕분에 모호하거나 알 수 없는 이름이 되어버리는 경우가 많습니다.
예로 들면 누군가 KakaoTalkPlugin을 줄여서 KTPlugin이라고 적었다고 합시다.
이게 누군가에게는 통신사 KT의 Plugin으로 인지될 수 있는 모호함이 있을 수 있습니다.
물론 이런 모호함을 고려하고 지었다면 이런 상황은 안 나오겠지만, 그렇게까지 사람이 완벽하지 않다고 봅니다.
또, 프로젝트 내 구성원들과 합의되지 않은 경우 A작업자는 줄여서 쓰고 B작업자는 풀네임으로 사용하게 되는 경우가 발생하는데, 이런 경우 각 작업자들이 검색을 하는데 몇 단계를 더 거쳐야 하는 단점 또한 존재합니다.
개인적으로 줄여도 되는 건 두 가지라고 생각합니다.
- 일반적으로 줄여서 사용하는 것들. (예로 들면 게임에서 일반적으로 쓰이는 HP, MP, EXP.. 등등)
- 프로젝트 내 구성원들과 합의한 약자.
2. 함수 이름 짓는 요령(?)
1) 함수 이름
기본적으로 영어 문법을 따라서 짓는 게 여러모로 도움이 된다고 생각합니다.
물론 제가 이런 코드에 익숙해진 탓도 있고 이미 많은 코드들이 이런 식으로 짜여 있어서 그런 것도 있습니다.
//아이템의 이름 반환
public string GetItemName(int itemID) { ... }
//아이템의 이름 반환 (Unique ID로 참조)
public string GetItemNameByUID(long itemUID) { ... }
//아이템의 이름 반환 (색상 태그 포함)
public string GetItemNameWithColorTag(int itemID) { ... }
//아이템 이름 반환 (공백 제외)
public string GetItemNameWithoutWhiteSpace(int itemID) { ... }
동사 + 목적어 (+ 수식어, 수식어, 수식어....)
제가 사용하는 규칙입니다.
물론 영어 문법과 완전히 동일하진 않겠지만(?) 어느 정도 영어 문법을 따라가고 있습니다.
2) 역할과 대상 분리
이 방법은 제가 주로 사용하는 방법입니다.
예로 들어 확인 버튼의 콜백을 받는 함수를 선언했다고 합시다.
일반적으로 카멜표기법/파스칼표기법으로는 OnClickConfirm라고 할 것이고, 스네이크표기법으로는 on_click_confirm으로 될 겁니다(?) (사실 저도 정확한 건 모릅니다.)
저는 OnClick이라는 역할과 Confirm이라는 대상을 언더바(_)로 분리해서 OnClick_Confirm이렇게 사용하는 편입니다.
당장 이 함수 하나로는 의미가 없지만, 함수가 늘어났을 경우 역할과 대상이 분리되면 코드가 한눈에 들어오게 됩니다.
public void OnClickTabItemType() { ... }
public void OnClickButtonConfirm() { ... }
public void OnClickButtonCancel() { ... }
public void OnClickButtonReset() { ... }
public void OnClickSlotItem() { ... }
public void OnClickTab_ItemType() { ... }
public void OnClickButton_Confirm() { ... }
public void OnClickButton_Cancel() { ... }
public void OnClickButton_Reset() { ... }
public void OnClickSlot_Item() { ... }
어디까지나 가독성이라는 부분은 개인차가 있는 부분이라 글을 읽으시는 분들이 좀 더 편하신 방법을 선택하시거나 찾아서 쓰시면 될 거라 생각합니다.
3. 코드 그룹핑(?)
개인적으로 같은 역할을 하는 변수, 함수들은 한 곳에 모아서 선언해주는 것이 가독성면에서 좋다고 생각하는데, 생각보다 많은 분들이 그냥 코드 재일 아래에 한 줄씩 추가해서 결국 나중에 코드를 다시 보게 되면 의식의 흐름대로 추가되어 읽기 힘든 코드가 되어버린걸 자주 보았습니다.
우리가 누군가와 대화할 때도 A, B, C를 의식의 흐름대로 ACBABBBCCA.. 이런 순서로 말하는 사람과, AAAABBBBCCCC 이런 순서로 말하는 사람 중 후자 쪽이 더욱 대화하기 편합니다.
(어디까지나 정보전달의 관점입니다. 개인적으로 사적인 대화는 전자가 재밌습니다 ^^)
저는 누군가에게 설명해야 하는 글쓰기도 비슷하고 코드 역시 비슷하다고 생각합니다.
1) 기본 규칙
규칙은 단순합니다. 같은 역할 혹은 같은 콘텐츠의 멤버들끼리 모아주는 것입니다.
//UI 갱신 함수들
public void UpdateUI();
protected void UpdateUI_ButtonState() { ... }
protected void UpdateUI_UserName() { ... }
protected void UpdateUI_CharacterModel() { ... }
protected void UpdateUI_CharacterStats() { ... }
//버튼 콜백 함수들
public void OnClickButton_Confirm() { ... }
public void OnClickButton_OpenLevevlUpPopup() { ... }
제가 생각하기에 나쁜 예제들을 회사코드에서만 봐왔고 제가 해당 코드를 직접 만들려니 너무 마음이 아파서 못하겠습니다...
2) #region
코드가 길어질 경우 단순히 모아주는 것 만드로는 힘들 수 있는데, 그럴 경우 region로 구분을 해주면 좋습니다.
사용법은 간단합니다.
#region UI 갱신 함수들
public void UpdateUI();
protected void UpdateUI_ButtonState() { ... }
protected void UpdateUI_UserName() { ... }
protected void UpdateUI_CharacterModel() { ... }
protected void UpdateUI_CharacterStats() { ... }
#endregion
#region 버튼 콜백 함수들
public void OnClickButton_Confirm() { ... }
public void OnClickButton_OpenLevevlUpPopup() { ... }
#endregion
이런 식으로 #region ~ #endregion으로 묶어줍니다.
그러면 아래 사진처럼 Visual Studio에서는 폴딩이 가능해지고, 단축키로 region도 같이 접고 펴면서 코드를 찾기 편하게 이용할 수 있습니다.
마무리.
그냥 제 나름대로 코드 정리에 관해 제 의식의 흐름대로 적어봤습니다.
제가 꼭 옳은 방법은 아니지만 그냥 생각할 수 있는 기회가 되었으면 하네요.
긴 글 읽어주셔서 감사합니다.