1장 추상 데이타 타입과 객체 지향 방법

Download Report

Transcript 1장 추상 데이타 타입과 객체 지향 방법

1장
소프트웨어 공학과
프로그래밍 기법
순서
1.1 소프트웨어 생명 주기
1.2 추상 데이터 타입
1.3 알고리즘과 문제 해결
1.4 알고리즘의 표현
1.5 순환
1.6 프로그램 성능 분석
2
1.1 소프트웨어 생명 주기(1)

소프트웨어의 중요 조건



효율성
정확성
소프트웨어 생명 주기 (software life cycle)






요구 분석
시스템 명세
설계
구현
검사
유지 보수
요구 분석
시스템 명세
설계
구현
검사
유지 보수
3
1.1 소프트웨어 생명 주기(2)
1) 요구 분석(requirement analysis)





사용자의 요구 사항을 바탕으로, 문제에 대해 해답이 해답이 될 수
있는 요건 정의
최선의 해결 방법을 위해 상충되는 제약 조건 사이의 장단점과
문제점을 모두 이해하는 데 도움이 됨
목표 소프트웨어의 필수 요건과 선택 요건을 추출하여 구분
요구 명세서(requirement specification) 작성
급여 지불 문제의 예

문제 해결 방법


현금으로 지불 / 컴퓨터로 봉급 수표 발행 / 봉급 수표 수동 발행 /
은행 계좌에 자동 이체
고려 사항

처리 시간 / 비용 / 착오 발생 위험도 / 도난 또는 부정 발생 가능성
4
1.1 소프트웨어 생명 주기(3)
2) 시스템 명세(system specification)


시스템이 무엇을 수행해야 되는가를 정밀하게 정의
기능적 명세(functional specification)를 통해 정의
 소프트웨어의 기능 (입력, 처리, 출력)에 대한 명세 포함
 사용자와 소프트웨어 구축자간의 구체적인 합의 사항

급여 지불의 예







직원 레코드는 디스크 파일에 있는가? 테이프에 있는가?
입력과 출력은 무엇인가?
화일의 각 레코드 양식은 무엇인가?
출력 형식은 무엇인가?
급여 명세를 인쇄하는가?
급여 명세 내용을 저장해 두기 위해 또 다른 테이프가 사용되는가?
공제액을 계산하기 위하여 어떤 알고리즘이 필요한가?
5
1.1 소프트웨어 생명 주기(4)
3) 설계(design)



시스템 명세 단계에서 정의된 기능을 수행할 방법,
즉 소프트웨어 시스템의 전체적인 알고리즘을 설계하는 것
추상적으로 “무엇(what)”에서부터 구체적으로
“어떻게(how)”로의 계속적인 변환을 수행하는 과정
설계 방법

하향식 설계 (top-down design)
 단계별 세분화 (stepwise refinement)라고도 함
 하나의 큰 문제를 여러 개의 작은 문제로 분해함으로써 문제 전체를 해결
 Divide and conquer

상향식 설계 (bottom-up design)
 기존에 개발되어 이용할 수 있는 것들이 있으면 이것을 재사용해
나가면서 전체 목적을 달성하려는 것
 객체지향 설계(object-oriented design) 방법과 유사
6
1.1 소프트웨어 생명 주기(5)
4) 구현(implementation)


설계된 알고리즘을 특정 프로그래밍 언어로 변환 즉, 코딩하는 것
프로그램 구현의 기본 원칙

구조화 프로그래밍 (structured programming)
 지정문, 조건문, 반복문을 이용하여 프로그램 작성
 정확성 증명이 쉬움
 프로그램의 유지 보수와 디버깅(debugging)이 쉬움

모듈러 프로그래밍 (modular programming)
 프로그램을 여러 모듈로 나눠 계층 형태의 관계를 갖도록 구성
 외부에 영향을 주지 않고 모듈 구현을 보다 효율적으로 구현하기 용이
 모듈 (module)
 하나의 기능만을 수행하는 서브 프로그램(subprogram)
 하나의 진입점과 하나의 진출점 가짐
7
1.1 소프트웨어 생명 주기(6)
5) 테스트
 테스트의 목적


테스트의 3단계




