“구글, 자바 베꼈다“ 오라클의 증명

임민철 기자 imc@zdnet.co.kr 2012.04.21 / AM 11:31


안드로이드 운영체제(OS)와 스마트폰 생태계의 미래를 좌우할 수 있는 재판이 1주일째 열리고 있다. 자바 기술 특허를 도용당했다고 주장하는 오라클과 잘못한 게 없다는 구글의 입장이 평행선을 긋는 가운데 본격적인 심리가 진행중이다. 

 

양사는 지난해 2010년 오라클이 구글에 자바 특허 침해에 따른 손해배상을 청구하며 소송을 건 뒤부터 해당 기술의 권리와 안드로이드 소스코드의 독창성 등에 반대되는 주장을 펼치며 합의점을 찾지 못해왔다. 이에 따라 재판이 열리는 법원에 증인 신분으로 나선 양사 임원들의 기술적 공방이 계속될 것으로 예상된다. 

 

이를 위해 오라클은 지난 17일 오전 구글에 자바 특허와 저작권 관련 소송에 따른 재판이 열리자 법원에 91장짜리 슬라이드 발표를 준비해 모바일OS 안드로이드를 둘러싼 구글측의 방어 논리를 공격했다. 고의적으로 자바 API와 코드를 안드로이드에 갖다 썼는데 필요하다는 걸 알면서도 제대로 대가를 치르지 않았다는 게 골자다. 

 

이번 사건은 시간순으로 ▲썬이 자바의 전신인 오크(Oak) 프로젝트를 시작(1991년 6월) ▲후일 '104번으로 재발행된 '685번특허를 등록(1992년 12월) ▲자바 플랫폼 1.0.2 버전 공개(1996년 1월) ▲'520 특허 승인(2000년 5월) ▲'104번 특허 승인(2003년 4월) ▲앤디 루빈이 훗날 구글에 인수된 안드로이드를 시작(2003년 10월) ▲썬이 자바2 스탠다드에디션 5.0 공개(2004년 9월) ▲이어서 그에 대한 저작권 등록 인증서 발행(2004년 12월) ▲구글이 안드로이드 인수(2005년 7~8월) ▲이후 자바 기반으로 안드로이드 구현 시작(2005년 10월) ▲안드로이드 소프트웨어개발도구(SDK) 공개(2007년 11월) ▲최초 안드로이드 단말기 'HTC드림' 출시와 하께 안드로이드 플랫폼 공개(2008년 10월) ▲오라클이 썬 인수(2010년 1월) ▲구글이 안드로이드에 자바 대체기술을 쓰기보단 자바와 라이선스 협상이 필요하다는 내부 의견 수렴(2010년 8월6일) ▲오라클이 구글에 소송 제기(2010년 8월12일) 등으로 진행됐다.

 

오라클은 썬 인수에 앞서 구글 안드로이드와 스마트폰 시장에서 경쟁에 초점을 맞추지 않기로 판단(2009년 4월)했다. 

 

▲ 실제로 재판 첫날 먼저 소환된 오라클측 기술담당자는 구글이 안드로이드에 자바 기술을 도용했음을 주장하는 91장짜리 슬라이드를 동원해 자사 입장을 담당판사와 배심원들에게 이해시키려 했다.

▲ '구글 직원은 안드로이드를 구현할 때 썬에 저작권이 있는 자바 관련 자료를 참조해 했다'는 제목의 슬라이드. 지난해 8월 기록된 영상에 따르면 밥 리라는 개발자가 안드로이드 API를 구현할 때 썬 웹사이트에 자바 기술문서를 참조했다는 증언이 나온다.

▲ '안드로이드는 무균실(Clean Room)에서 구현된 게 아니다'라는 슬라이드. 자바 소스파일 java.util.arrays.java 내용과 안드로이드 소스파일 TimSort.java 내용에서 rangeCheck() 함수를 다룬 영역 코드가 너무 일치하는 점을 근거로 무단 전재가 이뤄졌다는 주장.

▲ '타임라인' 슬라이드. 자바와 안드로이드를 둘러싼 각 기업들의 움직임을 연표화. 구글이 안드로이드 안에 자바 기술을 쓰기 위해 썬 또는 오라클과 협상을 진행한 시점이 2005년8월~2006년5월, 2008년9월~11월, 2009년4월, 2010년3월~7월, 이렇게 4번 있었다.

▲ '구글은 자신들이 자바를 조각내지 않도록 해야 한다는 것을 인지하고 있었다'. 안드로이드를 만든 앤디 루빈은 래리 페이지 CEO에게 지난 2005년 10월 메일을 보내 썬의 자바 라이선스와 기술호환성키트(TCK)에 대가를 지불해야 한다는 점을 언급했다. 안드로이드용 자바가상머신(JVM)에 대한 TCK 검증을 통해 파편화를 막아야 한다는 이유에서다.

