Presentation is loading. Please wait.

Presentation is loading. Please wait.

소프트웨어 공학 Lecture #8: 코딩 안 병 익 강의 블로그 Mobilecom.tistory.com.

Similar presentations


Presentation on theme: "소프트웨어 공학 Lecture #8: 코딩 안 병 익 강의 블로그 Mobilecom.tistory.com."— Presentation transcript:

1 소프트웨어 공학 Lecture #8: 코딩 안 병 익 biahn99@gmail.com 강의 블로그 Mobilecom.tistory.com

2 학습 목표 2 코딩 원리 코딩 스타일 리팩토링 코드 품질 향상 방법

3 코딩 단계 코딩 작업 각 모듈에 대한 원시코드를 작성하고 모듈 안에 포함된 오류를 검출하는 단계 코딩 원칙 설계를 철저히 반영시킨다 원시코드는 간단 명료하도록 한다 디버깅이 쉽게 시험이 용이 수정이 간편 설계 사양 원시코드 목적코드 코딩 컴파일 디버깅 모듈 테스트 3

4 Weinberg 의 실험 상반되는 원칙을 잘 조화시켜야 함 결과 (1 = 최적 ) O1O2O3O4O5 코딩 작성에 드는 노력의 최소화 (O1) 14453 문장 수의 최소화 (O2) 2-31235 소요 메모리 최소화 (O3) 52144 프로그램 명확성의 극대화 (O4) 43322 출력 명확성의 극대화 (O5) 2-35511 4

5 8.1 코딩 원리 코딩 정의 분리하여 구현할 수 있는 작은 단위를 프로그래밍 하는 작업 절차적 방법 : 모듈 안의 함수 작성 객체지향 방법 : 개별 메소드의 프로그래밍 코딩의 목표 설계 명세에 나타낸 요구를 만족하는 프로그램을 작성  요구분석서, 아키텍처 설계서 참조 오류가 적은 품질 좋은 프로그램 작성  원리와 가이드 준수 5

6 코딩 과정 상세설계 - 의사코드 - 흐름도 각 프레임워크 패키지 또는 애플리케이션 패키지에 대하여... 모든 클래스에 대하여... 요구사항 2. 메소드를 구현 1. 코딩 표준을 정의 4. 단위 테스트 3. 클래스 인스펙션 5. 통합을 위하여 릴리스 아키텍처 6

7 코딩 작업 순서  원시코드를 같은 스타일로 만들기 위한 코딩 표준 작성  아키텍처 설계 결과를 근거로 프레임워크 패키지와 응용 패키지를 구분. 요구사항과 상세설계를 반영하여 메소드 코딩  인스펙션  클래스 단위로 테스트  통합을 위하여 릴리스 7

8 코딩 오류 (1) 오류를 피하기 위하여 오류 타입을 잘 알고 있어야 함 메모리 누수 메모리가 프리되지 않는 현고 프로그램에 계속 할당되는 현상 char * foo(int s) { char *output; if ( s > 0 ) output = (char *) malloc (size); if ( s == 1 ) return NULL; /* if s == 1 then memory leaked */ return(output); } 8

