2015년 1월 25일 일요일

[algospot] 알고스팟 BOARD COVER [자바]








문제

03.png
H*W 크기의 게임판이 있습니다. 게임판은 검은 칸과 흰 칸으로 구성된 격자 모양을 하고 있는데 이 중 모든 흰 칸을 3칸짜리 L자 모양의 블록으로 덮고 싶습니다. 이 때 블록들은 자유롭게 회전해서 놓을 수 있지만, 서로 겹치거나, 검은 칸을 덮거나, 게임판 밖으로 나가서는 안 됩니다. 위 그림은 한 게임판과 이를 덮는 방법을 보여줍니다.
게임판이 주어질 때 이를 덮는 방법의 수를 계산하는 프로그램을 작성하세요.

입력

력의 첫 줄에는 테스트 케이스의 수 C (C <= 30) 가 주어집니다. 각 테스트 케이스의 첫 줄에는 2개의 정수 H, W (1 <= H,W <= 20) 가 주어집니다. 다음 H 줄에 각 W 글자로 게임판의 모양이 주어집니다. # 은 검은 칸, . 는 흰 칸을 나타냅니다. 입력에 주어지는 게임판에 있는 흰 칸의 수는 50 을 넘지 않습니다.

출력

한 줄에 하나씩 흰 칸을 모두 덮는 방법의 수를 출력합니다.

예제 입력

3 
3 7 
#.....# 
#.....# 
##...## 
3 7 
#.....# 
#.....# 
##..### 
8 10 
########## 
#........# 
#........# 
#........# 
#........# 
#........# 
#........# 
########## 

예제 출력

0
2
1514


풀이 방법

메소드 설명.


  •  isPossibleCase(가능한 케이스 판단 메소드)  ; L 모양이 2차배열에 들어갈 수 있는지 없는지 판단. 여기서 지역변수 int x는 case를 구분하기 위해 임의로 값을 넣어준것임.  (인덱스의 값이"." 일 때만 가능)
  •  paintCaseA,B,C,D (가능하다면 케이스의 값을 벼꿔주는 메소드) : 4가지 경우에 있어서 가능한 경우가 있다면  인덱스 값이 " . "이었던 칸을 "#"으로 채워준다.
  • nextRowCol (채워졌다면 다음 행, 열로 이동하고 callback 재귀함수수를 호출하거나 이동할 필요가 없다면 return하는 메소드) : checkArray를 호출해 return 값이 true라면 Result(경우의 수)값을 +1 시켜준다. 
  • checkArray : 배열의 값이 모두 "#"으로 바뀌었는지 판단하는 메소드
  • callback : 이 문제에 핵심이라고 할 수 있는 재귀함수. 


이해하기 어려울 수도 있어 이 부분을 글로 표현하자면 ,

if (isPossibleCase(row, column, 1, inputArray)) {
copiedArray = arrayCopy(inputArray);
paintCaseA(row, column, copiedArray);
nextRowCol(row, column, copiedArray);
}

만약 매개변수 x의 값이 1을 가진 경우라면 (케이스 A[┌]의 경우) (row, column은 처음엔 0.0부터 시작, inputArray는 사용자가 입력한 배열)
사용자가 입력한 배열의 모양을 copiedArray에 담아 놓는다. callback함수가 return 된 후에도 같은 모양의 배열에서 다른 경우의 수를 판단할 수 있게 하기 위함이다.
케이스 A의 인덱스 값을 "#"으로 바꾸고(paintCaseA),
다음 행과 열로 이동한 다음 재귀함수 호출한다(nextRowCol)는 뜻이다.

이와 같이 계속 재귀함수가 호출되면서 총 경우의 수를 계산한다.