▲ '구글은 자바를 채택함으로써 안드로이드 플랫폼으로 개발자들을 끌어들일 수 있음을 알았다'는 슬라이드. 2006년9월28일자 구글 프리젠테이션 자료에 따르면 안드로이드 전략가운데 자바 개발자 영입을 플랫폼 활성화 전략으로 제시하고 있다.

▲ 소송전까지 구글은 썬의 라이선스를 얻어야 한다, 안드로이드가 자바중심으로 만들어지고 있다(2005), 기존 자바 개발자들을 통해 플랫폼을 이끈다(2006), 안드로이드는 자바와 호환 않된다, 자바 요소 걷어내야 한다(2007), 안드로이드에 자바를 기술적으로 대체하기엔 품질이 낮다(2010), 안드로이드는 거대한 이익이 된다(2011) 등 꾸준히 말을 바꿨다.

▲ '구글은 자바 사용 흔적을 숨기려 했다'는 제목의 슬라이드. 기존 자바를 도용한 혐의를 찾을 수 없도록 열심히 자바의 영향을 받은 코드들을 걷어내고 있다는 설명이 포함됐다.

▲ 지난해 10월 실적공개서 에릭 슈미트가 '안드로이드가 구글에 막대한 이익을 준다'던 언급이 인용됐다. 현재 구글 입장은 안드로이드도 중요하지만 최우선요소는 아니란 것.

▲ 오라클에 인수되기 전 썬이 자바2 스탠다드에디션 5.0버전에 대해 저작권을 인정받았음을 증명하는 문서. 즉 구글이 썬과 자사에 대해 해당 기술 지적재산권을 침해했단 뜻이다.

▲ 안드로이드 소스코드가 자바 API 디자인에 기반하고 있음을 주장하는 슬라이드.

▲ 구글이 자바API를 쓰기 위해선 그 저작권에 대한 라이선스가 필요함을 알고 있었다는 증거. 앤디 루빈이 그레그 스타인에게 지난 2006년 3월 보낸 메일 내용을 인용하고 있다.

▲ 조나단 슈워츠 전 썬 CEO가 지난 2009년 4월 래리 엘리슨 오라클 CEO에게 구글 안드로이드와 분쟁할 소지가 있음을 경고한 이메일을 보냈다는 슬라이드.

▲ 마지막 슬라이드. 구글이 오라클 자바를 안드로이드에 베껴넣어 자바 개발자 커뮤니티와 기술로 사업상 탄력을 얻으려 작심했고, 라이선스가 필요함을 알았지만 얻으려 안 했다는 요약. 오라클은 구글이 안드로이드로 법을 어긴 사실을 밝혀낼 것이라고 예고한다.


출처 - http://www.zdnet.co.kr/news/news_view.asp?artice_id=20120421023934&type=xml

Posted by linuxism
,

1. 조건문 - if, switch
  
조건문은 조건식과 문장을 포함하는 블럭{}으로 구성되어 있으며, 조건식의 연산결과에 따라 실행될 문장을 달리 할 수 있다. 
처리해야할 경우의 수가 많을 때는 switch문을 사용해서 표현할 수 있는지 살펴봐야 한다. 
[참고] 모든 switch문은 if문으로 변경이 가능하지만, 모든 if문이 switch문으로 변경 가능한 것은 아니다. 


1.1 if문

if문은 널리 사용되는 조건문이며, 기본구조는 다음과 같다. 