단위 검사 (unit test) : 각 모듈별로 제공된 테스트 데이타로 검사
통합 검사 (integration test) : 몇 개의 요소들을 그룹으로 통합시켜 검사
시스템 검사 (system test) : 완성된 시스템이 기능적 명세에 따라 정확하게
동작하는가를 진단
인수 검사 (acceptance test)




소프트웨어에 내재되어 있는 오류를 찾는 것
개발 완료된 소프트웨어를 공식적으로 인수하기 전에 소프트웨어 주문자
측에서 자체 검사 수행
벤치마크 테스트 (benchmark test) : 경쟁적인 시스템과 성능 비교
베타 검사 (beta test) : 초기 버전의 소프트웨어를 배포하여 사용케 함으로써
검출되지 않은 오류나 결함 찾으려는 방법
테스트는 소프트웨어의 정확성(correctness)을 확신하려는 것이지
보장하려는 것이 아님

정확성 보장을 위해서는 프로그램 증명(program verification) 과정 필요
8
1.1 소프트웨어 생명 주기(7)

유지 보수(maintenance)


완성된 소프트웨어 시스템을 사용하기 시작한 뒤부터의
모든 활동
유지 보수가 필요한 경우



테스트 단계에서 발견이 안된 오류나 버그(bug)가 추후
발견되어 수리해야 되는 경우
소프트웨어가 설계될 때의 실제 운영 환경이 바뀌어
소프트웨어를 교정(tuning)해야 되는 경우
시스템 성능 향상이나 사용자의 추가 요구에 따라
소프트웨어를 갱신해야 되는 경우
9
1.1 소프트웨어 생명 주기(8)

데이타의 표현과 이에 적합한 알고리즘의 선정이 중요

효율적이고 정확한 프로그램 작성 좌우
예) 순차 탐색법과 이진 탐색법
 일반적으로 이진 탐색법이 효율적
 하지만 이진 탐색법은 데이타가 값 크기에 따라 정렬되어 있는
경우에만 적용 가능

추상화 (abstraction)


자세한 것은 무시하고 필수적이고 중요한 속성만을
골라서 단순화시키는 과정
데이타 추상화 (data abstraction)


프로그램 속의 복잡한 데이타에 추상화 개념을 적용
기존의 잘 정의된 개념들을 이용하여 표현하는 것이 보통
10
1.1 소프트웨어 생명 주기(9)

데이타
 프로그램의 처리 대상이 되는 모든 것
 특별히 값 (value) 자체를 의미하기도 함

데이타 타입
 데이타의 집합과 이 데이타에 적용할 수 있는 연산의 집합
 종류
 시스템 정의 (system-defined) 데이타 타입
 원시(primitive) 데이타 타입 또는 단순(simple) 데이타 타입
 복합(composite) 데이타 타입 또는 구조화(structured) 데이타 타입
 사용자 정의 (user-defined) 데이타 타입
 기존의 데이타 타입을 이용해 정의
 일단 정의만 되면 시스템 정의 데이타 타입과 똑같이 사용할 수 있음

예) integer 데이타 타입
 데이타 : 정수 (... –2, -1, 0, 1, 2 ...)
 연산자 : +, -, *, /
11
1.2 추상 데이타 타입

추상 데이타 타입 (abstract data type: ADT)


데이타 타입의 논리적 정의
데이타와 연산의 본질에 대한 명세만 정의한 데이타 타입
 데이타가 무엇이고, 각 연산은 무슨 기능을 수행하는가 만을 정의
 데이타의 구조, 연산의 구현 방법은 포함시키지 않음
 기존의 데이타 타입을 이용하여 정의

추상화와 구체화와의 관계
데이타
연산
추상화
추상데이타 타입
(ADT)
알고리즘
구체화
데이타 타입
프로그램
12
1.2 추상 데이터 타입

자연수(Natno) 추상 데이터 타입
ADT Natno
데이타 : { i | i  integer, i  0}
연산자 : for all x, y  Natno
zero() ::= return 0; Natno
isZero(x) ::= if x then return false
else return true;
succ(x) ::= return x+1;
add(x, y) ::= return x+y;
subtract(x, y) ::= if x<y then return 0
else return x-y;
equal(x, y) ::= if x=y then return true
else return false;
End Natno
13
1.3 알고리즘과 문제 해결

