본문 바로가기

경험공유

[프로그래밍 C#] 조건문 쓰지 않기 (if, switch case)

서문

프로그래머로 살면서 가장 짜증나는 상황은 고객 업체의 담당자가 일의 이해도가 떨어지거나  갑자기 현재의 일의 흐름과 다른 방향의 요구사항을 할때이다.

.. 담당자가 일의 이해도가 떨어진다는 뜻은 ..  가솔린으로 움직이는 자동차를 만들되 자동차에 주유구는 만들지 마세요.. 같은 이상한 요구를 할 수 도 있다는 뜻이다. 보통 이런 경우 미리 문제점을 파악하면 다행이지만 대게 프로그램의 구조가 어느정도 잡혀 고치기도 힘든시점에 문제가 터지기 때문에 참 많이 힘들다. 

.. 그리고 일을 진행하다 보면 본래의 의도와 조금 또는 많이 다른 요구 사항을 할때에도 있다. 이런 요구 사항은 무조건 있는것 같다. 그래도 이건 좀 덜 힘들다.

여튼, 이런 저런 경험을 하다 보니 여러가지 꼼수 같은 스킬들이 생겼고, 이 경험을 공유하고자 한다.

--- 깨달음을 주기 위한 댓글은 언제든지 환영합니다..

 

 

 

 

 

조건문 쓰지 않기

나는 되도록이면 조건문을 쓰지 않기 위해 노력한다. 

이유는, 조건문으로 비교해야 하는 항목들이 많고, 일을 진행하는 와중에 그 항목들이 유동적으로 생기거나 없어지거나 또는 항목의 인덱스 또는 이름이 자주 바뀐다면, 바쁘게 작업하는 와중에도 하나하나 찾아서 수정해줘야 하고 인덱스같은 경우는 굉장히 사소한 이유로 잘못된 조건을 선택하는 경우가 생기기 때문이다. 한마디로 수정하기도 번거롭고, 수정 후에도 확실하게 고쳐진것이 맞는지 의심을 한번쯤 하게 된다.

직관적이지 못하다는 생각을 많이 한다.

 

그래서 보통 조건문을 쓰는 상황이 되었을때, 그 조건 항목이 많을 때에는 조건문 대신 다른 방법을 선택한다.

 

 

예제를 통해 설명해보도록 하겠다.

 

 

아래는 현재 개발중인  코드 이다. 

 

대략적으로 코드를 설명 하자면 100번을 반복하면서 랜덤으로 생성된 종족을 콘솔을 통해서 알려주는 기능이 구현되어있다.

 

static void Main(string[] args)
{
	System.Random r = new System.Random(System.DateTime.Now.Millisecond);


	for (int i = 0; i < 100; i++)
	{
		int 생성 = r.Next(0, 4);

		switch (생성)
		{

			case 0:
				전사();
				break;
			case 1:
				마법사();
				break;
			case 2:
				궁수();
				break;
			case 3:
				어쎄신();
				break;
		}
	}	
}

public static void 전사()
{
	System.Console.WriteLine("Create 전사");
}

public static void 마법사()
{
	System.Console.WriteLine("Create 마법사");
}

public static void 궁수()
{
	System.Console.WriteLine("Create 궁수");
}

public static void 어쎄신()
{
	System.Console.WriteLine("Create 어쎄신");
}

 

그런데 고객사로 부터 새로운 요청이 들어왔다

  • 종족이 100개 추가 됩니다.
  • 그런데 어쩌면 추후에 약 20개 정도의 종족은 없어질 것입니다.

지금이야 종족이 4개라 switch case 를 사용했지만 100개의 종족이 추가 된다면 아래 코드는 굉장히 지루하고 길고 직관적이지 못한 코드가 될것이다. 그리고 추후에 20개 종족이 없어지게 되면 수정하기도 번거롭고 짜증난다.

 

그런데 여기서 가장 중요한건 또 어떤 요청사항이 들어올지 모른다는 것이다.

 

자 그럼.. 예측하기 힘든 요청사항들을 확실하게 대비 하기 위해서 지루하고 직관적이지 못한 switch case 문을 없애보도록 하자.

 

 

delegate

다행이 종족 생성을 위해 호출하는 함수의 구조가 모두 같다.

public static void 전사()

public static void 마법사()

public static void 궁수()

public static void 어쎄신()

 

그럼 함수를 담을 그릇을 한번 만들어 보자.

C# 에서는 함수 포인터 같은 기능을 가진 delegate 를 제공한다.

 

public delegate void CreateMethod();

 

이제 CreateMethod delegate 를 이용해  종속 생성 함수를 리스트에 담아보자

 

static System.Collections.Generic.List<CreateMethod> list = new System.Collections.Generic.List<CreateMethod>();

public static void Init()
{
	list.Add(전사);
	list.Add(마법사);
	list.Add(궁수);
	list.Add(어쎄신);
}

리스트를 선언하여 종족 생성함수를 Add 하였다.

 

이제 switch case 문을 없애보자

 

for (int i = 0; i < 100; i++)
{
	// list.Count 를 통해 동적으로 종족 숫자를 할당한다
	int 생성 = r.Next(0, list.Count);

	list[생성]();
    
	//switch (생성)
	//{

	//	case 0:
	//		전사();
	//		break;
	//	case 1:
	//		마법사();
	//		break;
	//	case 2:
	//		궁수();
	//		break;
	//	case 3:
	//		어쎄신();
	//		break;
	//}

}

switch case 문을 통해 각 case 에 배정된 함수를 호출 하는 방식에서

list의 인덱스를 통해 해당 인덱스의 공간에 저장되어 있는 함수 delegate 에 접근하여 호출하는 방식으로 변경 되었다.

이제 종족을 추가 하거나 삭제하는 것은 Init() 함수를 통해서 추가 삭제만 진행하면 된다.

깔끔하고 직관적으로 변경된듯 하다.

물론.. 어디까지나 나의 짧은 지식을 바탕으로한 개인적인 생각이다..... ㅠ

 

 

이제 전체 코드를 보자

public delegate void CreateMethod();

static System.Collections.Generic.List<CreateMethod> list = new System.Collections.Generic.List<CreateMethod>();

// 여기에서 종족 추가, 삭제 진행
public static void Init()
{
	list.Add(전사);
	list.Add(마법사);
	list.Add(궁수);
	list.Add(어쎄신);
	
    	// 새롭게 추가된 종족들
    	list.Add(엘프);
    	list.Add(드워프);
}



static void Main(string[] args)
{
	// 리스트에 종족 생성 함수 담기
	Init();
    
	System.Random r = new System.Random(System.DateTime.Now.Millisecond);


	for (int i = 0; i < 100; i++)
	{
		// list.Count 를 통해 동적으로 종족 숫자를 할당한다
		int 생성 = r.Next(0, list.Conut);

		list[생성]();

		//switch (생성)
		//{

		//	case 0:
		//		전사();
		//		break;
		//	case 1:
		//		마법사();
		//		break;
		//	case 2:
		//		궁수();
		//		break;
		//	case 3:
		//		어쎄신();
		//		break;
		//}
	}	
}

public static void 전사()
{
	System.Console.WriteLine("Create 전사");
}

public static void 마법사()
{
	System.Console.WriteLine("Create 마법사");
}

public static void 궁수()
{
	System.Console.WriteLine("Create 궁수");
}

public static void 어쎄신()
{
	System.Console.WriteLine("Create 어쎄신");
}

// 새로 추가된 종족들
public static void 엘프()
{
	System.Console.WriteLine("Create 엘프");
}

public static void 드워프()
{
	System.Console.WriteLine("Create 드워프");
}

 

 

누군가에게 조금이나마 도움이 되기를 바랍니다. 

혹시 더 좋은 의견이나 스킬 있으시면 공유 해주세요