if (조건식) { 
      // 조건식의 연산결과가 true일 때 수행될 문장들을 적는다. 



if 다음에 오는 조건식에는 연산의 최종결과 값이 true 또는 false인 수식만을 사용할 수 있다. 조건식의 결과가 false이면, 블럭{} 내의 문장이 실행되지 않는다. 

[참고] C언어에서는 조건식의 최종결과 값으로 true 또는 false 이외의 값을 허용하지만, 자바에서는 이를 허용하지 않는다. 

if문의 변형인 if-else문의 기본 구조는 다음과 같다. if문에 else블럭을 추가한 것이다. else블럭 내의 문장들은 if문의 조건식의 결과가 false일 때 수행되는 문장들이다. 조건식의 결과에 따라 이 두 개의 블럭 중 어느 한 블럭의 내용만 수행하고 전체 if문을 벗어나게 된다. 


if (조건식) { 
      // 조건식의 연산결과가 true일 때 수행될 문장들을 적는다. 
else { 
      // 조건식의 연산결과가 false일 때 수행될 문장들을 적는다. 



if문의 또 다른 변형으로 if-else if가 있는데 기본 구조는 다음과 같다. 여러 개의 블럭 중 조건식을 만족하는 하나의 블럭만을 수행하고 if문 전체를 빠져나가게 된다. 
if-else if의 기본구조는 다음과 같다.


if (조건식1) { 
      // 조건식1의 연산결과가 true일 때 수행될 문장들을 적는다. 
else if (조건식2) { 
      // 조건식2의 연산결과가 true일 때 수행될 문장들을 적는다. 
else if (조건식3) {       // 여러 개의 else if를 사용할 수 있다. 
      // 조건식3의 연산결과가 true일 때 수행될 문장들을 적는다. 
      //... 
else {       // 보통 else블럭으로 끝나며, else블럭은 생략이 가능하다. 
      // 위의 어느 조건식도 만족하지 않을 때 수행될 문장들을 적는다. 



블럭{}은 여러 개의 문장을 하나로 묶기 위해 사용되는 것이며, 함수, 조건문, 반복문 등에 사용된다.조건문과 반복문에서는 수행될 문장이 하나인 경우 블럭을 생략할 수 있으나, 가능하면 생략 않고 사용하는 것이 바람직하다.
수행될 문장이 한 문장이라서 블럭을 생략하고 적었을 때, 나중에 새로운 문장들이 추가되면 블럭으로 문장들을 감싸 주어야 하는데 이 때 블럭을 추가하는 것을 잊기 쉽기 때문이다. 그리고, 여러 개의 if문이 중첩되어 사용되었을 때 if문과 else블럭의 관계가 의도한 바와 다르게 형성될 수도 있다. 

[예제4-1] FlowEx1.java

class FlowEx1 

      public static void main(String[] args) 
      { 
            int visitCount = 0; 
            if (visitCount < 1) { 
                  System.out.println("처음 오셨군요. 방문해 주셔서 감사합니다.") ; 
            } 
      } 

[실행결과]
처음 오셨군요. 방문해 주셔서 감사합니다. 

[예제4-2] FlowEx2.java

class FlowEx2 

      public static void main(String[] args) 
      { 
            int visitCount = 5; 
            if (visitCount < 1) {       // 5 < 1의 연산결과는 false. 
                  System.out.println("처음 오셨군요. 방문해 주셔서 감사합니다.") ; 
            } else { 
                  System.out.println("다시 방문해 주셔서 감사합니다.") ; 
           } 
           System.out.println("방문횟수는 " + ++visitCount + "번 입니다."); 
      } 

[실행결과]
다시 방문해 주셔서 감사합니다. 
방문횟수는 6번 입니다. 

[예제4-3] FlowEx3.java

class FlowEx3 

      public static void main(String[] args) 
      { 
            int score = 45; 
            char grade ='\u0000'; 

            if (score >= 90)                   // score가 90점 보다 같거나 크면 A학점(grade) 
            { 
                        grade = 'A';             
            } else if (score >=80){             // score가 80점 보다 같거나 크면 B학점(grade) 
                        grade = 'B'; 
            } else {                         // 나머지는 C학점(grade) 
                        grade = 'C'; 
      } 
            
            System.out.println("당신의 학점은 " + grade + "입니다."); 
      } 

[실행결과]
당신의 학점은 C입니다. 

if문은 삼항연산자(? :)로 바꿀 수 있는 경우가 많이 있는데, 간단한 if문의 경우 삼항연산자를 사용한 문장들로 변경하는 것을 고려해보도록 한다. 
위의 예제에서 if문 대신 삼항연산자를 사용하면 다음과 같다. 

[예제4-4] FlowEx4.java

class FlowEx4 

      public static void main(String[] args) 
      { 
            int score = 45; 
            char grade ='\u0000'; 
            grade = (score >=90) ? 'A' : ((score >=80) ? 'B' : 'C'); 
            
            System.out.println("당신의 학점은 " + grade + "입니다."); 
      } 

[실행결과]
당신의 학점은 C입니다. 

두 예제는 모두 같은 결과를 얻지만, 삼항연산자를 사용한 두 번째 예제가 보다 더 간결하다. 이렇듯 삼항연산자를 활용하면, if문을 간단히 표현할 수 있다. 



1.2 중첩 if문

if문의 블럭 내에 또 다른 if문을 사용하는 것이 가능하며, 이것을 중첩 if문이라고 부른다. 


if (조건식1) { 
      // 조건식1의 연산결과가 true일 때 수행될 문장들을 적는다. 
      if (조건식2) { 
            // 조건식1과 조건식2가 모두 true일 때 수행될 문장들 
      } else { 
            // 조건식1이 true이고, 조건식2가 false일 때 수행되는 문장들 
      } 
else { 
      // 조건식1이 false일 때 수행되는 문장들 



[예제4-5] FlowEx5.java

class FlowEx5 

      public static void main(String[] args) 
      { 
            int score = 82; 
            String grade ="";                   // 두 문자를 저장할 것이므로 String으로 했음 

           System.out.println("당신의 점수는 " + score + "입니다."); 
            if (score >= 90)                   // score가 90점 보다 같거나 크면 A학점(grade) 
            { 
                        grade = "A"
                        if ( score >= 98) { // 90점 이상 중에서도 98점 이상은 A+ 
                                    grade += "+";       // grade = grade + "+";와 같다. 
                        } else if ( score < 94)       { 
                                    grade += "-"
                        } 
            } else if (score >= 80){       // score가 80점 보다 같거나 크면 B학점(grade) 
                        grade = "B"
                        if ( score >= 88) { 
                                    grade += "+"
                        } else if ( score < 84)       { 
                                    grade += "-"
                        } 

      } else {                         // 나머지는 C학점(grade) 
                        grade = "C"
      } 
            
            System.out.println("당신의 학점은 " + grade + "입니다."); 
      } 

[실행결과]
당신의 점수는 82입니다. 
당신의 학점은 B-입니다. 

위 예제에서 보듯이, 모두 3개의 if문으로 이루어져 있으며 if문 내의 블럭에 또 다른 2개의 if문을 포함하고 있는 모습을 하고 있다. 제일 바깥쪽에 있는 if문에서 점수에 따라 학점(grade)을 결정하고, 내부의 if문에서는 학점을 더 세부적으로 나누어서 평가를 하고 그 결과를 출력한다. 



1.3 switch문


조건의 경우의 수가 많을 때는 if문 보다 switch문을 사용하는 것이 더 간결하고 알아보기 쉽다. if문은 조건식의 결과가 true, false 두 가지 밖에 없기 때문에 경우의 수가 많아 질수록 계속 else-if를 추가해야하므로 조건식이 많아져서 복잡해지고, 여러 개의 조건식을 계산해야하므로 수행시간도 많이 걸린다. 하지만, switch문의 조건식은 결과값으로 int형 범위의 정수값을 허용하므로, 하나의 조건식만 계산하면 그 결과에 따라서 해당 문장들을 수행하면 되므로 같은 기능의 if문보다 속도가 빠르다. 

하지만, switch문은 if문 보다 제약조건이 많기 때문에, 조건식을 switch문으로 작성할 수 없는 경우가 많다. 

switch문의 기본구조는 아래와 같다. 


switch (조건식) { 
      case 값1 : 
            // 조건식의 결과가 값1과 같을 경우 수행될 문장들 
            //... 
            break; 
      case 값2 : 
            // 조건식의 결과가 값2와 같을 경우 수행될 문장들 
            break; 
            //... 
      //... 
      default : 
            // 조건식의 결과와 일치하는 case문이 없을 때 수행될 문장들 
            //... 



switch문의 조건식은 연산결과가 int형 범위의 정수값이어야한다. byte, short, char, int 타입의 변수나 리터럴을 사용할 수 있다. 그리고, case문에는 반드시 상수값만을 허용한다. 변수는 허용되지 않으므로 유의해야한다. 
switch문의 조건식을 먼저 계산한 다음, 그 결과와 일치하는 case문으로 이동하다. 이동한 case문 이하에 있는 문장들을 수행하며, break문을 만나면 전체 switch문을 빠져나가게 된다. 만일 case문 아래에 break문을 생략하면, 다른 break문을 만나거나 switch문 블럭의 끝을 만날 때까지 나오는 모든 문장들을 수행한다. 

[예제4-6] FlowEx6.java

class FlowEx6 

      public static void main(String[] args) 
      { 
            // Math클래스의 random()함수를 이용해서 1~10사이의 수를 임의로 얻어낼 수 있다. 
            int score = (int)(Math.random() * 10) + 1; 

            switch(score*100) { 
                  case 100 : 
                        System.out.println("당신의 점수는 100이고, 상품은 자전거입니다.");                   
                        break; 
                  case 200 : 
                        System.out.println("당신의 점수는 200이고, 상품은 TV입니다.");                   
                        break; 
                  case 300 : 
                        System.out.println("당신의 점수는 300이고, 상품은 노트북 컴퓨터입니다.");                                     break; 
                  case 400 : 
                        System.out.println("당신의 점수는 400이고, 상품은 자동차입니다.");                   
                        break; 
                  default : 
                        System.out.println("죄송하지만 당신의 점수에 해당하는 상품이 없습니다."); 
            } 
      } 

[실행결과]
당신의 점수는 100이고, 상품은 자전거입니다.

Math클래스의 random메서드를 사용해서 1과 10사이의 임의의 수를 얻은 다음, 그 값을 score에 저장한다. score에 100을 곱한 값과 일치 하는 case문을 찾아서 이동한다. 
예를 들어서 score값이 1이라면, score * 100의 결과는 100이 되고, 첫 번째 case문인 case 100:으로 이동하여 System.out.println("당신의 점수는 100이고, 상품은 자전거입니다.")문장을 수행한 후, break문을 만나서 switch문을 빠져 나오게 된다. 
이 예제에서는 switch문의 조건식인 score * 100의 결과가, 100, 200, 300, 400인 경우에 대해서만 다루고 있기 때문에 그 외의 값인 500, 600, 700, 800, 900, 1000의 경우에는 default문 이하의 문장들 수행된다. 
[참고]random메서드를 사용했기 때문에 매번 수행할 때마다 다른 결과를 얻게 될 것이다. 

random메서드는 0.0과 1.0사이의 값 중 하나의 double값을 생성한다.(0.0은 범위에 포함되고 1.0은 포함되지 않는다.) 


0.0 <= Math.random() < 1.0 


예를 들어 1 과 10 사이의 정수를 구하기를 원한다면 아래와 같은 순서를 따르도록 한다. 

1. 각 변에 10을 곱한다. 


0.0 * 10 <= Math.random() * 10 < 1.0 * 10 
0.0 <= Math.random() * 10 < 10.0 


2. 각 변을 int형으로 변환한다. 


(int)0.0 <= (int)(Math.random() * 10) < (int)10.0 
0 <= (int)(Math.random() * 10) < 10 


지금까지는 0과 9사이의 정수 중 하나를 가질 수 있다.(0은 포함, 10은 포함 안됨) 

3. 각 변에 1을 더한다. 


0+1 <= (int)(Math.random() * 10) +1 < 10 +1 
1 <= (int)(Math.random() * 10) +1 < 11 


자, 이제는 1과 10사이의 정수 중 하나를 얻을 수 있다.(1은 포함, 11은 포함 안됨) 
[참고]순서 2와 3을 바꿔서, 각 변에 1을 먼저 더한 다음 int형으로 변환해도 같은 결과를 얻는다. 

위와 같은 방식으로 식을 변환해가며 범위를 조절하면 원하는 범위의 값을 얻을 수 있다. 주사위를 던졌을 때 나타나는 임의의 값을 얻기 위해서는 10대신 6을 곱하면 된다. 그렇게 하면 1과 6사이의 값을 얻어낼 수 있을 것이다. 

random메서드의 활용 예를 한가지 더 소개하자면, 숫자 대신 임의의 문자를 얻을 수 있도록 하는 것이다. 대문자 A~Z사이의 문자 중 임의의 한 문자를 얻도록 하려면 다음과 같이 한다. 
[참고]대문자 26개의 코드값은 65부터 90까지(A~Z)이다. 



0.0 <= Math.random() < 1.0 



1. 발생시키려는 수의 개수가 26개 이므로 각 변에 26을 곱한다. 


0.0 * 26 <= Math.random() * 26 < 1.0 * 26 
0.0 <= Math.random() * 26 < 26.0 


2. 65부터 시작하므로 각 변에 65를 더한다. 


65.0 <= Math.random() * 26 + 65 < 91.0 


3. 각 변을 문자형(char형)으로 형변환을 한다. 


(char)65.0 <= (char)(Math.random() * 26 +65) < (char)91.0 
'A' <= (char)(Math.random() * 26 +65) < '[' 


[참고] '['는 대문자 Z다음에 오는 문자.(코드값이 Z보다 1이 더 큰 문자). 

여기서 주의해야할 것은 위의 예에서와는 달리 char형으로 형변환한 후에 65를 더하면 전체 결과가 int형이 되어 버리기 때문에 char형 값을 얻을 수 없다. 그렇기 때문에 65를 먼저 더하고 그 다음에 형변환을 해야 하는 것이다. 

[예제4-7] FlowEx7.java

class FlowEx7 

      public static void main(String[] args) 
      { 
            char ch = (char)(Math.random() * 4 +65); // A, B, C, D중의 하나를 얻을 수 있다. 
            int score = 0; 
            
            switch (ch) 
            { 
                  case 'A': 
                        score = 90; 
                        break; 
                  case 'B': 
                        score = 80; 
                        break; 
                  case 'C': 
                        score = 70; 
                        break; 
                  case 'D': 
                        score = 60; 
                        break; 
            } 

            System.out.println("당신의 점수는 "+ score +"점 이상 입니다.");             
      } 

[실행결과]
당신의 점수는 80점 이상 입니다. 

[참고]Math.random()를 사용했기 때문에 실행결과가 이와 다를 수 있다. 

[예제4-8] FlowEx8.java

class FlowEx8 

      public static void main(String[] args) 
      { 
            int score = 1; 

            switch(score*100) { 
                  case 100 : 
                        System.out.println("당신의 점수는 100이고, 상품은 자전거입니다.");                   
                  case 200 : 
                        System.out.println("당신의 점수는 200이고, 상품은 TV입니다.");                   
                  case 300 : 
                        System.out.println("당신의 점수는 300이고, 상품은 노트북 컴퓨터입니다."); 
                  case 400 : 
                        System.out.println("당신의 점수는 400이고, 상품은 자동차입니다.");                   
                  default : 
                        System.out.println("죄송하지만 당신의 점수에 해당하는 상품이 없습니다."); 
            } 
      } 

[실행결과]
당신의 점수는 100이고, 상품은 자전거입니다. 
당신의 점수는 200이고, 상품은 TV입니다. 
당신의 점수는 300이고, 상품은 노트북 컴퓨터입니다. 
당신의 점수는 400이고, 상품은 자동차입니다. 
죄송하지만 당신의 점수에 해당하는 상품이 없습니다. 

위의 예제는 FlowEx6.java를 변형한 것으로 score의 값을 1로 고정시키고, switch문에 있는 break문을 모두 뺀 것이다. 
score의 값이 1이므로 switch문의 조건식 결과 값은 100이 된다. 그래서 case 100:으로 이동한 후 그 이하의 문장들을 수행한다. FlowEx6.java과는 달리, break문이 없으므로 case 100:이후부터 switch문의 블럭 끝까지 모든 문장들을 수행하게 된다. 
그렇기 때문에 매 case문마다 break문을 사용하는 것을 잊지 않도록 한다. 때로는 switch문의 이러한 성질을 이용하기도 한다. 

[예제4-9] FlowEx9.java

class FlowEx9 

      public static void main(String[] args) 
      { 
            int score = (int)(Math.random() * 10) + 1; 
            String msg =""

            score *= 100;             // score = score * 100; 

            msg = "당신의 점수는 " + score + "이고, 상품은 "
      
            switch(score) { 
                  case 1000 : 
                        msg += "자전거, ";             // msg = msg + "자전거, "; 
                  case 900 : 
                        msg += "TV, ";                   
                  case 800 : 
                        msg += "노트북 컴퓨터, ";                   
                  case 700 : 
                        msg += "자전거, ";                   
                  default : 
                        msg += "볼펜"
            } 

            System.out.println( msg + "입니다."); 
      } 

[실행결과]
당신의 점수는 800이고, 상품은 노트북 컴퓨터, 자전거, 볼펜입니다. 

Math클래스의 random()을 사용했기 때문에 위 예제의 결과는 실행할 때마다 결과가 다를 것이다. 위의 결과는 점수가 800점이 되었을 때의 결과이다. 점수(score)는 100부터 1000점까지 100점 단위의 값을 갖을 수 있는데, 높은 점수를 얻을수록 많은 상품을 주도록 되어 있다. 예를 들어 1000점을 얻은 사람은 모든 상품을 다 가질 수 있도록 되어 있다. 
이 예제에서 알 수 있듯이 switch문에 각 case문마다 반드시 break문을 사용해야하는 것은 아니며, 이 성질을 잘 이용하면 보다 간결하고 논리적으로 명확한 코드를 작성할 수 있게 된다. 

한 가지 더 간단한 예를 들어 보겠다. 아래의 코드는 전체 코드가 아닌 코드의 일부를 발췌한 것인데, 
회원제로 운영되는 인터넷 사이트에서 많이 사용될 만한 코드이다. 


switch (level) { 
      case 3 : 
            grantDelete();       // 삭제권한을 준다. 
      case 2 : 
            grantWrite();       // 쓰기권한을 준다. 
      case 1 : 
            grantRead();       // 읽기권한을 준다. 



로그인한 사용자의 등급(level)을 체크하여, 등급에 맞는 권한을 부여하는 방식으로 되어 있다. 제일 높은 등급인 3을 가진 사용자는 grantDelete, grantWrite, grantRead메서드가 모두 수행되어 읽기, 쓰기, 삭제 기능까지 모두 갖게 되고, 제일 낮은 등급인 1을 가진 사용자는 읽기 권한만을 갖게 된다. 
[참고]위의 코드는 사용자에게 읽기, 쓰기, 삭제권한을 주는 기능의 grantRead(), grantWrite(), grantDelete()가 존재한다는 가정 하에 작성되었다. 

[예제4-10] FlowEx10.java

class FlowEx10 

      public static void main(String[] args) 
      { 
            int score = 88; 
            char grade ='\u0000'; 
            switch(score) { 
                  case 100: case 99: case 98: case 97: case 96: 
                  case 95: case 94: case 93: case 92: case 91: 
                  case 90 : 
                        grade = 'A'; 
                        break; 
                  case 89: case 88: case 87: case 86: 
                  case 85: case 84: case 83: case 82: case 81: 
                  case 80 : 
                        grade = 'B'; 
                        break; 
                  case 79: case 78: case 77: case 76: 
                  case 75: case 74: case 73: case 72: case 71: 
                  case 70 : 
                        grade = 'C'; 
                        break; 
                  case 69: case 68: case 67: case 66: 
                  case 65: case 64: case 63: case 62: case 61: 
                  case 60 : 
                        grade = 'D'; 
                        break; 
                  default : 
                        grade = 'F'; 
            } // end of switch 
            System.out.println("당신의 학점은 " + grade + "입니다."); 

      }       // end of main 
}             // end of class 
[실행결과]
당신의 학점은 B입니다. 

위의 예제는 예제4-3을 switch문을 이용해서 변형한 예제이다. 위의 예제를 if문을 이용해서 구현하려면, 조건식이 4개가 필요하며, 최대 4번의 조건식을 계산해야한다. 하지만, switch문은 조건식을 1번만 계산하면 되므로 더 빠르다. 하지만, case문이 너무 많아지므로 좋지 않다.

반드시 속도를 더 향상시켜야 한다면 복잡하더라도 switch문을 선택해야겠지만, 그렇지 않다면 이런 경우 if문이 더 적합하다. 

[예제4-11] FlowEx11.java

class FlowEx11 

      public static void main(String[] args) 
      { 
            int score = 88; 
            char grade ='\u0000'; 
            switch(score/10) { 
                  case 10: 
                  case 9 : 
                        grade = 'A'; 
                        break; 
                  case 8 : 
                        grade = 'B'; 
                        break; 
                  case 7 : 
                        grade = 'C'; 
                        break; 
                  case 6 : 
                        grade = 'D'; 
                        break; 
                  default : 
                        grade = 'F'; 
            } 
            System.out.println("당신의 학점은 " + grade + "입니다."); 
      } 

[실행결과]
당신의 학점은 B입니다. 

이전 예제에 기교를 부려서 보다 간결하게 작성한 예제이다. score를 10으로 나누면, 전에 배운 것과 같이 int / int의 결과는 int이기 때문에, 예를 들어 88/10은 8.8이 아니라 8을 얻는다. 따라서 80과 89사이의 숫자들은 10으로 나누면 결과가 8이 된다. 마찬가지로 70~79사이의 숫자들은 10으로 나누면 7이 된다.

출처 - http://cafe.naver.com/javachobostudy






'Development > JavaEssential' 카테고리의 다른 글

java - 변수  (0) 2012.09.24
String과 StringBuffer의 성능에 대해서...  (0) 2012.05.02
연산자 1  (0) 2012.04.19
변수와 메서드  (0) 2012.04.18
클래스와 객체  (0) 2012.03.18
Posted by linuxism
,

Dead code

Development/Java 2012. 4. 19. 17:31


Dead code

원문 : http://www.aivosto.com/vbtips/deadcode.html

Dead code 란 필요 없는 또는 작동하지 않는 코드 조각들을 말한다. 반대말은 live, operational code 라고 할 수 있다.

dead code 를 제거하는 것만으로도 프로그램의 품질을 높일 수 있다. 여기서 말하는 품질이란 기능상의 변화가 없는 소스코드 자체의 품질 제고를 말한다. 이는 다른 프로그래머들이 코드를 읽을 때 이해를 쉽게 하고, 유지보수 비용을 낮추는 데 도움이 된다.

dead code 의 종류에는 여러 가지가 있다.

  • Dead procedure or funciton : 호출이 일어나지 않는 함수를 말한다. dead code 에서 가장 큰 비중을 차지한다. 실행파일을 쓸데 없이 차지하고, 시스템의 이해를 어렵게 하며 추후에 새로운 에러들을 야기할 수 있다. 나중에 이 함수가 사용된다 하더라도 문제는 있다. 왜 처음 만들 때는 사용되지 않았는지, 함수가 제대로 작동하기는 하는지, 더 좋은 다른 함수가 있어서 버려진 건지 알 수 없고, 테스트되지 않았기 때문에 어떤 버그를 안고 있을 지도 알 수 없다. 예전에 테스트되고 쓰였던 거라고 해도, 방치해둔 기간이 있으므로 여전히 잘 작동한다는 보장도 없다.
  • Dead variable : 선언만 해 놓고 쓰지 않는 변수는 아무데에도 쓸 모가 없다. 그저 소스코드 상의 몇 줄만 차지하고 있으니 그리 큰 문제가 안 될 거처럼 보이지만, 사실은 그렇지 않다. 누군가가 이 변수를 쓸 위험을 항상 안고 있기 때문에 버그의 씨앗이라고 할 수 있다. 또, 변수에 값을 저장만 하거나, 할당되지도 않은 채 변수에서 값을 읽어오기만 하는 것도 마찬가지다. 코드가 복잡해지면, 변수들이 dead code 인지 확인하는 일이 갈수록 어려워진다. 변수가 참조되기는 하는데, caller 들이 실행되지 않는 경우에도 dead code 의 일부로 봐야 한다.
  • Dead parameter : 쓰이지 않는 파라메터는 호출을 느리게 만든다. 이 영향이 그리 크진 않겠지만, 만약 publice interface 를 호출하거나 mashalling 을 해야 하는 경우라면 영향이 있을 수 있다. 사용되지 않는 파라메터의 나쁜 점은 caller 를 작성하는 프로그래머에게 잘못된 정보를 전달한다는 것이다. 그 때문에 프로그래머가 더 많은 실수를 할 수 있는 여지를 남겨두는 것과 같은 의미이다.
  • Dead return value : caller 들이 쓰지 않는 리턴 값을 의미한다. dead return value 는 두 가지 상황을 의미하는데 첫째로 caller 를 잘못 프로그래밍 했을 수가 있고, 둘째는 return value 자체가 아무 쓸 모가 없는 경우이다. 앞의 경우는 caller 가 함수 리턴 값이 항상 일정하리라는 잘못된 가정을 했기 때문에 발생한다. 뒤의 경우는 함수를 void 등으로 바꿔 씀으로써, 그 함수를 호출하는 프로그래머가 리턴 값을 고려하지 않아도 되게 해야 한다.
  • Dead event declaration : 발생하지 않는 이벤트를 말한다. fire 는 됐으나 핸들러가 없는 이벤트의 경우는 dead event 라고 하지 않는다.
  • Dead enumeration or constant : 쓰이지 않는 enumeration 과 상수 값들을 말한다.
  • Dead user-defined type : structure 나 record 등 프로그래머가 정의한 타입 중 쓰이지 않는 것을 말한다. 위의 많은 것들과 마찬가지로 source code reading 을 어렵게 만든다.
  • Dead class : 상동. 특히나 dead class 가 위험한 경우는 나중에 갑자기 프로그래밍에 사용될 때다. dead class 들은 테스트되지 않은 코드 들이나, 오래된 코드들을 가지고 있기 때문에 더 많은 버그를 만들어 낼 수 있다.
  • Dead interface :
  • Dead module, dead file
  • Dead control : 쓰이지 않은 UI Control 들 때문에, 다른 바이너리에 대한 dependency 를 안고 가야 될지도 모른다.
  • Dead external declaration
  • Unreachable statement : 논리적으로 결코 실행되지 않는 코드를 말한다.

Dead code 는 항상 발생할 수 있다. 쓰던 클래스를 다른 걸로 대체한다던 지, 함수가 obsolete 된다던 지 하는 등의 코드 변경이 일어날 때는 dead code 가 발생할 가능성이 늘 존재한다. 또 코드 재사용을 위해, 기존의 모듈을 복사했을 때도 필요 없는 부분까지 가져감으로써 dead code 발생 확률이 높아진다.

원문에서는 dead code 를 제거하기 좋은 시점들을 얘기해주고 있는데, 내 생각은 가장 좋은 시점은 ‘바로 지금’ 이라고 본다. dead code 를 제거하는 것이 소프트웨어 품질에 좋다는 데 동의한다면, 굳이 따로 날을 잡아 이 작업을 하기 보다 매일 조금씩 해 나가는 것이 좋지 않겠나. Refactoring to Patterns 의 저자 조슈아가 쓴 트윗으로 글을 급마무리한다.

If you are not actively looking for dead code, you are likely living with zombies.


출처 - http://www.gsong.pe.kr/wp/?p=4269

Posted by linuxism
,