알고리즘 (algorithm)


특정 문제를 해결하기 위해 기술한 일련의 명령문
프로그램 (program)

알고리즘을 컴퓨터가 이해하고 실행할 수 있는 특정
프로그래밍 언어로 표현한 것
 Program = algorithm + data structures

알고리즘의 요건

완전성과 명확성
 수행 단계와 순서가 완전하고 명확하게 명세되어야 함
 순수하게 알고리즘이 지시하는 대로 실행하기만 하면 의도한 결과가 얻어져야 함

입력과 출력
 입력 : 알고리즘이 처리해야 할 대상으로 제공되는 데이타
 출력 : 입력 데이타를 처리하여 얻은 결과

유한성
 유한한 단계 뒤에는 반드시 종료
14
1.4 알고리즘의 표현(1)

ADL (Algorithm Description Language)




알고리즘 기술을 위해 정의한 언어
사람이 이해하기 쉽고, 프로그래밍 언어로의 변환이 용이
의사 코드 (pseudo-code) : ADL과 약간의 자연어로 기술한 것
ADL 알고리즘에서 프로그램으로의 변환
A언어
프로그램
ADL
변환기
...
ADL
알고리즘
C언어
프로그램


ADL의 데이타 : 숫자, 부울(boolean)값, 문자
ADL의 명령문 :
 종류 : 지정문, 조건문, 반복문, 함수문, 입력문, 출력문
 명령문 끝에는 세미콜론(;)을 사용
15
1.4 알고리즘의 표현(2)

지정문 (assignment)

형식 : 변수 ← 식;

식 (expression)
 산술식 (arithmetic exp)
 부울식 (Boolean exp)
 결과 : 참(true) 또는 거짓 (false)
 표현
 논리 연산자(and, or, not)
 관계 연산자(<, ≤, =, ≠, ≥, >)
 문자식 (character exp)

제어 구조 : 순차적
16
1.4 알고리즘의 표현(3)

조건문



true
cond
if문


제어 구조 : 선택적
종류 : if문과 case문
if (cond) then S1
else S2
S1
false
S2
case문

case {
cond1 : S1
cond2 : S2
...
condn : Sn
else : Sn+1
}
cond1
false
cond2
true
S1
true
S2
false
...
condn
false
Sn+1
true
Sn
17
1.4 알고리즘의 표현(4)

반복문 (repeat)



제어 구조 : 일정한 명령문 그룹을 반복해서 수행하는
루프(loop) 형태
종류 : while문, for문, do-while문
while문

형식
 while (cond) do
S

무한 루프
 while (true) do
S
cond
true
S
false
18
1.4 알고리즘의 표현(5)

for문

형식
 for (initialization; cond; increment) do
S

동등한 while문
 initialization
while (cond) do {
S
increment;
}

무한 루프
 for ( ; ; ) do
S
(cond의 기정값이 true이므로)
19
1.4 알고리즘의 표현(6)

do-while문

형식
 do
S
S
while (cond);

cond
true
false
특징
 S가 최소한 한 번은 실행됨

루프 명령문


goto 명령문 : 루프에서 바로 빠져나갈 때 사용
exit문 : 자신을 둘러싸고 있는 가장 가까운 루프 밖의
명령문으로 제어를 이동시킴
20
1.4 알고리즘의 표현(7)

함수문

형식
function-name(parameter_list)
S
end

호출 함수로의 복귀
 return expr;
 여기서 expr은 함수의 실행 결과

함수 호출
 function-name(argument-list)
 인자 리스트(argument-list)는 타입과 수에 있어서 함수의 형식 매개 변수와
대응되어야 함

인자와 매개변수와의 연관
 값 호출 (call by value) 규칙
 각 인자의 실제값이 호출된 함수로 전달
 인자의 값이 주소(참조)가 되면 매개 변수에 주소값이 전달되어 값은 데이타 지시
21
1.4 알고리즘의 표현(8)

입력 함수 : read (argument_list);

출력 함수 : print (argument_list);

인자 : 변수나 인용부호가 있는 문자열
22
1.4 알고리즘의 표현(9)

기타 명령문




