기본 데이터 형

일반적인 숫자의 사용시 유의할 점

  • 매직넘버(Magic Number)를 피하라
  • 0과 1은 그냥 사용
  • 0으로 나누는 것은 미연에 방지
  • 형 변환은 명확하게 수행
    • 예) y = x + (float) i
  • 서로 다른 형을 비교하지 않는다
  • 컴파일러의 경고에 주의

 

정수(integer)를 사용할 때 주의할 점

  • 정수 나눗셈 검사
  • 정수 오버플로우 검사
  • 중간 결과에서 오버플로우 검사
int termA = 1000000;
int termB = 1000000;
int product = termA * termB / 1000000;
System.out.println(...+product);

 

부동소수점 변수 사용시 주의할 점

  • 서로 크기가 매우 다른 수를 더하거나 빼지 않는다
    • 가장 작은 수부터 더하는 것이 좋다
  • 동치 비교를 피한다
  • 라운딩 오류를 예측한다
    • 더 큰 정밀도를 사용
    • BCD 표기법을 사용한 변수로 변경
    • 정수형을 사용(화폐 등을 계산할 때)
  • 특정한 데이터 형을 지원하는 언어 또는 라이브러리가 있는지 확인

 

문자와 문자열

  • 매직문자와 매직문자열을 사용하지 않는다
  • 하나 모자름(off-by-one) 오류 주의
  • 사용하고 있는 언어가 유니코드(Unicode)를 어떻게 지원하는지 파악
  • 국제화(Internationalization, i18n) / 지역화(Localization, L10n) 전략을 초기에 결정
  • 만약 알파벳만을 사용할 것이면 ISO 8859를 사용하는 것이 좋다
  • 다중 언어를 지우너하려면 유니코드를 사용
  • 문자열 타입 간에 일관된 변환 전략 사용
    • 프로그램이 다중 문자코드를 지원하는 경우, 내부적으로는 유니코드를 쓰고 I/O에만 코드 변환 사용

 

불린(Boolean) 변수

  • 프로그램을 문서화하기 위해 불린 변수를 사용
  • 필요하면 고유한 불린 타입을 만든다
    • 불린 타입이 제공되지 않는 언어(C와 같은) 경우, 0 = False, 1 = True
if ( (elementIndex < 0) || (MAX_ELEMENTS < elementIndex) || (elementIndex == lastElementIndex) ) )
{
	…
}

// ↓↓↓↓

finished = (elementIndex<0) || (MAX_ELEMENTS < elementIndex) ;
repeatedEntry = elementIndex == lastElementIndex;
if (finished || repeatedEntry) {
	…
}

 

열거 형의 사용

  • 가동성 향상
  • 신뢰성
    • 컴파일러가 정수 또는 상수를 사용할 때 보다 타입 검사를 강력하게 할 수 있다
  • 수정을 용이하게 하기 위해
    • 기존 요소의 할당 값 변경 또는 새로운 요소의 추가가 용이
  • 불린 변수에 대한 대안
    • 불린 변수는 2가지만 표시할 수 있지만 열거형은 Status_Success, Status_Warning, Status_FatalError 등과 같이 다양한 값을 표현하기에 유리
  • 타당하지 않는 값 검사
  • 반복문의 범위를 지정하기 위해 열거형의 처음과 마지막 엔트리를 정의
    • 연속되지 않는 경우 주의
  • 열거 형의 첫째를 타당하지 않는 값으로 남겨둔다
    • 대다수의 언어가 열거형의 처음을 0로 할당하므로 초기화되지 않은 변수(0일 가능성이 높음)를 잡는데 유리

 

명명된 상수

  • 리터럴 대신 명명된 상수를 사용
  • 확실한 리터럴이더라도 명명된 상수를 쓰는 것이 좋다
for (int i=1; i<12; i++) {
	profit[i] = revenue[i] –expense[i];
}

// ↓↓↓↓

for (int i=1; i<=NUM_MONTHS_IN_YEAR) …
// or
for (int i=Month_Jan ; i<=Month_Dec; i++) …

 

배열의 사용

  • 배열의 모든 인덱스가 경계 내에 있는지를 확인
  • 경계를 확인해 주는 언어(Java)가 있으나 그렇지 않은 것(C, C++)도 있다
  • 배열 대신 컨테이너를 사용하거나 배열을 순차적인 구조체로 생각하라
  • 배열의 마지막 위치를 확인
  • 다차원 배열에서 첨자의 순서가 정확한지 확인
  • 인덱스가 혼선(Cross-Talk)되지 않도록 주의
    • 예) Array[i] 와 Array[j]
  • C 또는 C++에서는 ARRAY_LENGTH 매크로를 사용
#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0])
float consistency_ratio[] = {
	0.0, 0.0, 0.58, 0.90, 1.12,
	…
	1.59
};
…
for (ratioIdx = 0; ratioIdx < ARRAY_LENGTH(consistency_ratio) ; ratioIdx++) {
	…
}

 

