코딩 스타일 질문입니다.

lovejin0309의 이미지

안녕하세요. 코딩 스타일 질문입니다.

전 주로 아래와 같이 짜는 편입니다.

switch(code){
    code world:
           switch(key){
                  ......
           }
           break;
    code korea:
           switch(key){
                  ......
           }
           break;
    code japan:
           switch(key){
                  ......
           }
           break;
}

제 사수는 다음과 같이 짜라고 합니다.

switch(code){
    case world:
        if(..........){
            ..........
        } else if(.........) {
            .........
        } else if(.........) {
        }
        break;
    case world:
        if(..........){
            ..........
        } else if(.........) {
            .........
        } else if(.........) {
        }
        break;
   case world:
        if(..........){
            ..........
        } else if(.........) {
            .........
        } else if(.........) {
        }
        break;
 }

프로그래밍 내공이 깊지 않아서 어떤식으로 짜야 할지 고민중입니다.

전 코드를 알아보기 편해서 주로 switch()문을 사용하는 편인데, 고수님들 경험상 if()문 나열하는게 더 편한지요?

익명 사용자의 이미지

많으면 switch, 적으면 if.

그러나 가장 좋은건 상속이나 함수 포인터 등을 활용해서 switch문 쓸 일이 아예 없게 만드는 것.

cinsk의 이미지

switch(code){
    case world:
           switch(key){
                  ......
           }
           break;
    case korea:
           switch(key){
                  ......
           }
           break;
    case japan:
           switch(key){
                  ......
           }
           break;
} 

switch(code){
    case world:
        if(..........){
            ..........
        } else if(.........) {
            .........
        } else if(.........) {
        }
        break;
    case japan:
        if(..........){
            ..........
        } else if(.........) {
            .........
        } else if(.........) {
        }
        break;
   case korea:
        if(..........){
            ..........
        } else if(.........) {
            .........
        } else if(.........) {
        }
        break;
 }

를 의미한 것이라 믿고 말하겠습니다. :wink:

일단, 그런식으로 코딩하는 것은 어느 쪽이든 보기 힘듭니다. 또, 버그가 발생할 확률도 높습니다. 즉, switch statement를 nesting하거나 switch 안에 if .. else if .. 를 쓰는 것은 썩 바람직하지 않습니다. 차라리 최 상위 switch()에서 적당한 함수를 호출해서 그 함수에서 세부적인 사항을 결정하게 하던지, 만약 최 상위 switch()에 쓴 code가 일정하다면,

typedef int (*handler_t)(int key);
handler_t country_dispatch[N];

..

void
do_work(int cod, int key)
{
  int ret;
  ret = country_dispatch[cod](key);
  ...
}

이런 식으로 하는 것도 한 방법이며, 아예 flex의 state machine 형태로 할 수도 있습니다.

그래도 보여 준 코드 두 개 중 하나로 선택하라면, lovejin0309님이 쓴 코드가 더 나을 수 있다고 하겠습니다. 물론 case에서 쓸 수 있는 것은 constant expression 밖에 되지 않으니, 문자열 비교 같은 것은 할 수 없다는 단점이 있긴 합니다. 이 경우 사수가 충고한 코드를 쓸 수 밖에 없을 겁니다.

또한 실제 컴파일러는 더욱 큰 값을 쓰는게 당연하지만, 표준에 따르면 적어도 C 컴파일러는 127개의 nesting block을 이해할 줄 알아야 하며, 한 switch는 적어도 1023개의 case label을 처리할 수 있어야 합니다. 전문가가 아니라서 잘 모르겠지만, if .. else if 도 어차피 nesting block으로 봐야 할 것 같습니다.

hermian의 이미지

이란 무얼의미하는지 좀더 자세히 말씀해 주실 수 있나요?
그리고 관련 소스를 알려주시면 더더욱 고맙구요 ^^

익명 사용자의 이미지

switch 문이 if else 문보다 수행속도가 빠릅니다. 윗분이 말씀하신 것처럼 상수식밖에 쓸 수 없는 단점이 있지만, 이는 컴파일시에 Label로 만들어져 switch문에서 식 판단 후, 정의한 case문으로 곧바로 점프한다는 것입니다. 이는 if else문과 같이 여러단계의 조건비교를 하지 않으므로 switch문을 사용할 수 있는 환경이면, switch문이 더 좋은 선택이라 할 수 있습니다.

함수포인터를 이용한 추상화도 좋은 방법이겠네요.
수행속도면에서는 큰 이익이 없을 수 있지만, 프로그램의 확장성을 좋게 하므로 추후 업그레이드 시, 도움이 많이 됩니다.

revizes의 이미지

hermian wrote:
이란 무얼의미하는지 좀더 자세히 말씀해 주실 수 있나요?
그리고 관련 소스를 알려주시면 더더욱 고맙구요 ^^

flex = fast lexical analyzer generator

다 덤벼! 다 받아줄께!!

익명 사용자의 이미지

최근에 보고 있는 책이 C++ Coding Standards라는 책입니다. 101가지 룰을 다루고 있는데

0번이 Don't sweat the small stuff입니다.