프로그래밍 입문이라 코드가 정리되진 않았지만.. 혹시 누군가 도움이 될수도 있다는 생각에 공유한다.
코드는 아래와같다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
package algospot;
import java.util.Scanner;
public class BoardCover {
    public static int HEIGHT = 0// 높이(행)
    public static int WIDTH = 0// 너비(열)
    public static int TOTALNUM = 0// height*width
    public static int RESULT = 0// 경우의 수
    public static void main(String[] args) {
        // 1. 사용자에게 입력받음
        Scanner scan = new Scanner(System.in);
        int testCount = scan.nextInt();
        for (int test = 0; test < testCount; test++) {
            int height = scan.nextInt();
            HEIGHT = height;
            int width = scan.nextInt();
            WIDTH = width;
            TOTALNUM = height * width;
            String[][] inputArray = new String[height][width];
            for (int row = 0; row < height; row++) {
                String dd = scan.next();
                for (int column = 0; column < width; column++) {
                    inputArray[row][column] = String.valueOf(dd.charAt(column));
                }
            }
            callBack(00, inputArray);
            System.out.println(RESULT);
            RESULT = 0;
        }
    }
    // 배열 출력 모양
    private static void printInputArray(String[][] inputArray) {
        for (int row = 0; row < HEIGHT; row++) {
            for (int column = 0; column < WIDTH; column++) {
                System.out.print(inputArray[row][column]);
            }
            System.out.println("");
        }
    }
    // 0.0의 인덱스를 시작으로 callBack
    private static void callBack(int row, int column, String[][] inputArray) {
        if ("#".equals(inputArray[row][column])) {
            nextRowCol(row, column, inputArray);
        }
        String[][] copiedArray;
        if (isPossibleCase(row, column, 1, inputArray)) {
            copiedArray = arrayCopy(inputArray); //처음 복사된 배열을 가짐 (사용자가 입력한 배열)
            paintCaseA(row, column, copiedArray);// . 의 부분을 ┌ 모양으로 #으로 바꿈 
            nextRowCol(row, column, copiedArray);//callback이 여기서 호출됨. 이때 들어가는 배열은 paint된 배열. 
        }
        if (isPossibleCase(row, column, 2, inputArray)) {
            copiedArray = arrayCopy(inputArray); //처음 복사된 배열
            paintCaseB(row, column, copiedArray);
            nextRowCol(row, column, copiedArray);
        }
        if (isPossibleCase(row, column, 3, inputArray)) {
            copiedArray = arrayCopy(inputArray);
            paintCaseC(row, column, copiedArray);
            nextRowCol(row, column, copiedArray);
        }
        if (isPossibleCase(row, column, 4, inputArray)) {
            copiedArray = arrayCopy(inputArray);
            paintCaseD(row, column, copiedArray);
            nextRowCol(row, column, copiedArray);
        }
        return;
    }
    private static void nextRowCol(int row, int column, String[][] inputArray) {
        if (checkArray(inputArray)) {
            RESULT++;
            return;
        }
        
        //row가 마지막 행이면 return. 
        //우리가 계산하려고 하는 블럭은 ㄴ 모양 이기 때문에 2*2 행렬만 취급한다. 따라서 마지막 행은 계산할 필요가 없다. 
        if (row == HEIGHT - 1) {
            return;
        }
        
        //column이 width-2일때 
        //위와 같은 논리로 마지막 열에는 들어가지 않기 때문에 계산할 필요 없다. 
        if (column == WIDTH - 2) {
            if (row + 1 == HEIGHT - 1) { //row가 마지막 행이면 return
                return;
            }
            
            callBack(row + 10, inputArray);//행이 한줄 내려감
            
        } else if (column < WIDTH - 1) {    
            
            callBack(row, column + 1, inputArray); //열이 한칸 이동함
        }
    }
    //┌ ┐└ ┘패턴이 가능한지 판단( 값이 "." 인 곳만 가능하다)
    public static boolean isPossibleCase(int row, int column, int x, String[][] inputArray) {
        boolean case_A = inputArray[row][column].equals(".") && inputArray[row][column + 1].equals(".")
                && inputArray[row + 1][column].equals(".") == true;
        boolean case_B = inputArray[row][column].equals(".") && inputArray[row][column + 1].equals(".")
                && inputArray[row + 1][column + 1].equals(" .") == true;
        boolean case_C = inputArray[row][column].equals(".") && inputArray[row + 1][column + 1].equals(".")
                && inputArray[row + 1][column].equals(".") == true;
        boolean case_D = inputArray[row][column + 1].equals(".") && inputArray[row + 1][column].equals(".")
                && inputArray[row + 1][column + 1].equals(".") == true;
        // 1
        if (x == 1 && case_A) {
            return true;
        }
        // 2
        if (x == 2 && case_B) {
            return true;
        }
        // 3
        if (x == 3 && case_C) {
            return true;
        }
        // 4
        if (x == 4 && case_D) {
            return true;
        }
        return false;
    }
    //┌ ┐└ ┘ 가 가능하면 . 을 # 으로 변경 
    //caseA
    public static String[][] paintCaseA(int row, int column, String[][] inputArray) {
        inputArray[row][column] = "#";
        inputArray[row][column + 1] = "#";
        inputArray[row + 1][column] = "#";
        // System.out.println("A경우 색칠! 결과는 : ");
        // printInputArray(inputArray);
        return inputArray;
    }
    
