19. 개발과 코딩(10-1)
프로그래밍(Programming)의 개념
개념
소프트웨어 개발 과정에서 프로그래밍은 설계의 연장
상세 설계가 끝난 후 프로그래밍(코딩)에 들어가며, 프로그래밍은 설계 명세서에 나타난 결과를 더욱 구체화시켜 컴퓨터가 이해할 수 있는 모습으로 바꾸는 것
컴퓨터가 이해할 수 있는 언어로 표현한다는 뜻
프로그래밍 언어 - 컴퓨터가 이해할 수 있는 언어
코딩은 설계의 자연스러운 결과
설계가 제대로 이루어지면 프로그래밍은 기계적으로 이루어진다고 볼 수 있음
프로그래밍 언어는 인간과 컴퓨터 사이의 통신 또는 대화 수단으로 사용되는 컴퓨터 언어
지금까지 수백 종의 프로그래밍 언어가 개발되어 사용됨
현재도 기계어, 어셈블리어, 고급언어 등 다양한 언어들이 사용
소프트웨어 품질과 유지보수에 영향을 끼침
프로그래밍언어의 세대별 분류
1세대 언어
1950년 전후, 기계어 또는 어셈블리 언어
2세대 언어
1950년대 후반, 최초의 고급언어인 FORTRAN, COBOL 등 등장
3세대 언어
구조적 프로그래밍을 지원하는 언어인 ALGOL, PASCAL, Smalltalk, C, C++ 등의 등장
4세대 언어
수행하는 과정을 프로그래밍하기 보다는 의도하는 결과물을 선언하는 비절차적 언어 (Non-Procedural Languages)의 등장
비 절차식 언어(Non-Procedural Languages)
구체적인 알고리즘을 명시할 필요가 없음
추상화 수준을 높일 수 있음
쉽게 프로그래밍할 수 있음
비 절차 언어
관계형 데이터베이스의 질의어인 SQL (Structured Query Language), PROLOG 등을 들 수 있음
SQL 질의어 예
추상화 수준을 높일 수 있음
예 - SELECT AVG(SALARY)
FROM EMPLYEE
WHERE DNAME = 'RESEARCH'
2. 개발원리 및 단계
코딩 원리
코딩 작업
각 모듈에 대한 원시코드를 작성
모듈 안에 포함된 오류를 검출하는 단계
코딩 원칙
설계를 철저히 반영
원시코드는 간단 명료하도록 함
디버깅이 쉽게함
시험이 용이
수정이 간편
코딩
정의
분리하여 구현할 수 있는 작은 단위를 프로그래밍하는 작업
모듈 안의 함수 작성 절차적 방법
개별 메소드의 프로그래밍 객체지향 방법
목표
설계 명세에 나타낸 요구를 만족하는 프로그램을 작성
요구분석서, 아키텍처 설계서 참조
오류가 적은 품질 좋은 프로그램 작성
원리와 가이드 준수
코딩 작업의 순서
원시코드를 같은 스타일로 만들기 위한 코딩 표준 작성 1
아키텍처 설계 결과를 근거로 프레임워크 패키지와 응용 패키지를 구분 2
요구사항과 상세설계를 반영하여 메소드 코딩
인스펙션(Inspection) 3
검증 또는 검사
클래스 단위로 테스트 4
통합을 위하여 릴리스 5
구조적 프로그래밍
원시코드정의
프로그램의 제어흐름을 선형화시켜 논리구조를 명백하게 하려는 코딩 규율
구조적 프로그램
세가지 제어구조(순차, 선택, 반복)로 무조건적 Goto에 의한 복잡한 제어흐름을 방지
제어구조가 하향식
Stepwise Refinement를 이용한 프로그래밍
Proper Program
단일입구, 단일 출구
모든 노드는 입구에서 도달할 수 있는 경로가 있어야 함
모든 노드는 출구에서 도달할 수 있는 경로가 있어야 함
정보은닉
용도
일반적으로 어떤 정보에 대하여 제한된 방법으로만 사용
예 - 회계 원장(차변, 대변, 잔고확인)
→모든 차변을 더하여 대변의 합으로 나누는 것과 같은 오퍼레이션은 적용되지 않음
자료구조
정의
내부의 정의가 시스템의 다른 부분으로부터 감추어져 있어야 함
장점
결합도를 줄이고 시스템의 유지보수를 쉽게 만듦
데이터를 관리하는 관점과 데이터를 사용하는 관점을 분리할 수 있음
언어자체의 메커니즘
모듈 선택
구현 활동의 첫 단계
모듈들이 구현될 순서를 결정하는 것이며, 특히 어느 모듈이 다음에 구현될 것인가를 결정하는 것
모듈 선택 작업은 두 개의 기본적 가정을 기초로 한 단순한 결정 과정
첫 번째 가정 - 시스템이 점차적으로 코드화되고, 통합되어 테스트되는 것
두 번째 가정 - 가정은 시스템이 하향식으로 개발되는 것
→ 계층 구조의 상위 모듈들을 하위 모듈들보다 먼저 코드화하고 통합할 것
모듈의 코드화
이 단계에서는 코드(Code)가 작성되며, 이 단계의 입력은 전 단계에서 만들어진 모듈 명세서\
골격 구조 시험 단계
이 단계는 모듈 시험과 시스템 통합을 동시에 수행하는 활동
전 단계에서 작성된 코드화된 모듈은 이미 만들어진 부분 시스템과 합쳐져서 시스템이 시험됨
프로그래밍 표준
개념
옷을 입는 스타일이 사람마다 다르듯이 프로그래밍 스타일도 사람마다 다름
좋은 프로그래밍 스타일이 어떤 것이라는 정의를 내리는 것은 쉽지 않음
좋은 프로그램이란 일반적으로 단순하고 명확하여 그 내용을 쉽게 파악할 수 있도록 만들어진 것을 일컬음
코드는 간결하며 명확하고 이해하기 쉽도록 쓰여져야 함
프로그램에 대한 가이드라인과 표준을 제시하는 것은 프로그램에 대한 관리를 용이하게 하고 생산성을 높이려는데 그 목적이 있음
코드의 문서화
개념
프로그램이 만들어진 후 설계 명세서를 참조하지 않고도 모듈의 기능을 쉽게 이해될 수 있어야 함
변수 이름, 레이블 이름을 정할 때도 직접적이며 정직한 이름을 사용해야 함
식별자 이름의 선정은 프로그램을 이해하는데 중요한 역할을 함
예 - AREA = LENGTH * HEIGHT
프로그램 내부에 포함되는 문서 형태를 '주석문(Comments)'이라 함
주석문은 한국어나 영어 등 우리가 사용하는 언어를 이용하여 기술
주석문
모듈의 목적을 기술하는 목적문
인터페이스에 대한 기술
호출 표본
모든 인수에 대한 설명
모든 종속 모듈 목록
중요 변수들과 이들의 사용 한계, 제한 등을 포함하는 중요 정보들
개발 역사
모듈 설계자(Author)의 이름
검토자의 이름과 검토 날짜
수정 일자와 수정에 대한 설명
가이드라인
변수, 구조체, 함수 등은 그 의미를 알기 쉬운 이름을 사용하거나 주석을 통하여 선언 시 그 목적을 분명히 알 수 있도록 해야 함
주석은 코드와 명확히 구분되어 눈에 잘 띄어야 함
주석은 코드에 대한 정확한 설명을 해야 하나, 명백한 코드에 대한 재 설명은 필요 없음
함수의 이름과 그 인자 사이에 연관관계를 명확하게 해야 함
함수의 인자는 선언 시 인자에 대한 설명(주석)이 있어야 함
쉽게 이해되지 않는 논리식이나 자료구조에 대한 설명(주석)이 있어야 함
코드의 간결성
개념
공백을 이용하여 실행문 그룹과 주석을 명확히 구분
편집의 편의를 위해 탭 키를 일관성 있게 사용
복잡한 논리식과 산술식은 괄호와 줄 맞추기(Indentation)를 통해 명확하게 표현하고, 상호 관련이 있는 것 사이에는 밑줄을 그어 표현함
두 개의 피 연산자를 갖는 산술연산자나 논리연산자의 경우에는 연산자와 피 연산자 사이를 한 칸 띄움
단일 피 연산자를 갖는 연산자와 피 연산자 사이에는 공백이 있어서는 안 됨
함수 이름과 시작하는 괄호 사이에는 공백이 있어서는 안 됨
예약어(Reserved Keyword) 뒤에는 공백
한 줄에 오직 한 문장만 코딩
빈 줄을 사용하여 선언 부와 구현 부를 구별
중괄호를 사용하는 방법에는 두 가지 방법이 있음
제어문과 같은 줄에 쓰는 방법과 다음 줄에 쓰는 방법이 있음
제어문과 같은 줄에 쓰는 방법
제어문의 다음 줄에 쓰는 방법
개념
while (foobar != 20)
{
……
}
while (foobar != 20){
……
}
프로그래머는 같은 Source 파일 내에서 두 가지 방법을 혼용하지만 않는다면 어떤 방식을 사용해도 상관없음
복잡하고 긴 복합문장으로 이루어진 제어문 블록이나 함수블록의 처음과 끝을 명확히 알 수 있어야 함
내장된 함수와 매크로를 사용
불필요하게 사용자 정의 함수(기능이 중복되는)를 만들지 않도록 내장함수나 매크로의 기능을 익히는 것이 중요
호환성을 극대화 하기 위해 C의 비표준적인 특성을 사용하지 말 것
C 문법을 재정의하기 위해서 전 처리기(Preprocessor)를 사용하지 말 것
구조체 멤버에 접근할 때 포인터(*)가 필요하지 않다면 사용하지 말 것
예 - 가능하면 -> 연산자를 이용하는 대신 연산자를 이용
잘 알려진 한도 값(예, 버퍼 크기)의 경우, 모듈의 시작 부분에 선언하는 것이 바람직함
전역변수나 상수 정의를 할 경우 찾기 쉽도록 코딩
선언 부와 구현 부를 분리하고, 많은 양의 변수나 상수를 정의할 경우 알파벳 순서대로 할 것
코드의 명확성
조건문에는 반드시 예외사항까지도 처리되어야 함
함수를 만들 때 고려사항
함수의 길이가 너무 길거나 지나치게 짧지는 않은지 여부
인자의 수가 지나치게 많지는 않은지 여부
그 함수의 목적이 충분히 범용적이고, 명확한 목적을 갖고 있는지 여부
효율적인 해결책이 될 수 있는지 여부
다음과 같은 구성은 피해야 함
if(condition)
; /* ie. a null statement */
else
statement;
if (!condition)
statement
단순한 코드의 반복을 피하고 코드를 간단히 하기 위해 프로그램에 알맞는 프로그램 구조와 자료구조를 선택
"#define"에 의해 정의된 상수는 대문자로 쓰고, 불분명한 상수는 "#define"을 사용하여 정의
동적으로 변하는 자료를 사용하지 말고 Sizeof 연산자나 #define된 상수를 사용하여 자료 크기를 미리 정할 것
비정적인(Nonstatic) 변수가 NULL 이나 0으로 초기화 되어 있다고 생각하지 말 것
효율성을 높이기 위한 해결책을 만들었다면 코드를 바꾸기 전에 Time Command를 사용하고 그 코드의 시간 복잡도(Time Complexity)를 측정
효율적인 해결책을 문서화할 것
"?:" 연산자를 주의 깊게 사용하라. 가능하다면 If.... Then.... Else....를 사용하는 것이 명확
If.... Then.... Else....를 사용하는 것이 명확
다중 출구를 갖는 Loop를 주의해서 사용할 것
Break Statement 가 Loop 종결 조건에 합해질 수 있는가?
Continue Statement를 주의해서 사용
Continue Statement에 의해 실행되어지지 않는 어떤 코드를 실행하기 위해 If Statement를 사용할 수 있는가를 생각
공동으로 사용되는 변수를 분리해서 사용하지 말고 구조체를 이용
예 - struct tn
char npa[4];
char nnx[5];
;)
이렇게 관리하는 것이 서로 다른 변수를 사용하는 것보다 Loop 등에서 편리하게 이용
정적인 함수를 사용하고, 전역변수(Global Variable)는 피해야 함
이렇게 함으로써 작성된 함수나 변수가 다른 목적으로 다른 프로그램에서 이용될 때 유용하게 쓰일 수 있음
변수의 범위를 제한해두는 것도 좋은 프로그래밍 방법
변수의 범위를 제한해두는 것도 좋은 프로그래밍 방법
객체지향 프로그래밍
개념
우리 주위의 많은 문제들이 객체를 중심으로한 구조를 가지고 있으며, 객체들 사이의 관계 및 계층 구조로 이루어져 있음
객체지향 언어는 이러한 관점을 나타내는 추상화 과정인 객체지향 분석과 객체지향 설계의 과정을 거쳐 나타난 결과를 작동하는 시스템의 모습으로 보여주는 도구라고 할 수 있음
결국 객체지향 언어를 잘 사용하기 위해서는 개념적인 측면에서부터 실제 동작 과정에 이르기까지 다양한 부분을 이해하지 않으면 안됨
객체지향 언어에서 제공하는 의미와 동작 원리를 정확히 이해하여야만 객체지향 언어로 구현하였을 때 시스템이 원하는 대로 동작할 뿐만 아니라 객체지향 시스템에서 얻을 수 있는 많은 이점
예 – 재 사용성, 확장성, 유지보수성 등
예를 들어 객체지향 언어인 C++ 언어를 단순히 C 언어의 확장이라고 해석할 것이 아니라 객체지향에서 요구되는 근본적인 개념을 이해하고 객체지향적으로 문제를 보는 눈이 있을 때 원하는 객체지향 시스템이 만들어짐
객체지향 언어는 객체지향에서 나타나는 개념들인 객체, 클래스, 캡슐화, 상속, 다형성 등을 지원
객체지향 언어로는 Smalltalk, C 언어를 확장한 C++, Eiffel, Flavors, Object Pascal 등이 있음
프로그래밍 스타일
스타일
어떤 작업이나 선택에서 일관된 유형
- 예 : 패션 스타일
프로그래밍 스타일
간결하고 읽기 쉬운 코드
문형 구조, 원시 코드의 편집 상태 등에 따라 가독성이 달라짐
설계에 의하여 좌우됨
모듈화 - 높은 응집력, 낮은 결합도
명명 원칙
의미 있게 작성
--잘못된 예시----------------------------------------------------
if (a < 65) { // What property does 'a' describe?
y = 65 - a; // What is being calculated here?
}
else {
y = 0;
}
--바른 예시----------------------------------------------------
if (age < RETIREMENT_AGE) {
yearToRetirement = RETIREMENT_AGE - age;
}
else {
yearToRetirement = 0;
}
이름만 보아도 무엇인지(클래스, 멤버함수, 상수 등) 알 수 있게 작성
이름 만들기
원칙
단어 붙이기 1
예 - cylinderLength
클래스 이름은 대문자로 시작 2
변수 이름은 소문자로 시작 3
상수 이름은 모두 대문자로 4
예 - MAX_NAME_LENGTH
Static Final을 사용 5
예 - static final String XML_DOCUMENT = ‘text/XML”;
데이터의 이름은 Underline 6
예 - _timeOfDay
타입 이름
클래스와 인터페이스 이름의 첫 글자는 대문자
public class PrintStream
extends FilterOutputStream {
…
}
public interface ActionListener
extends EventListener {
…
}
메소드 이름
첫 단어는 소문자, 연속되는 단어의 첫 글자는 대문자
class MyImage extends Image {
public MyImage() {
…
}
public void flush() {
…
}
public Image getScaledInstance() {
…
}
}