stop : 현재 진행 중인 함수의 실행을 정지
코멘트 : //는 그 행 끝까지, /*과 */은 코멘트의 시작과 끝
표시
배열 : a[n], a[n1, n2 ], a[n1, n2, , nn]
ADL 기술 규칙






함수의 입  출력 변수를 명확히 명세
변수의 의미를 알 수 있게 정의
알고리즘의 제어 흐름은 되도록 순차적
시각적 구분을 위해 인덴테이션 이용
코멘트는 짧으면서 의미는 명확히
함수를 적절히 사용
23
1.5 순환(1)

순환 (recursion)


정의하려는 개념 자체를 정의 속에 포함하여 이용
종류
 직접 순환 : 함수가 직접 자신을 호출
 간접 순환 : 다른 제 3의 함수를 호출하고 그 함수가 다시 자신을
호출

순환 방식의 적용
 분할 정복(divide and conquer)의 특성을 가진 문제에 적합
 어떤 복잡한 문제를 직접 간단하게 풀 수 있는 작은 문제로
분할하여 해결하려는 방법.
 분할한 문제는 원래의 문제와 그 성질이 같기 때문에 푸는 방법도
동일

순환 함수의 명령문 골격
 if (simplest case) then solve directly
else (make a recursive call to a simpler case);
24
1.5 순환(2)

Factorial (n!)

정의
 n=0 : 1
 n  1 : n  (n 1)   2  1 = n  (n - 1)!

순환 함수의 표현
factorial(n)
// n은 음이 아닌 정수
if (n  1) then return 1
else return (n  factorial(n 1));
end factorial()

비순환 함수로도 표현 가능
 표현이 좀 길지만 제어의 흐름이나 실행 과정을 쉽게 이해할 수
있음
25
1.5 순환(3)

이진 탐색


정의 : 주어진 탐색키 key가 저장된 위치(인덱스) 찾아내는 방법
 key = a[mid] : 탐색 성공, return mid
 key  a[mid] : a[mid]의 왼편에 대해 이진탐색
 key  a[mid] : a[mid]의 오른편에 대해 이진탐색
순환 함수의 표현
binsearch(a[], key, left, right)
if (left  right) then {
mid  (lift + right) / 2;
case {
key = a[mid] : return (mid);
key  a[mid] : return (binsearch(a, key, left, mid 1));
key  a[mid] : return (binsearch(a, key, mid+1, right));
}
}
else return -1; // key 값이 존재하지 않음
end binsearch()
26
1.5 순환(4)

피보나치 수열 (Fibonacci sequence)


각 항은 바로 직전 두 항의 합으로 만들어짐
순환 정의
 n=0 : f0
 n=1 : f1
 n  2 : fn = fn-1 + fn-2

순환 함수의 표현
fib(n)
if (n  0) then return 0;
else if (n=1) then return 1
else return (fib(n 1) + fib(n 2));
end fib()

이 fib() 함수는 순환 호출이 증가하여 실행시간으로 볼 때
반복적 함수보다 비효율적임
 환적 정의가 순환적 알고리즘으로 문제를 해결하는 데 최적의
방법이 아닐 수도 있다는 예
27
1.6 성능 분석 (1)

프로그램의 평가 기준







원하는 결과의 생성 여부
시스템 명세에 따른 올바른 실행 여부
프로그램의 성능
사용법과 작동법에 대한 설명 여부
유지 보수의 용이성
프로그램의 판독 용이
프로그램의 성능 평가

성능 분석 (performance analysis)
 프로그램을 실행하는데 필요한 시간과 공간의 추정

성능 측정 (performance measurement)
 컴퓨터가 실제로 프로그램을 실행하는데 걸리는 시간 측정
28
1.6 성능 분석 (2)

공간 복잡도 (space complexity)


프로그램을 실행시켜 완료하는데 소요되는 총 저장 공간
Sp = Sc + Se
 Sc : 고정 공간
 명령어 공간, 단순 변수, 복합 데이타 구조와 변수, 상수
 Se : 가변 공간
 크기가 변하는 데이타 구조와 변수들이 필요로 하는 저장 공간
 런타임 스택(runtime stack)을 위한 저장 공간

시간 복잡도 (time complexity)