    //caseB
    public static String[][] paintCaseB(int row, int column, String[][] inputArray) {
        inputArray[row][column] = "#";
        inputArray[row + 1][column + 1] = "#";
        inputArray[row][column + 1] = "#";
        // System.out.println("B경우 색칠! 결과는 : ");
        // printInputArray(inputArray);
        return inputArray;
    }
    
    //caseC
    public static String[][] paintCaseC(int row, int column, String[][] inputArray) {
        inputArray[row][column] = "#";
        inputArray[row + 1][column] = "#";
        inputArray[row + 1][column + 1] = "#";
        // System.out.println("C경우 색칠! 결과는 : ");
        // printInputArray(inputArray);
        return inputArray;
    }
    //caseD
    public static String[][] paintCaseD(int row, int column, String[][] inputArray) {
        inputArray[row][column + 1] = "#";
        inputArray[row + 1][column] = "#";
        inputArray[row + 1][column + 1] = "#";
        // System.out.println("D경우 색칠! 결과는 : ");
        // printInputArray(inputArray);
        return inputArray;
    }
    //배열이 #으로 다 찼는지 판단
    private static boolean checkArray(String[][] inputArray) {
        int count = 0;
        for (int row = 0; row < HEIGHT; row++) {
            for (int column = 0; column < WIDTH; column++) {
                if (inputArray[row][column].equals("#")) {
                    count++;
                } 
            }
        }
        
        if (count == TOTALNUM) {
            return true;
        } else
            return false;
    }
}
cs


코드 질문이나 다른 문의사항 모두 환영!

그럼...누군가에게 도움이되길 바라면서 오늘도 화이팅!!

2015년 1월 12일 월요일

[Code Complete 좋은 코딩습관 기르기] Chapter 11. 변수이름의 효과 (변수이름짓기)



개발자들들의 가장 큰 고민중 하나는 변수이름 짓기다. 코딩작업은 팀프로젝트가 대부분이고 코드를 공유하게 되는데, 이때 변수이름을 잘못 짓게 되면 다른사람이 코드를 읽는데 큰 어려움을 느낀다.

이번엔 코드컴플릿에서 제공하는 변수이릅 짓는 법에 대해 적고자 한다.

11.1 좋은 이름에 대한 고려사항

  • Naming에서 가장  중요한 고려사항은 변수 이름이 변수가 표현하고 있는 것을 완벽하고 정확하게 설명해야 한다는 것이다. 좋은 이름을 짓기위해 효율적인 기법은 변수가 표현하는 것을 단어로 표현하는 것이다. 예를들어 미국 올립픽 대표팀에 있는 선수의 수를 표현하는 변수 이름은 numberOfPeopleOntherUsOlympicTeam일 것이다. 운동장의 좌석수를 표현하는 변수 이름은 numberOfSeatsIntheStadium일 것이다. 조금 길지만 변수가 표현하는 것을 정확히 표현하고 있다. (일반적으로 최적의 변수 길이는 10~16문자라고 한다-프로그램을 디버깅하기위해 들이는 노력을 최소화 할수 있다는...) 


  • 좋은 이름은 문제지향성이다. 좋은 이름은 "어떻게" 보다 "무슨 문제"인가를 표현하는 경향이 있다. 
  • 변수 이름으로 잘 쓰이는 것들 중 하나는 sum, total, average, Max, min, record, string, pointer 와 같은 계산값이다. 이러한 계산값을 변수의 앞에 두는 것이 좋다. 이럴 때 장점은 1) 변수에서 가장 중요한 부분이기에 눈에 쉽게 띄어 의미전달이 잘된다. 2) 이러한 규칙을 만듦으로써 totalRevenue와 revenueTotal 같은 혼란을 막을 수 있다. 3) 일관성 있다. 
  • 일반적으로 변수 이름 앞에 있는 num 은 합계, 변수 뒤에 있으면 인덱스를 가리킨다. 
  • 반의어는 정확하게 사용한다 (begin/end, first/last , locked/unlocked, min/max, next/previous, old/new... )

