16.소프트웨어 공학 구현
1. 프로그래밍 언어의 역사
포트란
- 사람이 이해하기 쉬운 형태로 만들어진 초창기 고급 언어
- IBM 이 우주항공 분야에서 사용하기 위해 제작
베이직
- 쉬운 문법을 사용하여 교육용으로 만든 언어
- 개발 환경이 시각적이고 베이직 언어 계열이라 초보자가 익히기 쉬움
C
- 현재 가장 널리 쓰이는 명령형 언어
- 대다수 컴퓨터 구조와 운영체제가 C 컴파일러를 갖고 있어 거의 모든 환경에 사용할 수 있음
C++
- C 언어에 객체지향의 개념을 더한 언어
C#
- 마이크로소프트가 닷넷 프레임워크의 일부로 만든 객체지향 프로그래밍 언어
자바
- 선 마이크로시스템즈의 제임스 고슬링이 개발한 객체지향 언어
- JVM(자바 가상 머신)이라는 프로그램을 사용하기 때문에 컴파일된 코드가 각각의 플랫폼에 대해 독립적
2. 표준 코딩 규칙의 필요성
표준화된 규칙의 예시
나쁜 예)
int main() {
int score, char grade;
printf("test");
scanf("%d, &score);
if(num >= 90)
grade = 'A';
else if(score >= 80)
grade = 'B';
else
grade = 'F';
return -;
}
좋은 예)
int main() {
int score;
char grade;
printf("test");
scanf("%d, &score);
if(num >= 90)
grade = 'A';
else if(score >= 80)
grade = 'B';
else
grade = 'F';
return -;
}
3. 주요 표준 코딩 규칙
명칭에 관한 규칙
명칭은 31자 이내로 정한다
- 개발자가 코딩 중에 혼란스러울 수 있어 변수명과 함수명은 별도의 이름으로 구별
나쁜 예 | 좋은 예 |
---|---|
int abcdefghijklmnopqrstuvwxyabcdef = 0; | int sum = 0; |
변수명과 함수명은 다르게 사용한다
- 개발자가 코딩 중에 혼란스러울 수 있어 변수명과 함수명은 별도의 이름으로 구별
나쁜 예 | 좋은 예 |
---|---|
int num; | int num; |
int sum = 0; | int sum = 0; |
int sum(); | int getSum() |
명칭의 규칙을 따른다
다른 프로그래밍 언어와 명칭이 호환되도록 특수 문자는 _(언더바)만 사용하고, 다음의 대소 문자 사용 규칙을 따름
- 매크로명 : _ 및 대문자 사용
- 상수명 : _ 및 대문자 사용
- 변수명 : 소문자로 시작
- 함수명 : 소문자로 시작, 첫 번째 단어는 동사로 작성
- 포인터명 : 참조하는 변수명의 첫 글자는 대문자 사용
나쁜 예 | 설명 | 좋은 예 | 설명 |
---|---|---|---|
int num$sum = 0; | 허용되지 않는 특수 문자 사용 | int num sum = 0; | 허용된 특수 문자 사용 |
#define size 10 |
매크로명에 소문자 사용 | #define SIZE 10 |
매크로명에 대문자 사용 |
const int hight = 20; | 상수명에 소문자 사용 | const int HIGHT = 20; | 상수명에 대문자 사용 |
int Sum = 0; | 변수명이 대문자로 시작 | int sum = 0; | 변수명이 소문자로 시작 |
int Data(){} | 함수명이 대문자로 시작, 동사로 시작X | int getData(){} | 함수명이 소문자로 시작. 동사로 시작 |
포인터 변수명은 앞에 p를 붙인다
나쁜 예 | 좋은 예 |
---|---|
int a = 0; | int a, sum = 0; |
int *sum += a; | int *pSum = a; |
명칭에 관한 규칙
소스 파일 하나는 200줄 이내로 작성한다
- 200줄이상: 문맥을 파악 및 파일 관리가 어렵고, 유지보수의 효율성이 저하
한 줄의 길이는 80자 이내로 작성한다
- 한 줄이 너무 길면 가독성이 떨어짐
함수의 내용은 70줄 이내로 작성한다
- 함수의 크기는 한 화면에 전체 내용이 보일 수 있도록 70줄 이내로 작성
- 함수가 너무 길어 화면이 분할되면 가독성이 떨어져 문맥을 파악하기가 어려움
여는 중괄호 { 는 문장의 끝에, 닫는 중괄호 }는 문장의 시작에 둔다
나쁜 예 | 좋은 예 |
---|---|
if(a > b) { pringf(“YES) } | if(a > b) { printf(“YES”) } |
하나의 문장을 2줄로 작성하는 경우 다음 규칙을 따른다
- 80자가 넘어 쉼표(,)가 오면 다음 문자는 새 줄로 시작
- 둘째 줄의 시작은 다음의 좋은 예처럼 이전 줄의 표현식과 같게 함
나쁜 예 | 좋은 예 |
---|---|
int a = k(parameter A, parameter B, parameter C) | int a = k(parameter_A, prameter_B, parameter_C) |
수준이 동일한 문장은 시작 위치를 맞춘다
- 수준이 같은 문장은 동일하게 들여쓰기를 하는 것이 좋음
나쁜 예 | 좋은 예 |
---|---|
if(a > b) { x = a + b; return x; } | if(a > b) { x = a + b; return x;} |
주석에 관한 규칙
코드의 첫 주석에는 다음 내용을 담는다
- 최초 작성자
- 최초 작성일
- 최초 변경일
- 목적
- 개정 이력(변경자, 변경 일자, 변경 내용)
- 저작권
메서드 정의 앞에 다음 내용을 주석으로 추가하고 시작한다
- 목적 : 함수의 용도(목적)
- 매개변수 : 함수의 인자로 사용되는 변수에 대한 설명
- 반환 값 : 함수의 결과 값에 대한 설명
- 변경 이력 : 함수를 변경한 변경자, 변경 일자, 변경 내용
원시 코드와 주석을 명확히 구분한다
- 원시 코드와 주석이 명확히 구별될 수 있도록 공백(또는 탭)을 두고 주석을 작성해야 눈에 잘 들어옴
원시 코드와 주석이 일치하게 한다
- 처음에는 원시 코드를 작성하면서 주석을 달아 서로 일치하지만 시간이 지나 원시 코드가 변경된다면 주석이 어긋나게 됨
- 주로 다음 내용을 주석으로 달고 원시 코드에 맞춰 계속 함
- 함수 인자에 대한 설명
- 복잡한 논리식
- 간단하지 않은 자료구조
변수 선언 및 자료형에 관한 규칙
용도가 같은 변수는 한 줄에 작성한다
- 용도가 같은 변수는 여러 줄로 쓰지 말고, 한 줄로 작성
나쁜 예 | 좋은 예 |
---|---|
int a = 0; | int a = 0, int b =0; |
int b = 0; |
필요한 변수만 선언한다
- 불필요한 변수는 개발자에게 혼란을 주어 이해하기 어렵게 만듬
나쁜 예 | 좋은 예 |
---|---|
int a = 0; // a 변수를 사용하지 않는데 선언함 | int a = 0; // a 변수 사용, functA(a); |
배열 선언 시 요소 수를 명시하거나 초기화한다
- 배열 선언 시 배열의 요소 수를 알 수 있게 명확히 표시하거나 초기화를 통해 작성
나쁜 예 | 좋은 예 |
---|---|
int score[ ]; | int scrore[5]; int score[ ] = {1, 4, 7, 9, 10}; |
배열을 초기화할 때는 중괄호를 적절히 사용한다
- 중괄호를 적절히 사용하지 않으면 원시 코드의 가독성이 떨어져 초기화 값을 혼동할 수 있음
나쁜 예 | 좋은 예 |
---|---|
int score[2][2] = {1, 4, 7, 9}; | int score[2][2] = { {1,4}, {7,9} }; |
지역 변수는 선언 시 초기화한다
- 초기화를 하지 않으면 쓰레기 값으로 초기화될 수 있음
나쁜 예 | 좋은 예 |
---|---|
int a; // 초기화 안 됨 | int a = 0; // 초기화됨 |
부호 없는 자료형은 끝에 u를 붙인다
나쁜 예 | 좋은 예 |
---|---|
#define MIN 20; |
$define MIN 10u; |
포인터 변수에 주소나 정수 값을 저장할 때는 자료형이 일치해야 한다
나쁜 예 | 좋은 예 |
---|---|
int *pKim; | int *pKim; |
char chi = ‘SU’; | int chi = ‘5’; |
pKim = χ |
pKim = χ |
비트 필드는 unsigned/signed int형으로만 선언한다
- 만약 비트 필드를 다른 자료형으로 선언하면 동작이 정의되지 않아 원치 않은 결과를 얻을 수 있음
나쁜 예 | 좋은 예 |
---|---|
struct st { char a : 2; unsigned int b : 3; } | struct st { unsigned int a : 2; unsigned int b : 3; } |
상수에 관한 규칙
8진수는 사용하지 않는다
- 8진수로 표현하면 가독이 떨어짐
나쁜 예 | 좋은 예 |
---|---|
int octal = 0377; // 8진수 표현 | int hexa = 0xFF; // 16진수 표현 int chi = 10; // 10진수 표현 |
숫자 리터럴은 const 변수를 사용한다(C 언어의 경우)
- 원시 코드에 직접 표현(하드 코딩)한 숫자 리터럴은 그 의미를 파악하기 어렵게 함
- 값을 변경할 수 없는 const 변수 사용
나쁜 예 | 좋은 예 |
---|---|
int tri area = 10*5/2; (삼각형 면적 = 밑변x높이/2) |
const int base line = 10; const int hight = 5; int tri area = base line x hight / 2 |
상수는 부호 있는 자료형을 사용하고 부호 없는 자료형을 사용할 때는 u를 붙인다
나쁜 예 | 좋은 예 |
---|---|
#define SIZE 20; |
#define SIZE 20u; |
수식에 관한 규칙
단항 연산자의 바른 표기
- 단항 연산자(++, –)는 피연산자와 붙여 써야 피연산자가 어떤 것인지 금방 알 수 있음
나쁜 예 | 좋은 예 |
---|---|
a ++ | a++ |
이항 연산자의 바른 표기
이항 연산자(+, -, *, /)는 전후에 공백을 넣어야 연산자와 피연산자가 명확히 구분되고 가독성도 높아짐
- (dot) 연산자는 제외
나쁜 예 | 좋은 예 |
---|---|
a=b+c+d; | a = b + c + d; |
삼항 연산자의 바른 표기
- 삼항 연산자(?:)는 알아보기 쉽게 맨 앞의 수식을 괄호(( ))로 묶어줌
나쁜 예 | 좋은 예 |
---|---|
a > b ? x: -x; | (a > b) ? x: -x; |
증강 연산자의 바른 표기
- 증강연산자는 다른 줄에 써야 혼란을 초랳지 않고, 가독성을 높일 수 있음
나쁜 예 | 좋은 예 |
---|---|
sum = kor + (++eng); | ++eng; sum = kor + eng; |
연산자가 3개 이상인 경우의 바른 표기
- 연산자가 3개 이상일 경우에는 우선순위를 쉽게 알 수 있도록 괄호로 묶어주는 것이 좋다
나쁜 예 | 좋은 예 |
---|---|
if(a == 0&&b == 0) | if((a == 0) && (b == 0)) |
sizeof 인자의 바른 표기
- 수식을 sizeof 함수의 인자에 사용하지 않음
나쁜 예 | 좋은 예 |
---|---|
sizeof(a = b + c) | sizeof(a) |
문장에 관한 규칙
switch 문에서 case 문을 빠져나오기 위해 break 문을 사용한다
- break 문이 없을 때는 다음 case 문으로 제어가 넘어간다는 사실을 주석으로 달아 주면 프로그램을 이해하는 데 도움이 됨
나쁜 예 | 좋은 예 |
---|---|
case 1: statements case 2: ~~ |
case 1: statements // break 문이 case 2로 넘어감 case 2: ~~ |
switch 문에서 case 문이 다 끝나면 default 문을 넣어주어야 한다
- 만족하는 case 문이 없을 때 마지막 default 문에서 후속 처리를 해주기 위해서 default 문을 넣어줌
나쁜 예 | 좋은 예 |
---|---|
case 1: statements break; case 2: statements break; |
case 1: statements break; case 2: statements break; default; |
goto 문을 사용하지 않는다
- goto 문은 프로그램의 흐름을 복잡하게 만드는 주범이므로 가능하면 사용을 하지 않음
for 문을 제어하는 수식에 실수 값을 사용하지 않는다
- for 문의 제어 인자로 실수 값 대신 정수 값을 사용하는 것이 좋음
나쁜 예 | 좋은 예 |
---|---|
float i = 1.1 for(i = 1.1; i < 2.5; i = i + 0.1) |
int i = 1 for(i = 1; i < 8; i = i++) |
for 문을 제어하는 수치 변수의 바른 사용
- 계산에 사용하면 반복 횟수를 예측할 수 없게 되니 원래의 용도로만 사용해야 함
나쁜 예 | 좋은 예 |
---|---|
int i = 0, j = 10 for(i = 0; i < 10; ++) i = i + j; |
int i = 0, j = 10 for(i = 0, j = 10; i < j; i++, j++) |
break 문은 가능하면 한 번만 사용한다
- 반복문에서 반복 중단을 위한 break 문을 여기저기에서 사용하면 프로그램의 동작을 예측하기가 어려움
나쁜 예 | 좋은 예 |
---|---|
// 반복을 중단하기 위해 여러 번 break 문 사용 int i = 0; while(1){ if(i == 0){ break; } else if(i == 20){ break; } } |
int i = 0; while(1){ if(i == 0) || (i == 20){ break; } …. } |
if ~ else 문의 끝은 else 문으로 종료한다
- else 문으로 종료하지 않으면 문법적 오류는 아니지만 처리가 누락되어 원하는 결과가 나오지 않을 수 있음
나쁜 예 | 좋은 예 |
---|---|
int score; char grade; printf(“점수 입력:”); scanf(“%d”, &score); if(score >= 70) printf(“PASS”); |
int score; char grade; printf(“점수 입력:”); scanf(“%d”, &score); if(score >= 70) printf(“PASS”); else printf(“failure”); |
댓글남기기