9 코딩 오류 (2) 중복된 프리 선언 이미 프리로 소멸된 자원을 또 다시 프리로 선언하는 경우 NULL 의 사용 NULL 를 포인트하고 있는 곳의 콘텐트를 접근하려 하면 오류 Alias 를 사용하는 경우 유의 main() { char *str; str = ( char * ) malloc (10); if ( global == 0 ) free(str); free(str); /* str is already freed } 9

10 코딩 오류 (3) 별칭의 남용 서로 다른 주소값을 예상하고 사용한 두 변수가 Alias 로 선언된 경우 예 ) strcat(src, destn) src 와 destn 이 alias 로 선언된 경우 char *ch = NULL; if ( x > 0 ) { ch = 'c'; } printf("\%c", *ch); // ch may be NULL *ch = malloc(size); ch = 'c'; // ch will be NULL if malloc returns NULL 10

11 코딩 오류 (4) 배열 인덱스 오류 인덱스 한도를 벗어난 배열 수식 예외 오류 0 으로 나누는 오류, 변동 소수점 예외 오류 하나 차이에 의한 오류 예 ) < N <= 오류 if( number = SSN ) { == 의 오류 dataArray[80]; for ( i=0; i <= 80; i++ ) dataArray[i] = 0; 11

12 코딩 오류 (5) 사용자 정의 자료형 오류 스트링 처리 오류 strcpy, sprintf 등 많은 스트링 처리 함수 매개 변수가 NULL 이거나 스트링이 ‘ \0 ’ 이 아니거나 typedef enum {A, B, C, D} grade; void foo(grade x) { int l, m; l = GLOBAL_ARRAY[x - 1]; // Underflow possible m = GLOBAL_ARRAY[x + 1]; // Overflow possible } 12

13 코딩 오류 (6) 버퍼 오류 버퍼 오류시 리턴 주소가 반환되는 것을 이용하여 해킹에 이용될 수 있음 void mygets(char *str) { int ch; while ( ch = getchar() != '\n' && ch != '\0' ) *(str++) = ch; *str = '\0'; } main () { char s2[4]; mygets( s2 ); } 13

14 코딩 오류 (7) 동기화 오류 다수의 스레드가 있는 병렬 프로그램에서의 오류 데드락 다수의 스레드가 서로 자원을 점유하고 릴리스 하지 않는 상태 레이스 컨디션 두 개의 스레드가 같은 자원을 접근하려 하여 수행 결과가 스레드들의 실 행 순서에 따라 다르게 되는 경우 모순 있는 동기화 공유하는 변수를 접근 할 때 로킹과 언로킹을 번갈아 할 때 일어나는 오류 14

15 구조적 프로그래밍 정의 프로그램의 제어흐름을 선형화시켜 논리구조가 명백하게 하려는 코딩 규 율 구조적 프로그램 세가지 제어구조 ( 순차, 선택, 반복 ) 로 무조건적 goto 에 의한 복잡한 제어흐 름을 방지 제어구조가 하향식 stepwise refinement 를 이용한 프로그래밍 Proper Program 단일입구, 단일 출구 모든 노드는 입구에서 도달할 수 있는 경로가 있어야 모든 노드는 출구까지 도달할 수 있는 경로가 있어야 15

16 Go To 문의 사용 구조적인 제어흐름을 해치지 않는 범위에서 사용 DO 50 I=1, COUNT. IF (ERROR1) GO TO 60. IF (ERROR2) GO TO 70. 50 CONTINUE 60 {Code for Error1 handling} GO TO 80 70 {Code for Error handling} 80 CONTINUE I = 1for I = 1 to TableSize do while I <= TableSize and if Table(I) = Target then goto Found Table(I) <> Target do I = I + 1 NotFound: {code for Target not found} if I > TableSize then Found: {code for Target found} {code for target not found} else { code for Target found} (a) 구조적 코딩 (b) goto 의 사용 16

17 정보 은닉 일반적으로 어떤 정보에 대하여 제한된 방법으로만 사용됨 예 : 회계 원장 ( 차변, 대변, 잔고확인 ) 모든 차변을 더하여 대변의 합으로 나누는 것과 같은 오퍼레이션은 적용되지 않음 자료구조 정의 내부의 정의가 시스템의 다른 부분으로부터 감추어져 있어야 장점 결합도를 줄이고 시스템의 유지보수를 쉽게 만듦 데이터를 관리하는 관점과 데이터를 사용하는 관점을 분리할 수 있음 언어자체의 메커니즘 17

18 8.2 코딩 스타일 스타일 어떤 작업이나 선택에서 일관된 유형 예 ) 패션 스타일 프로그래밍 스타일 간결하고 읽기 쉬운 코드 문형 구조, 원시 코드의 편집 상태 등에 의하여 가독성이 달라짐 설계에 의하여 좌우됨 모듈화 – 높은 응집력, 낮은 결합도 18

19 명명 규칙 명명 원칙 - 의미 있게 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; } 이름만 보아도 무엇인지 ( 클래스, 멤버함수, 상수 등 ) 알 수 있게 19

20 이름 붙이기 단어 붙이기 예 ) cylinderLength 클래스 이름은 대문자로 시작 변수 이름은 소문자로 시작 상수 이름은 모두 대문자로 예 ) MAX_NAME_LENGTH static final 을 사용 예 ) static final String XML_DOCUMENT = ‘text/XML”; 데이터의 이름은 underline 예 ) _timeOfDay 20

21 이름 붙이기 임시변수 문자형 c, d, e 좌표 x, y, z 예외 e 그래픽 g 객체 o 스트림 in, out, inout 스트링 s 약자의 사용 SetDSTOffst() setDstOffset() loadXMLDocument() loadXmlDocument() 21

22 타입 이름 클래스와 인터페이스. 이름의 첫 글자는 대문자 public class PrintStream extends FilterOutputStream {... } public interface ActionListener extends EventListener {... } 클래스 이름은 명사 인터페이스의 이름은 명사나 형용사 능력을 나타내는 인터페이스의 이름은 형용사 “able”, “ible” 22

23 메소드 이름 첫 단어는 소문자, 연속되는 단어의 첫 글자는 대문자 class MyImage extends Image { public MyImage() {... } public void flush() {... } public Image getScaledInstance() {... } 23

24 메소드 이름 메소드와 오퍼레이션은 일반적으로 동작을 나타냄 동사로 표현 class Account { private int balance;... public void withdraw(int amount) { deposit(-1 * amount); } public void deposit(int amount) { this.balance += amount; } 24

25 메소드 이름 boolean isValid() { return this.isValid; } String getName() { return this.name; } String getAlias(int index) { return this.aliases[index]; } void setValid(boolean isValid) this.isValid = is.Valid; } void setName(String name) { this.name = name; } 25

26 변수 이름 첫 문자는 소문자, 연속되는 단어의 첫 문자는 대문자 class Customer {... private Address address; private Phone daytimePhone;... public Address setAddress(Address address) { Address oldAddress = this.address; this.address = address; return oldAddress; }... public void setDaytimePhone(Phone daytimePhone);... }... } 26

27 상수이름 대문자로 하되 단어 사이에는 밑줄로 연결 class Byte { public static final byte MAX_VALUE = 255; public static final byte MIN_VALUE = 0; public static final Class TYPE = Byte.class; } 27

28 포인터와 레퍼런스 C++ 에서는 매개변수를 레퍼런스 타입으로 사용 swap(int &x, int &y) { int t; t=x; x= y; y=t; } new() 의 사용을 피하고 메모리 관리 루틴 getNewCObject() 와 같은 팩 토리 멤버함수 사용 28

29 자료형 객체 타입을 리턴하는 클래스는 캐스트를 사용 public class Queue { public void enque(Object object) {... }; public Object dequeue() {... }; } public class OrderQueue { private Queue queue; public OrderQueue() { this.queue = new Queue(); } public void enqueue(Order order) { this.queue.enqueue(order); } public Order dequeue() { return (Order)this.queue.dequeue(); } 29

30 문장과 수식 되풀이 되는 문장 메소드나 클래스로 패키지화 블록 문장의 사용으로 dangling else 문제 해결 if (x >= 0) if (x > 0) positiveX(); else // Oops! Actually matches most recent if! negativeX() if (x >= 0) { if (x > 0) positiveX(); } else { negativeX(); // This is what we really wanted! } 30

31 문장과 수식 괄호를 이용 오퍼레이션의 순서 명확히 // Extraneous but useful parentheses. int width = (( buffer * offset ) / pixelWidth ) + gap; 객체 동일설 체크 Date today = new Date(); while (date != today) {... } String name;... if (name == "Bob") { hiBob(); } Date today = new Date(); while (!date.equal(today)) {... } String name;... if ("Bob".equals(name)) { hiBob(); } 31

32 오류 처리 잘 못된 데이터를 어떻게 처리할 것인가 ? 예 ) 은행 구좌가 없는 구좌번호 체계적인 접근 방법이 필수 SpecializedVehicle createACar() SpecializedVehicle createATruck() SpecializedVehicle createABus() evaluate( String vehicleP ) // problem with illegal string evaluate( SpecializedVehicle vehicleP ) // parameter value cannot be illegal 32

33 코드 문서화 코드 안의 커멘트 공개 인터페이스 – 사용을 위하여 정확히 문서화 되어야 비공개 인터페이스 – 유지보수 할 수 있도록 문서화 원시코드에 대하여 잘 모르는 것으로 가정하고 문서화 코드와 문서는 항상 일치시켜야 불필요한 것 생략하고 명확하고 간결하게 기술 클래스, 인터페이스, 메소드, 생성자, 필드 정의 앞에 문서화 주석 클라이언트와 서비스 제공자 사이에 프로그래밍 계약관계 (programming contract) 를 정의 33

34 문서화의 사례 /** * The Rectangle2D class describes * a rectangle defined by location (x, y) and dimensions (w, h). *... */ public abstract class Rectangle2D extends RectangularShape { /** * The Double class defines a */ static class Double extends Rectangle2D {... } /** * The bitmask that indicates that a point lies below this Rectangle2D... */ static int OUT_BOTTOM;... /** * Adds a Rectangle2D to this Rectangle2D... */ public void add(Rectangle2D r) {... } /** * This is an abstract class that cannot be instantiated directly... */ protected Rectangle2D() {... }... } 34

35 문서화의 사례 잘못된 사례 public int occurrencesOf(Object item) { // This turned out to be much simpler // than I expected. Let's Go Lions!!! return (find(item) != null) ? 1 : 0; } // Apply a 5% discount to all invoices // over a thousand dollars: if (this.invoiceTotal > 100000) { this.invoiceTotal = this.invoiceTotal * 0.95; // This term corrects for the effects of Jupiter, // Venus, and the flattening of the earch: sigma += (c1 * Angle.sin(a1) + c2 * Angle.sin(Angle.minus(L1, F)) + c3 * Angle.sin(a2) ); 잘된 사례 public int occurrencesOf(Object item) { // This works because no duplicates are allowed: return (find(item) != null) ? 1 : 0; } if (this.invoiceTotal > 100000) { this.invoiceTotal = this.invoiceTotal * 0.95; int cur = 0; // Index of current pattern element int prev = 0; // Index of previous pattern element 35

36 8.3 리팩토링 리팩토링 소프트웨어를 보다 쉽게 이해할 수 있고 적은 비용으로 수정할 수 있도록 겉으로 보이는 동작의 변화 없이 내부구조를 변경하는 것 프로그래밍의 가치 당장 수행되어 작업에 도움이 되는 가치 향후 변경이나 필요에 대비한 가치 코드 스멜 (smell) 읽기 어려운 프로그램 중복된 로직을 가진 프로그램 실행 중인 코드를 변경해야 하는 특별 동작을 요구하는 프로그램 복잡한 조건이 포함된 프로그램 36

37 두 개 모자의 비유 리팩토링 : 두 개의 모자 기능 추가 작업 리팩토링은 신경 쓰지 않고 기능 구현을 위하여 코딩하고 테스트하여 잘 동작 하는지 확인 리팩토링 기능추가에 신경 쓰지 않고 리팩토링, 즉 코드의 구조에만 관심을 기울임 목표에 맞는 작업만 하는 것이 효율적 37

38 리팩토링의 목적 소프트웨어의 디자인을 개선시킴 소프트웨어를 이해하기 쉽게 만듦 버그를 찾는 데 도움을 줌 프로그램을 빨리 작성할 수 있게 도와 줌 38

39 리팩토링 사례 리팩토링 하기 전 void foo(char c) { int i,count,len char str[MAX]; cin>>str len=strlen(str); count=0; for(i=0;i<=len;i++) if(str[i]==c) { count++; str[i]='\n'; } cout<<str<<" "<<count<<"\n"; } 리팩토링 한 후 void foo(char c) { int i,count,len char str[MAX]; cin>>str len=strlen(str); newfun(count,len,str,c); cout<<str<<" "<<count<<"\n"; } newfun(int& count,int len, char* str,char c) { int i; count=0; for(i=0;i<=leni++) if(str[i]==c) { count++; str[i]='\n'; } 39

40 리팩토링 프로세스  소규모의 변경 – 단일 리팩토링  코드가 전부 잘 작동하는지 테스트  전체가 잘 작동하면 다음 리팩토링 단계로 전진.  작동하지 않으면 문제를 해결하고 리팩토링 한 것을 undo 하여 시스 템이 작동되도록 유지. 40

41 41 코드 스멜 41

42 8.4 코드 품질 향상 방법 테스트 이 외에도 더욱 효과적인 방법이 많이 있음 코드 인스펙션 프로그램뿐만 아니라 설계, 분석 등의 문서에서도 오류를 찾아내기 위하여 사용할 수 있는 좋은 검사 방법 정적 분석 방법 프로그램을 실행시키지 않고 텍스트를 조직적으로 분석하여 결함 을 찾아내는 방법 증명 증명 수학 정리처럼 증명 수학 정리처럼 증명 42

43 코드 인스펙션 43

44 정적 분석 방법 대부분의 컴파일러는 제한된 기능이지만 정적 분석을 실행 코드에 존재하는 결함으로 나타날 비정상적인 패턴이나 원하지 않는 패턴을 찾는 방법 자료 흐름이나 논리 흐름을 분석하는 것 자료 흐름 : 자료가 어디서 정의되고 사용되었는지 나타내는 그래프 44

45 정적 분석 방법 정의 변칙 (define anomaly) 정의되지 않고 사용된 변수 사용 변칙 (use anomaly) 정의 되고 사용되지 않는 변 수 45

46 증명 프로그램을 위한 요구와 코드 자체에 기초하여 이루어짐 소프트웨어 품질이 아주 중요한 경우 증명을 사용 결함이 없다는 것을 증명할 정도로 중요한 시스템 항공기 탑재 시스템 원전 제어 시스템 요구 사항에 기초하여 프로그램의 전제조건과 사후 결과를 논리식으 로 표현하여 증명 46

47 증명 사례 // Define I: j <= n-1 < 100 & r = max{g[0], g[1], …, g[j]} // After the following two commands, I is true: int r = g[0]; int j = 0; // This block keeps I true while( j < n-1 ) { if( g[ j+1 ] > r ) r = g[ j+1 ]; ++j; } 47

48 증명 사례 불변조건 I 가 참이다. 루프가 종료된다고 가정하면 종료 시점에는 조 건 j =n-1 이다. 이상을 종합하면 j >=n-1, AND j <= n-1 (from statement I) AND k = max{ a[0], a[1], …, a[j] } (from statement I)..... 48

49 증명 사례 루프가 종료된다고 가정하면 종료 시점에 j < n-1 조건은 더 이상 참이 아니다. 그러나 불변조건 I 는 항상 참이므로 이를 종합하면, j < n-1 is false, AND j <= n-1 (from of statement I), AND r = max{ g[0], g[1], …, g[j] } (from statement I) 따라서 j = n-1 AND r = max{ g[0], g[1], …, g[n-1] } -- 바로 이것이 이 프로그램의 목표. 루프가 종료되는지를 증명하는 것이 남아 있음. 불변조건 I 가 참 이므 로 n-j 는 항상 양수이다. 또한 n-j 는 반복되면서 1 씩 감소된다. 따라서 루프는 언젠가는 종료된다. 49


Download ppt "소프트웨어 공학 Lecture #8: 코딩 안 병 익 강의 블로그 Mobilecom.tistory.com."

Similar presentations


Ads by Google