11.2 데이터의 특정 타입에 대한 명명

  • 루프 인덱스로는 i, j, k와 같은 이름이 관습적으로 사용된다. 하지만 루프가 길어진다면 i가 무엇을 나타내는지 쉽게 잊게 되기 때문에, 루프의 인덱스에 더 의미있는 이름을 제공하는 것이 좋다. 특히 중접된 루프가 있다면 가독성을 향상시키기 위해 변수의 의도를 잘 파악할수 있는 이름이 좋다.
  • 상태 변수로는 flag 보다 더 좋은 이름을 생각하는 것이 좋다.  단순히 flag가 아닌 무엇을 의도하는지 정확하게 나타내야 한다.

  • 임시변수의 명명은 일반적으로 x, temp로 쓰지만 임시변수가 일시적으로 유지되어야 할 때는 임시변수가 하는 일이 무엇인지 나타내는 변수이름이 좋다

  • 다음은 전형적인 boolean 변수 이름이다. 
1) done : 무언가 수행되었다는 것을 가리키기 위해 쓴다. 
2) error : 오류가 발생했음을 가리키기 위해,
3) found : 값이 발견되었다는 것을 가리키기 위해.
4) success or OK : 연산이 성공적인지를 가리키기 위해. 

boolean 변수 이름은 참 거짓의 의미를 함축할 수 있는 것이 좋다. 

앞에 is를 붙여 isdone, isError, isFound 와 같이 의문문으로 변경해 쓰기도 하지만 isStatus와 같이 문법에 어긋나거나 문맥이 이상하는 것은 오히려 가독성을 떨어뜨린다. 

긍정적인 boolean 변수 이름을 사용하는 것이 좋다. notFound = true보다  found=false가 더 낫다. 

  • 열거형일때는 Color_, Planet_,Month_ 와 같은 접두사를 사용해 해당 타입의 멤버들이 같은 그룹에 속하는 것을 분명히 하자.

  • 상수는 상수가 가리키는 숫자 보다는 상수가 표현하는 추상적인 대상으로 명명한다. 

이러한 규약으로 인해 익숙지 않은 변수들이 무엇을 의미하는지 쉽게 이해해 새로운 프로젝트에서 더 빠르게 코드를 배울수 있다. 또한 불필요한 이름이 늘어나는 것을 방지하며 관련된 항목들 간의 관계를 강조할 수 있다. 



11.4 비형식적인 명명 규약 

  • 일반적으로 변수 이름은 소문자로 시작하고(variableName) 메소드이름(루틴)이름은 (MethodName()) 은 대문자로 시작한다. 

  • 클래스와 객체를 구별한다. 
1) LongerWidget longerWidget;  첫글자 대/소문자  
2) WIDGET widget;                   대문자 / 소문자
3) t_Widget Widget;                  타입에 t_ 접두사
4)Widget awidget;                    변수에 a 접두사
5)Widget employeeWidget;        보다 구체적인 변수의 이름 사용해 타입과 구분 

  • 전역변수를 식별한다 - 접두사(g_)를 붙인다 
  • 멤버변수를 식별한다 - 이 변수가 지역변수나 전역변수가 아니라는 것을 분명히 한다. (접두사 m_)
  • 형 선언을 식별한다. 모두 대문자를 사용하거나, 접두사 또는 접미사 사용한다. 
  • 상수를 식별한다 상수가 다른 변수에 있는 값을 할당하는 것인지, 상수에 있는 값을 변수에 할당하느고 있는것인지를 구분해야한다. (c_)와같은 접두사를 붙일 수 있다.
  • 열거 형의 요소 식별한다. 위에 설명한것과 같다
  • 가독성을 강화시키기 위해 이름을 형식화한다. 가독성을 위해 _ 과 같은 구별자의 사용도 허용한다. 

특정 언어의 규약을 위한 지침. codeComplete은 Microsoft에서 출판되었기 때문에 MS사가 만든 언어 C와 비주얼베이직을 설명이 많은 편이다. 하지만 나는 자바를 공부하는 초보이기 때문에...... 우선 자바 규약만 정리한다. 


자바 규약
  •  i와 j는 정수 인덱스 
  • 상수는 밑줄로 구분되는 대문자로 표현 
  • 클래스와 인터페이스 이름은 첫 번째 단어를 포함해 각 단어의 첫번째 단어를 대문자로 작성 (낙타등표기법) ClassorInterfaceName
  • 변수와 메서드이름은 첫번째 단어를 소문자로 작성하고 다음단어는 대문자로 작성 variableOrRoutinName 
  • 밑줄은 대문자로만 이루어진 이름을 제외하고는 구별자로 안씀 
  • 접두사 get과 set은 접근자 메서드에만 사용, 


11.5 표준화된 접두사들 