적어주신 첫번째 코드와 두번째 코드가 얼마나 큰 의미가 있나요? 전체 코드를 보면 그 부분이 몇%나 담당을 합니까? 그냥 하라는데로 하시면 됩니다. 그대로 하면 뭔가 치명적인 문제점이 발생하나요?

빠르다고 말씀하시는분들 있는데 if와 switch가 전체 수행속도에 몇%나 영향을 준다고 생각하시나요? 차이 없습니다.

사소한걸로 사수와 싸우지 마세요.저건 그냥 다른거지 틀린건 아닙니다. 물론 사수가 선배로서 다름을 이해해주는 사람이라면 좋겠지만, 그게 아니라면 자신이 다름을 이해하는 수밖에 없습니다.

저걸 고집한다고 뭔가 대단한 코드가 되는건 절대로 아닙니다. 쉽게 생각하세요. 릴렉스!!

Prentice의 이미지

girneter의 이미지

Anonymous wrote:

사소한걸로 사수와 싸우지 마세요.저건 그냥 다른거지 틀린건 아닙니다. 물론 사수가 선배로서 다름을 이해해주는 사람이라면 좋겠지만, 그게 아니라면 자신이 다름을 이해하는 수밖에 없습니다.

저도 동의합니다.

coding 을 하다보면 윗사람이 분명하게 잘못 설계했거나
누가봐도 매우 잘못된 coding 스타일이라든가
싸워서 윗사람의 잘못을 고쳐야 할 경우가 생깁니다
그럴때 써먹기 위해서 카드를 아껴두시고

위의 경우처럼 사소한 경우는
걍 윗사람이 시키는대로 하세요.
다만, 함수 포인터까지는 아니라도
switch 안에 if else 나 switch 문을 또 쓰는것보다는
함수를 작성해서 넘기는게 깔끔하겠네요

개념없는 초딩들은 좋은 말로 할때 DC나 웃대가서 놀아라. 응?

shji의 이미지

윗분들 말씀대로 switch 문을 쓰지 않는 것이 깔끔하겠으나..
써야 한다면 switch나 if나 어느것을 써야 한다라고 하는 것은
너무 경직된 생각인 것 같습니다. 대신 기준을 어떤 것은 써야하고
어떤 것은 안써야 하고로 잡는것이 아니라 가독성/단순성에
목적을 둔다던가, 성능에 중점을 둔다던가로 잡아야 하지 않을까요?

hanzo69의 이미지

siwtch문 또한 라벨 상수값이 연속적으로 배치되어있지 못할 경우엔 생성되는 코드는 if-else와 같습니다.
0, 1, 2 식의 연속적 라벨 상수 배치라면 점프옵셋 테이블과 소수의 분기-점프문이 생성되지만, 12, 244, 128 같은 경우라면...
물론 c/c++의 경우고 java는 그냥 무조건 분기라 if-else와 같죠.
함수포인터를 통한 추상화는 switch문에 의해 점프옵셋이 생성되었을 경우와 같습니다. 상태 변경이 매 턴마다 일어나지 않는다면 불필요한 분기를 없앨 수 있으니까요.

그리고 그런식의 중첩 switch나 switch - if-else는 어차피 큰 차이가 없을 듯 하네요.

그냥 하라는대로 해주시길. 그런걸로 문제가 생기면 그땐 선배 찾으시고.
세상 참 살기 힘들죠^_^;

님ㅎ 즐~

죠커의 이미지

속도 문제로 switch를 쓴다면 성급한 최적화를 생각하고 있는 가능성이 큽니다. 미신을 믿지 말고 프로파일러를 믿으세요.

alsong의 이미지

위나 아래나 별반 차이 없어요.

코딩이나 변수 스타일은 사수의 형태를 따르세요.
처음엔 거부감이 느껴지는데 마음을 비우고 생각하면
별거 없습니다. 가볍게 생각하세요.

생각할수록 쓸 때 없는 짜증만 생깁니다.

그나저나 백수 언제 탈출하냐... ㅡㅡ; 배고파라.

ㅡ,.ㅡ;;의 이미지

lovejin0309 wrote:
안녕하세요. 코딩 스타일 질문입니다.

전 주로 아래와 같이 짜는 편입니다.

프로그래밍 내공이 깊지 않아서 어떤식으로 짜야 할지 고민중입니다.

전 코드를 알아보기 편해서 주로 switch()문을 사용하는 편인데, 고수님들 경험상 if()문 나열하는게 더 편한지요?

님이 말한것만 보고 어느것이 좋다 말할수 없네요..
그리고 그 상황은 매우다양합니다.

한가지 말씀드리고 싶은것은 반드시라는것은 없습니다.
옛말에 정석을 익히되 정석을 잊으라..


----------------------------------------------------------------------------

익명 사용자의 이미지

if문을 쓰느냐 switch문을 쓰느냐는 전화번호 불러 줄 때 '0'을 '영'이라고 불러 주느냐 '공'이라고 불러 주느냐와 같다고 생각됩니다.