프로그램을 실행시켜 완료하는데 걸리는 시간
Tp = Tc + Te
 Tc : 컴파일 시간
 Te : 실행 시간
 단위 명령문 하나를 실행하는데 걸리는 시간
 실행 빈도수 (frequency count)
29
피보나치수의 예 (1)

n번째 항을 계산하는 반복식 프로그램
1-2
3-4
5-6
7
8
9
10
11
12
fib_i(n)
if (n < 0) then stop; // error 발생
if (n ≤ 1) then return n;
fn2 ← 0; fn1← 1;
for (i←2; i<=n; i←i+1) do {
fn ← fn1 + fn2;
fn2 ← fn1;
fn1 ← fn;
}
return fn;
13
end fib_i()
30
피보나치수의 예 (2)
계산을 위한 실행 빈도수
 fn
명령문(행) 실행 빈도수 명령문(행) 실행 빈도수
1
1
8
n-1
2
0
9
n-1
3
1
10
n-1
4
0
11
0
5
1
12
1
6
1
13
0
7
n

실행 시간


4n+2 : O(n)
“함수 fib_i()의 시간 복잡도는 O(n)이다”라고 말함
31
점근식 표기법 (1)

점근식 표기법(Asymptotic notation)




Big-Oh (O)
Big-Omega ()
Big-Theta ()
Big-Oh (O)


f, g가 양의 정수를 갖는 함수일 때, 두 양의 상수 a, b가
존재하고, 모든 nb에 대해 f(n)  a  g(n) 이면, f(n) =
O(g(n))
예




f(n) = 3n + 2
f(n) = 1000n2 + 100n - 6
f(n) = 6 • 2n + n2
f(n) = 100
: f(n) = O(n) (a=4, b=2)
: f(n) = O(n2) (a=1001, b=100)
: f(n) = O(2n) (a=7, b=4)
: f(n) = O(1) (a= 100, b=1)
32
점근식 표기법 (2)

연산 시간 그룹
상수시간 : O(1)
 로그시간 : O(logn)
 선형시간 : O(n)
 n로그시간 : O(nlogn)
 평방시간 : O(n2)
 입방시간 : O(n3)
 지수시간 : O(2n)
 계승시간 : O(n!)


연산 시간의 크기 순서
O(1)  O(logn)  O(n)  O(nlogn)  O(n2)  O(n3)  O(2n)  O(n!)

O(nk ) : polynomial time
33
점근식 표기법 (3)

Big-Omega ()


f, g가 양의 정수를 갖는 함수일 때,
두 양의 상수 a, b가 존재하고, 모든 nb에 대해 f(n)  a 
g(n) 이면,
f(n) = (g(n))
예
 f(n) = 3n + 2
 f(n) = 1000n2 + 100n - 6
 f(n) = 6 • 2n + n2
: f(n) = (n) (a=3, b=1)
: f(n) = (n2) (a=1000, b=1)
: f(n) = (2n) (a=6, b=1)
34
점근식 표기법 (4)

Big-Theta()


f, g가 양의 정수를 갖는 함수일 때,
세 양의 상수 a, b, c가 존재하고, 모든 nc에 대해
a  g(n)  f(n)  b  g(n) 이면, f(n) = (g(n))
예
 f(n) = 3n + 2
 f(n) = 1000n2 + 100n - 6
 f(n) = 6 • 2n + n2
: f(n) = (n) (a=3, b=4, c=2)
: f(n) = (n2) (a=1000, b=10001, c=100)
: f(n) = (2n) (a=6, b=7, c=4)
35
fib_i()의 예

점근적 복잡도의 계산
세그먼트 점근적 복잡도
1~6
O(1)
7~11
O(n)
12~13
O(1)
T(Fib_i) = O(1) + O(n) + O(1) = O(n)

예






O(1) + O(1) = O(1)
O(1) + O(n) = O(n)
O(n) + O(n) = O(n)
O(n) + O(n2) = O(n2)
O(1) + O(n) + O(n2) = O(n2)
실행 환경


최선의 경우 (best case)
최악의 경우 (worst case)
36
Summary
1.1 소프트웨어 생명 주기
1.2 추상 데이터 타입
1.3 알고리즘과 문제 해결
1.4 알고리즘의 표현
1.5 순환
1.6 프로그램 성능 분석
37