의미적 접두사 
  • c: count 
  • first : first 
  • g : 전역변수
  • i : 배열인덱스
  • last : last
  • m : 클래스 수준의 변수 
  • max/min
  • p : pointer 

11.6 읽기 쉬운 짧은 이름 

     일반적인 축약 지침 
  • 표준 축약어 사용한다 
  • 불필요한 모음 제거 한다 (index = idx, integer = intgr)
  • 관사 제거
  • 각 단어의 첫문자 또는 처음의 몇 글자 
  • 이름에서 가장 중요한 단어 최대 세단어까지
  • 각 단어의 첫번째와 마짐가 단어 유지 
  • 각 음절에서 뚜렷한 소리 나는것
  • 쓸모없는 접미사 제거

11.7 피해야 할 이름의 종류 

  • 오해의 소지가 있는 이름이나 축약어 
  • 유사한 의미를 갖는 이름
  • 의미는 다르지만 유사한 이름의 변수 
  • 비슷하게 들리는 이름
  • 숫자는 되도록 넣지 않는다 
  • 오타는 없이
  • 영어에서 일반적으로 잘못 표기되는 단어는 피한다. 
  • 대문자만으로 변수의 이름을 차별화하지 않는다 
  • 여러개의 언어사용 피한다 
  • 표준형, 변수, 루틴의 이름을 피한다 
  • 변수가 표현하는 것과 전혀 관련이 없는 이름 피한다 
  • 읽기 어려운 문자 포함하는 이름. 


[출저 : code Complete - steve Mcconnel ]


 

2015년 1월 11일 일요일

[ 좋은 코딩 습관 기르기 Code Complete] Chapter 10. 변수 정리


  
10.3 변수의 초기화에 대한 지침
    
 부적절한 초기화와 관련된 문제는 예상치 못한 초기값을 변수가 포함하고 있기 때문이다. 이러한 문제는 다음과 같은 이유로 발생할 수 있다.

  • 변수에 값을 할당한 적이 없다. 이 값은 프로그램이 시작했을 때 해당 메모리 공간에 원래 있던 비트 값이 반영된 것이다.
  • 변수에 있는 값이 더이상 유효하지 않다. 어떤 위치에 변수의 값을 할당했지만, 그 변수가 더 이상 유효하지 않다.
  • 변수의 일부에는 값을 할당하고 나머지 부분에는 값을 할당하지 않았다. 

다음과 같은 문제를 해결하기 위한 지침

  • 변수가 선언될 때 초기화 한다 : 이는 방어적인 프로그래밍 방법, 초기화 오류를 막을 수 있는 좋은 방법이다. 
  • 변수가 처음 사용되는 곳과 근접한 위치에서 초기화하고 정의한다. 
  • 가능하면 final이나 const 를 사용한다 : 이는 변수가 초기화된 후에 다른 값으로 할당되는 것을 막을 수 있다. 
  • 카운터와 누산기를 주의한다 : 일반적인 오류는 카운터나 누산기를 다음 재사용 전에 초기화 하는 것을 잊기때문에 나타난다
  • 클래스의 멤버 데이터를 생성자에서 초기화 한다 : 루틴의 변수를 각 루틴 내에 초기화 하는 것처러 ㅁ클래스의 데이터도 생성자에서 초기화 되어야 한다. 
  • 다시 초기화 할 필요가 있는지 검사한다
  • 일단 명명된 상수를 초기화하고 실행코드로 변수를 초기화 한다. -?
  • 모든 변수들을 자동으로 초기화 해주는 컴파일러 설정을 사용한다.
  • 컴파일러 경고 메시지 활용
  • 입력매개변수의 타당성 검사
  • 부적절한 포인터를 검사하기 위해 메모리 접근 도구를 사용한다 
  • 포르그램 시작시 작업 메모리 초기화한다 


10.4 범위

  •  변수에 대한 참조를 지역화하라 : 변수에 대한 참조를 가까이 유지하는 것은 프로그램의 가독성을 향상시키는데 좋다. 얼마나 가까이 모여있는지를 측정할 수 있는 방법중 하나는 "폭(span)"을 계산하는 것이다. 즉 폭이 짧을 수록 좋다.
  •  변수의 "수명"을 가능한 짧게 유지한다 - 변수의 수명은 변수가 처음 참조되는 명령문에서 시작하고, 변수가 참조되는 마지막 명령문에서 끝난다. "긴 수명"은 변수가 여러 명령들에 걸쳐 살아있다는 것을 의미하고 "짧은 수명"은 변수가 몇 개의 명령문 동안에만 살아 있다는 것을 의미한다.  폭과 같이 수명에 관한 목표는 숫자를 낮추는 것, 변수의 수명을 짧게 유지하는 것이다. 이에 관한 이득은 1) 취약성의 창을 줄일수 있다. 즉 변수의 값을 변경하는 위치 사이에서 변수가 부정확하게 또는 부주의하게 변경되는 가능성을 줄인다. 2)초기화 오류를 줄인다. 3) 가독성을 높인다 4) 큰 루틴을 작은 루틴으로 나눌때 용이하다. 