위의 여러 분들이 말씀하신 바와 같이 중첩 switch문은 가독성이 떨어집니다. 가급적 피하는 것이 좋고 불가피하다면 같이 일하는 사람들이 많이 쓰는 스타일로 하는 것이 좋다고 생각합니다.

사수가 switch문 안에 if문을 사용해라고 할 정도면 다른 대부분의 사람들이 그렇게 쓰고 있다는 것일테니 따라 주십시오.
같이 일하는 사람들끼리 코딩 스타일이 서로 다른 것보다는 어느정도 통일하는 것이 유익합니다.

물론 아주 불합리한 것이라면야 다른 사람들을 설득시켜야 겠지만...

htna의 이미지

그냥 대강 하시길...
중첩switch를 사용하는 것이나,
중첩 if-else를 사용하는 것이나,
함수호출로 분리하는 것이나 (논란의 여지가 있을듯 하군요..)
머 별반 다른것은 없읍니다.
다른분들이 얘기하듯이 가장 중요한것은 가독성입니다.
정작 속도를 요하는 부분에서만, 문제해결을 위한 알고리즘/디자인을 고려하면, 대부분 문제가 생기지 않을것이라 생각합니다.
물론 속도가 생명인 application의 경우는 좀 생각을 해 봐야겠지만,
윈도우와 같이 이벤트에의해 프로세스가 진행되는 환경에서는, 사소한곳에 목숨걸 필요가 없습니다...

PS:
논란의 여지가 될 만한 부분에 있어서...
물론 함수로 분리하는것이 보기 좋을수도 있습니다.
하지만, 너무 자잘한 함수들이 만연하는것도 전체적인 가독성을 떨어뜨리는데 문제가 됩니다.
각 case처리를 위해서 잠시만 사용될만한 일회성 함수가 생성된다면, case 가 많아질수록 작은함수들이 많아질것입니다. 그렇다면, class를 보는 입장에서 함수가 너무 많아져서, 정작 필요한 함수를 찾기 힘들게 만들 소지가 다분합니다.
그럴경우 nest class(이게 명칭이 맞나요?)를 이용해서 함수안에 함수를 만들어 처리할 수도 있는데, 이경우는 결과적으로 주 함수가 너무 길어져서 함수간의 구분 및 가독성을 해칠수도 있습니다.
또한 그 호출함수로 필요한 파라메터 등을 넘기면서 도리어 코드가 지저분해질 수 있습니다. 그 중첩switch/if 문 안쪽에서 사용되는 정보가 경우에따라 다른경우가 많으니깐요.
역시나 함수구분이나 클래스구분은, 논리적인 기준 혹은 재활용상의 기준으로 구분하는게 대부분 좋습니다.

function(...)
{
	// 먼저 CNest를 봐야하고, 각 함수들이 어디서 사용되는지 인지해야 합니다.
	// 또한 함수에 파라메터를 넘기기 위해서 부가적인 작업/지저분해지는 부분 들이 있을수 있습니다.
	class CNest {
	public:
		static void case_a(...) {
			switch(key2) {
			case aa:
				break;
			case ab:
				break;
			default:
				break;
			}
		}
		static void case_b(...) {
			switch(key2) {
			case ba:
				break;
			case bb:
				break;
			default:
				break;
			}
		}
		static void case_c(...) {
			switch(key2) {
			case ca:
				break;
			case cb:
				break;
			default:
				break;
			}
		}
	} _nest;
	// 실제 프로그램이 진행하는 부분은 여기서부터 입니다.
	// 여기서부터 소스를 읽어나가기 시작해야 합니다.
	// 윗부분은 더미라는. ㅡ.ㅜ
	switch(key) {
	case a:
		_nest::case_a(...);
		break;
	case b:
		_nest::case_b(...);
		break;
	case c:
		_nest::case_c(...);
		break;
	default:
		...
	}
}

또한 함수포인터를 이용하는 방법도 속도개선의 방법중 하나일수 있겠지만, 그 또한 남용시 가독성을 떨어뜨리기 쉽습니다.
그 함수를 수정이나 버그픽스를 위해서 다시 검토해야 할 경우에, 그 부분을 이애하기 위해서 다른 부분 (함수포인터의 어레이의 구성 등...)을 이해해야 할 뿐만아니라, 함수호출의 경우와 마찬가지로 자잘한 함수들이 만연하게 됩니다.
또한 함수포인터의 어레이로 처리하고자 한다면, 각 case에 해당하는 함수로 넘기는 파라메터들을 통일화 해야 합니다. 경우에따라서는 아주 자잘한 정보를 여러개(많이)넘겨야 할 수도 있다는...
만약 함수포인터를 이용하고자 한다면, 리펙토링등을 이용해서 그 부분 처리를 위한 주변환경 디자인부터 정리(case정리를 위해 새로운 논리적인 객체를 정의하고 하는 과정(전반적인 과정을 이해하시리라 생각합니다.))해야 하지 않을까요? 이경우, 경우에따라서는 배보다 배꼽이 클수도 있다는... ㅡ.ㅜ

상황이란게 그때그때 다른것이니깐요.

WOW Wow!!!
Computer Science is no more about computers than astronomy is about telescopes.
-- E. W. Dijkstra

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.