변수 사용시 일반적인 문제

능률적인 변수 정의 방법

  • 다른 모듈에서 정의한 변수를 사용하려면 반드시 선언
    • 선언(Declaration)
    • 정의(Definition)
  • 명명 규약(Naming Convention)을 사용
  • 변수의 이름을 검사

 

부적절한 변수 초기화

  • 변수에 값을 할당한 적이 없다
  • 더 이상 유효하지 않은 변수에 값을 할당
  • 변수의 일부에 값을 할당하고 나머지는 할당하지 않는다

 

변수 초기화

  • 변수가 정의될 때 초기화
  • 변수가 처음 사용되는 곳에 근접한 위치에서 정의 및 초기화
  • 가능하면 const 또는 final을 사용
  • 카운터와 누산기를 조심
    • 재사용 전에 반드시 초기화
  • 객체의 데이터 필드는 생성자에서 초기화
  • 변수를 다시 초기화할 필요가 있는지 검사
    • 반복문과 변수 사용시 주의
  • 상수를 흉내내기 위한 변수들은 Startup() 루틴에서 한번만 초기화
  • 모든 변수를 자동으로 초기화해주는 컴파일러 설정 사용
  • 컴파일러 경고 메시지를 활용
  • 입력 인자의 타당성 검사
  • 부적절한 포인터를 검사하기 위해서 메모리 접근 도구 사용
    • Memory Leak Detection Tool 사용
  • 프로그램 시작시에 작업 메모리를 초기화
    • NULL(0), 0xCC(Intel CPU에서)

 

변수의 범위

  • 변수에 대한 참조는 지역화
    • 동일 변수에 대한 참조는 되도록 가깝게 유지
    • 변수들의 폭을 좁게 유지
    • 변수의 (평균) 폭이 작을수록 프로그램의 가동성이 좋다
[ 좋은 예시 ]
a = 0;
b = 0;
c = 0;
a = b + c;

[ 안좋은 예시 ]
a = 0;
b = 0;
c = 0;
b = a + 1;
b = b/c;
  • 변수의 수명을 가능한 짧게 유지
    • 수명이 짧은 변수는 코드를 읽기 쉽고 변수의 잘못된 사용을 막는다

 

변수의 범위를 최소화하기 위한 지침

  • 루트(반복문)에서 사용되는 변수는 루트 바로 직전에서 초기화
  • 변수를 사용하기전까지는 변수에 값을 할당하지 않는다
  • 연관된 명령문을 그룹화
  • 연관된 명령문을 별도의 루틴으로 나눈다
  • 처음에는 가시도를 제한하고 필요한 경우에만 가시도를 넓힌다
    • private → protected, package, pulic

 

변수의 지속성(수명)

  • 특정 코드 블록이나 루틴에서만 살아남은 경우
    • 코드 블록 또는 루틴에서 정의된 변수에 해당
  • 허용된 동안 살아남은 경우
    • new를 이용하여 생성한 객체는 delete(C++) 또는 가비지 컬레션(Java)때까지 살아남는다
  • 프로그램이 종료할 때까지 남는 경우
    • static 변수 (C, C++, Java)
    • 지역변수
  • 영원히(Persistent) 살아남는 경우
    • 데이터베이스 또는 파일에 값을 저장하는 변수

 

바인딩 시간(Binding Time)

  • 변수와 그것의 값이 서로 연결되는 시간
    • 코드 작성시 바인딩(리터럴)
    • 컴파일시 바인딩
    • 실행시 바인딩
      • 레지스트리 또는 파일 사용
    • 객체 생성시
    • 적시(Just in Time)
      • 예)윈도우를 화면에 그릴 때
  • 바인딩 시간이 이를수록(늦을수록) 유연성과 복잡성이 낮아진다(높아진다)

 

변수 사용시 주의할 점

  • 각 변수는 한가지 목적만을 위해 사용
  • 숨겨진 의미를 갖는 변수를 피하라
    • pageCount 변수는 값이 출력된 페이지 수를 표현한다. -1인 경우 오류를 표시한다.
    • bytesWritten 변수는 출력 파일에 쓰여진 바이트 수이다. 하지만 이 값이 음수면 출력 파일에 사용된 디스크 드라이브의 수를 가리킨다.
  • 정의된 모든 변수가 사용되는지 확인
[ 안좋은 예시 ]

temp = sqrt(b*b-4*a*c);
root[0] = (-b+temp) / (2*a)
root[1] = (-b-temp) / (2*a)



temp = root[0];
root[0] = root[1];
root[1] = temp;

 

[ 좋은 예시 ]

discriminant= sqrt(b*b-4*a*c);
root[0] = (-b+discriminant) / (2*a)
root[1] = (-b-discriminant) / (2*a)



temp = root[0];
root[0] = root[1];
root[1] = temp;

 

변수의 명명