즉 폭과 수명을 최소화 시키는 것이 좋다. 범위를 최소화 하기 위한 일반적인 지침을알아보자. 


  • 루프에서 사용되는 변수는 루프를 포함하고 있는 루틴의 시작에서가 아니라 루프 바로 앞에서 초기화한다
  • 변수를 사용하기 전까지 변수에 값을 할당하지 않는다
  • 연관된 명령문들은 그룹화 한다(같은 변수를 사용하는 것 끼리 그룹화...)
  • 필요한 경우에만 변수의 범위를 늘린다. - 변수의 범위를 최소화 하는 방법은 변수를 가능한 지역화 하는 것이다. 클래스 변수를 전역변수로 바꾸는 것보다 전역 변수를 클래습 변수로 바꾸는 것이 더 어렵다. 또한 protected 데이터 멤버를 private 멤버로 바꾸는 것이 더 어렵다. 
  •  *의문이 들때는 가능한 가장 작은 범위를 선택하도로고 하고, 특정한 루프로 제한하고, 개별적인 루틴으로 제한하고, 클래스에 대해서 private를 그 다음이 protected를 그 다음이 package를 그리고 최후에 수단에만 전역을 사용한다*

10.5 지속성

지속성은 데이터 수명을 나타내는 다른 말로 변수들은 다음과 같은 지속성을 가질 수 있다.

  • 특정한 코드 블록이나 루틴에서만 살아남는 경우 : 지역변수
  • 허용한 동안 살아남는 경우 : 자바에서 new로 생성된 변수는 가비지 컬렉션 (garbage collection)이 발생할 때까지 살아남는다
  • 프로그램이 종료할 때까지 살아남는 경우 : 대부분의 전역변수, 정적변수(static변수) 
  • 영원히 살아남는 경우 : 데이타 베이스에 저장한 값. 

10.6 바인딩 시간 

바인딩 시간 (Binding Time)은 변수와 값이 서로 연결되는 시간을 의미한다. 
변수와 값이 코드가 작성될때? 컴파일 될때? 로드될때? 프로그램이 실행될 때 연결 되는가?

가능한 바인딩 시간을 늦추는 것이 복잡성은 늘어나지만 코드의 유연성이 높아지기 때문에 좋다.  (반인딩 시간이 이를 수록 유연성과 복잡성은 낮아진다)

10.8 변수를 한 목적으로만 사용하는 방법 

  • 변수는 한 목적으로만. 
  • 선언된 변수가 모두 사용되는지 확인.

** 변수 사용시 Check List **

변수초기화
  1.  각 루틴이 입력 매개변수의 타당성을 검사하는가?
  2. 변수가 처음 사용된 곳에 가까운 위치에서 선언되었는가?
  3. 가능하면 변수가 선언될 때 초기화 하고 있는가?
  4. 3번이 불가하다면 변수가 처음 사용된 곳과 가까운 위치에 변수를 초기화 했나?
  5. 카운터와 누산기가 적절하게 초기화되고, 필요할 경우 사용될 때마다 다시 초기화되는가?
  6. 변수가 반복적으로 실행되는 코드에서 적절하게 초기ㅗ하 되는가?
  7. 코드를 컴파일 할때 컴파일 경고가 발생하지 않는가? 그리고 모든 경고를 활성화 하였는가?
데이터 사용에 대한 일만적인 문제

  1. 모든 변수가 가능한 작은 범위를 갖는가?
  2. 변수에 대한 참조가 폭과 전체 수명의 관점에서 가깜께 유지되는가?
  3. 제어구조가 데이터 형과 일치하는가?
  4. 선언된 모든 변수가 사용되는가?
  5. 모든 변수가 적절한 시간에 바인딩 되는가? 
  6. 각 변수가 오직 하나의 목적을 갖고 있ㄴ는가?
  7. 각 변수의 의미가 명확한가?




[출저:Code Complete, SteveMcConnel]