명명 규칙의 필요성

  • 다수의 개발자에 의한 공동작업을 수행하는경우
  • 다른 개발자가 작성한 코드를  검토하거나 유지 보수하는 경우
  • 프로그램을 부분적으로 생각하고자할 때
  • 시일이 지난후 자신이 작성한 코드를 다시 검토할 때
  • 특이한 용어들이 많아서 코드 작성시 표준 용어 또는 약어가 필요한 경우

 

좋은 변수이름을 위한 고려 사항

  • 변수의 의미를 완벽하고 정확하게 설명해야 한다
변수 의미 좋은 이름 나쁜 이름
날짜가 쓰인 유통중인 수표의 총계 runningTotal, checkTotal written, ct, checks, CHKTTL, x, x1, x2
고속 열차의 속도 velocity, trainVelocity, velocityInMph velt, v, tv, x, x1, x2, train
현재 날짜 currentDate, todaysDate cd, current, x1, x2, date
페이지당 행의 수 linesPerPage lpp, lines, x1, x2, l
  • 해결하고자 하는 문제 영역의 개념을 표현
    • 예) 직원 데이터는 inputRec 보다는 employeeData를 사용, 프린터의 상태 표시하는 프래그는 bigFlag 보다는 printerReady를 사용
  • 적절한 길이를 사용
    • Too shart : 의미 불명확
    • Too Long : 입력 불편, 코드 구조 파악 불편
  • 짧은 변수는 Loop 카운터 또는 배열인덱스를 위해 사용
    • 예) i, j, k 등
너무 길다  numberOfPeopleOnTheUsOlympicTeam
 numberOfSeatsInTheStation
 maximumNumberOfPointsInModernOlympics
너무 짧다  n, np, ntm
 N, ns, nsisd
 M, mp, max, points
적당  numTeamMembers, teamMemberCount
 numSeatsInStadium, seatCount
 teamPointsMax, pointsRecord
  • 이름 공간(Namespace)(C++)를 사용하여 변수 이름 충돌을 회피 (Java는 Package 사용)
    • 한정자는 주로 변수의 끝에 위치시킨다
    • 앞부분의 중요한 의미를 전달하도록
    • 일관성을 유지하여 혼돈을 방지
      • totalRevenue ↔ revenueTotal
    • 대칭적 이름을 작성하기에 유리
      • revenueTotal/expenseTotal, revenueAverage/expenseAverage 는 totalRevenue/totalExpense, averageRevenue/averageExpense 보다유리
    • 일반적인 반의어의 조합을 사용
      • begin/end, first/last, locked/unlocked, min/max, next/previous, old/new, opened/closed, visible/invisible, source/destination, up/downsource/target, source/destination, up/down

 

변수명의 축약 - 일반적 지침

  • 표준 축약어를 사용 (사전에나오는)
  • 불필요한 모음을 제거
    • 예) computer → cmptr, screen → scrn
  • 관사 및 접속사(a, the, and, or 등)는 제거
  • 각 단어의 첫 문자 또는 처음 몇개의 문자를 사용
  • 각 단어의 첫 번째와 두 번째, 세 번째 다음에 오는 것을 일관성 있게 자른다
  • 각 단어의 처음과 마지막 문자를 유지
  • 이름에서 가장 중요한 단어를 최대 세 단어까지 사용
  • 쓸모없는 접미사(ing, ed 등)를 제거
  • 각 음절에서 가장 뚜렸한 소리를 유
  • 변수의 의미가 변경되지 않도록 주의
  • 위의 기법을 반복적으로 적용
  • 음성축약 ← 비추천
    • highlight hilite, before b4, excute xqt

 

축약시 주의할 점

  • 단어에서 한 문자를 없애는 방법으로 축약하지 말라 → 노력의 감소에 비해가독성이 떨어짐
    • 예) June Jun
  • 일관성 있게 축약
  • 발음할 수 있는 이름으로 생성
    • 예) XPstn xPos, ndsCmptg needsComp
  • 잘못된 발음으로 인한 조합을 피한다
    • 예) 마지막 B를 나타내기 위해 BEND 보다는 ENDB, B-END, BEnd, b_end를사용
  • 축약시 이름의 충돌을 방지하기 위해 동의어 사용
    • 예) fired와 full revenue disbursal이 frd로 축약될 수 있음, 이경우 fired dismissed dsm, full revenue disbursal complete revenue disbursal → crd
  • 매우 짧은 이름은 코드 내에 변환 테이블을 사용하여 문서화
  • 모든 축약어는 프로젝트 수준의 표준축약어 문서에 기록

 

'Memo' 카테고리의 다른 글

JEB java.lang.NullPointerException 오류 해결 방법  (0) 2020.07.19
Git 사용법  (0) 2020.06.21
Python(.pyc) 디컴파일  (0) 2020.05.01
CTF 풀 때 도움 되는 사이트 정리  (0) 2020.04.13
GitHub 사용법  (0) 2020.04.13