Upload
jaeyeoul-ahn
View
50
Download
8
Embed Size (px)
Citation preview
Working with Code
Kookmin UniversityGraduate School of Busuness IT
e-Government System Development석사과정 1학기 안재열
Contents
Identifying
“bed smell”Refactoring
13가지소개 및 코드확인
4가지소개 및 코드확인
테스팅종류
Testing Debugging
+ Extending the Software for a New Project
테스팅종류UnitTestxUnitTDD 소개 및 코드
디버깅종류UnitTestIDE사용확인 – 2가지
Four central activities for Coding
Identifying
“bed smell”Refactoring
Coding/
Debugging
Testing DebuggingRefactoringTesting
Bad Smells
What is the Bad Smells?
-> A bad smell is a segment of code that doesn’t readclearly and concisely.
코드가 명확하지 않고 간결하지도 않다.
Bad Smells
What is the Bad Smells?
Kinds of Bad Smells in the code
1) Poorly Named 9) Lazy Class
2) Duplicate Code 10) Speculative Generality
3) Long Method 11) Temporary Fields
4) Large Class 12) Inappropriate Intimacy4) Large Class 12) Inappropriate Intimacy
5) Too Many/Few comments 13) Incomplete Class
6) Data Clump 14) Refused Bequest
7) Parallel Inheritance Hierarchies 15) Feature Envy
8) Primitive Obsession
Bad Smells
1) Poorly Named
-> Variable, method or Class name does not clearlyrepresent its purpose in the code
<?php
class A{public $li1;
class A{public $li1;public function s(){$abcd = $this->li1 * 10;return $abcd;
}}?>
Bad Smells
2) Duplicate Code
-> the same sequence of expression orinstruction appears in several places.
<?php
class SumMyScore{public $math1, $math2;
public function Scoring3(){$result = $this->math1 * 10;$result + 100;return $result;
}public function Scoring1(){$result = $this->math1 * 10;$result + 1;return $result;}
public function Scoring2(){$result = $this->math1 * 10;$result + 10;return $result;}
}
public function Scoring3(){$result = $this->math1 * 10;$result + 600;return $result;
}
}#class end?>
Bad Smells
3) Long Method
-> A method contains a lot of codethat accomplishes several sub-task
<?php
class MyBestWay{public $startpoint, $endpoint;
public function finding(){public function finding(){$result = $this->math1 + $this->math2 ;$result = $result / 2;$result splice($result);
….+ 최단거리알고리즘 + sort + …return $result;}
} #class end?>
Bad Smells
4) Large Class
-> A class has an unusually and diverse collection of instance variablesor methods.
<?php
class Vehicle{public $size, $color, $weight, $cost;public $engine; #자동차, 비행기, 오토바이public $Wings; #비행기
범위가 너무 커서 인스턴스 변수와 메소드의
public $Wings; #비행기public $feed, age; #말
….public function flying(){}public function jumpStart(){}public function kickStart(){}public function eatting(){}
……
} #class end?>
턴스 변수와 메소드의개수가 엄청나게 커진다.
따라서 중복코드의 문제 또한 발생 할 수가있다.
Bad Smells
5) Too many or few Comments
-> Too many comments can hide bad code.Too few comments can make code difficult to read.
<?php
class Vehicle{public $size, $color, $weight, $cost;public $engine; #자동차, 비행기, 오토바이public $Wings; #비행기public $feed, $age; #말public $feed, $age; #말
….# flying() 메소드를 사용하실경우에는 vehicle클래스를 사용한 인스턴스들 중 하늘을 나는 경우#에 한하여 사용하실 수 있습니다. kicKStart() 메소드의 경우에는 멤버변수 $engine을 사용하게#되며 두 바퀴가 달린 이륜차에 한하여 이용하실 수 있습니다. eatting()메소드의 경우에는 말과#같은 생물에 한해 사용하실수 있으며, 메소드에서 사용되는 멤버변수로는 $feed, $age가 있습#니다.
public function flying(){}public function jumpStart(){}public function kickStart(){}public function eatting(){}
……} #class end
?>
Bad Smells
5) Too many or few Comments
-> Too many comments can hide bad code.Too few comments can make code difficult to read.
<?php
class Vehicle{public $size, $color, $weight, $cost;public $engine;public $engine;public $Wings;public $feed, $age;
public function flying(){}public function jumpStart(){}public function kickStart(){}public function eatting(){}
……} #class end
?>
321
Bad Smells
5) Data Clumps
-> The same three or four variables appear together in several differentplace.
Class A Class B Class C
Bad Smells
6) Feature Envy
-> A method requires lots of information from a different class
class First{public static $temp;public function __construct(){$this->temp = new Second();
class Second{public $maxSize = 10;public $minSize = 2;public function maxCal($value){$this->temp = new Second();
}public function maxCal($value){return $temp->maxCal($value);}
public function minCal($value){$result = $value * $temp->minSize;return $result;}}
public function maxCal($value){$result = $value * $this->maxSize;return $result;
}}
Bad Smells
7) 기본타입에 대한 강박관념 Primitive Obsession
->the code is reluctant to use classes instead of primitive data types.OOP에서 클래스 사용보다, 기본타입을 우선 고려 할 경우의 문제.
$Students = array();array_push($Student, “Tom”); //namearray_push($Student, 20); //agearray_push($Student, “Male”);//Genderarray_push($Student, “Swimming”); //hobby 배열내의 요소가
.
.
.
array_push($Student, “Swimming”); //hobbyarray_push($Student, true);//자취여부array_push($Student, 7);//좋아하는 숫자
$Students2 = array();array_push($Student, “Emily”); //namearray_push($Student, 24); //agearray_push($Student, “Female”);//Genderarray_push($Student, false); //자취여부array_push($Student, 24);//좋아하는 숫자....
배열내의 요소가많아 질 수록
코딩 시 헷갈릴 수있다.
Bad Smells
8) Lazy Class
->클래스를 생성할 때마다, 그것을 유지하고 이해하기 위한 비용이 발생한다.이 비용을 감당할만큼 충분한 일을 하지 않는 클래스는 삭제되어야 한다.
Person TelephoneNumber
->리팩토링 이후 기능이 축소되거나 쓸모 없어진 클래스
Person
name
getTelephoneNumber()
TelephoneNumber
areaCodenumber
getTelephoneNumber()
사용1회
사용1회
총 2회
Bad Smells
8) Lazy Class
class Person{private $_name; //이름private $_officeTelephoneNumber = new TelephoneNumber(); //회사전화(객체)
public function getName(){return $this->_name;
}
//전화번호가져오기 -> 전화객체에서public function getTelephoneNumber(){return $this->_officeTelephoneNumber->getTelephoneNumber();
}//전화객체가져오기 ->전화객체에서funcion getOfficeTelephone(){return $this->_officeTelephoneNumber;}
}
Bad Smells
8) Lazy Class
class TelephoneNumber{private $_number; // 개인고유번호private $_areaCode; // 지역번호//전화번호 가져오기 ; 지역번호 + 개인고유번호public function getTelephoneNumber(){return “(“.$this->_areaCode.”) ”. $this->_number
}public function getAreaCode(){return $this->_areaCode;return $this->_areaCode;
}
public function setAreaCode($arg){$this->_areaCode = $arg;
}public function getNumber(){return $this->_number;
}
public function setNumber($arg){$this->_number = $arg;
}}
Bad Smells
8) Lazy Class
->클래스를 생성할 때마다, 그것을 유지하고 이해하기 위한 비용이 발생한다.이 비용을 감당할만큼 충분한 일을 하지 않는 클래스는 삭제되어야 한다.
-> 추후에 기능이 확장되거나, 활용될 가치가 없다고 판단되면 Lazy Class!
Person
name
getTelephoneNumber()
TelephoneNumber
areaCodenumber
getTelephoneNumber()
Bad Smells
9) 추측성 일반화 (Speculative Generality)
->일어날 가능성이 거의 없는 일까지 다 대비한 필요없는 코드들은 제거하라. 모든 기능들과 절차들은 제대로 이용되었을 때 쓸모가 있다.
Class Test
만약을 위한 멤버변수 1만약을 위한 멤버변수 2만약을 위한 멤버변수 3만약을 위한 멤버변수 4만약을 위한 멤버변수 4……만약을 위한 멤버변수 100
만약을 위한 메소드 1만약을 위한 메소드 2만약을 위한 메소드 3….If 만약을 위한 분기문 1If 만약을 위한 분기문 2If 만약을 위한 분기문 3……
Bad Smells
10) 임시 필드 (Temporary Field)
->때로는 어떤 객체 안의 인스턴스 변수가 특정 상황에서만 세팅되는 경우가 있다. 보통은 객체의 모든 변수가 값을 가지고 있을 거라고 기대하기 때문에 이런 코드는 이해하기 어렵다.
Student
$Name //학생이름$AGE // 학생나이$AGE // 학생나이$height // 학생키$temp // 평균 낼 때 사용되는 임시변수$temp2 // function4와 5, 8에서 사용되는 임시변수….
Function 1(){}Function 2(){}Function 평균(){}Function 4(){}……
Bad Smells
11) 지나친 관여(Inappropriate Intimacy)
-> 간혹 클래스끼리 관계가 지나치게 밀접한 나머지 서로의 private 를 알아내느라 시간을 낭비하게 되는 경우가 있다.
A
Private $a
B extends C
Private $b
C
Private $c =new D().getD();
Protected getC()Private $a
Public getA()
Private $b= new C().getC()
Public getB()
Protected getC()
D
Private $d = 1
Protected getD()
Protected1. 같은 package 내의 모든 클래스에서 접근가능2. 다른 패키지의 클래스라도 해당클래스 상속시 접근가능
Bad Smells
12) 불완전한 클래스 (Incomplete Class)
-> One that doesn’t do everything you need.
Sort
MemberQuick Sort?
Membervariables.
BubbleSelectInsertionMerge...
Quick Sort?오름차순?
Bad Smells
13) 방치된 상속물 (Refused Bequest)
-> 서브클래스는 메소드와 데이터를 그 부모 클래스로부터 상속 받는다.그러나 만약 서브클래스가 그들에게 주어진 것을 원치 않는다거나,필요하지 않는 경우.
Parents
function a
SonA
function a //상속
function b
GrandSonAA
function a //상속
function b//상속
function c
GrandSonAB
SonB
function a //상속
function b
GrandSonBA
Software Metrics
- 소프트웨어의 Quality를 평가 할 수 있는 방법 4가지
• Pakages, classes, instance variables, methods, paramethers, lines
• 적당하고 자연스럽게 적을수록 좋다.
Count (수량)
• 메소드 안에서의 분기문 및 제어문의 수량. //
• 많을수록 복잡하다. 한 메소드안에는 10개 미만으로 유지하는게 좋다.
Clarity (명확성)
• 하나의 단위 내에서, 한 기능을 수행하기 위해 각 구성 요소들이 가까이 있는 경우
• 모듈은 응집도를 높이기 위한 방안 중 하나.
• OOP는 정적인데이터와 동작을 함께 묶어 객체를 정의함으로써 높은 응집도를 얻음
• 4장에서 LCOM 의 값이 0에 가까울 수록 응집도가 높음
Cohension (응집도)
• 코드기반의 패키지(모듈,클래스,함수,라이브러리등)이 얼마나 독립적으로 움직일 수 있는가?
Coupling (결합도)
Refactoring
1. 메소드 정리
2. 객체나 클래스 사이의 이동
3. 데이터의 재구성
4. 조건문을 이해하기 쉽게 단순화4. 조건문을 이해하기 쉽게 단순화
5. 메소드 호출 단순화
6. 상속관계 재구성
Refactoring
How to do ?
1) Renaming 7) Simplifying conditionals
2) Extracting a method 8) Removing Useless Code
3) Extracting a methods 9) Removing Violations to Layering Principles
4) Reorganizing a class 10) Merging Similar Functions /Modules4) Reorganizing a class 10) Merging Similar Functions /Modules
5) Unifying data clumps 11) Separating Model, View, Controller Code
6) Removing a parameter
Refactoring - Renaming
네이밍 관례와 표준
파스칼 표기법
"PascalCase"
"쌍봉낙타" 표기법
첫 단어를 대문자로 시작하는 카멜 표기법첫 단어를 대문자로 시작하는 카멜 표기법
예시:
BackgroundColor, TypeName, PowerPoint
Refactoring - Renaming
네이밍 관례와 표준
카멜 표기법"camelCase""단봉낙타" 표기법
첫글자는 소문자,단어와 단어 만나면 첫 글자 -> 대문자단어와 단어 만나면 첫 글자 -> 대문자띄어쓰기 대신 대문자로 단어를 구분하는표기 방식
예시:backgroundColor, typeName, iPhone
Refactoring - Renaming
네이밍 관례와 표준
헝가리안 표기법
-. 헝가리안 개발자가 창시-. 변수명 맨 앞에 자료형을 명시함
예시:예시:-. iNum, iCnt, dAmount //
int ,int, double
언더바 표기법(Underbar Notation), Snake Notaion-. 단어와 단어 사이에 언더바-. user_name
Refactoring - Renaming
네이밍 관례와 표준
1.1. 클래스 명에는 파스칼 표기법을 사용한다.
public class HelloWorld{...}
1.일반적으로 클래스이름은 명사명사들의 조합혹은 형용사형용사 ++ 명사로명사로지정한다.}
1.2. 함수(Method) 명에는 카멜 표기법을 사용한다.
void sayHello(string name){...}
지정한다.
2. 메소드는 동사동사 ++ 명사명사의의 형태로 지정하는 것이 일반적이다.
Refactoring - Renaming
네이밍 관례와 표준
올바른 클래스명의 예
class LoginAction;
class HTTPRequest; : 축약어는 모두 대문자로 사용(HTTP는 범용적으로 사용되는 축약어)
abstract class AbstractUserInformation;
잘못된 클래스명의 예
class GSL; : 정확하게 약어의 뜻을 유추할 수 없음
class my_action; : 클래스 명이 소문자로 시작되어 클래스 명 식별이 쉽지 않고,
밑줄을 사용하여 자바 API와 일관성이 떨어짐
class 사용자; : 한글을 클래스 명으로 사용할 경우 일부 OS에서 클래스를 읽을 수 없음
class DoIt; : 클래스는 하나의 엔티티(entity)를 뜻하므로, 어떠한 행동을 기술하는
동사를 사용할 경우, 클래스의 정확한 용도를 유추하기가 어려움
Refactoring - Renaming
올바른 메소드명의 예
Customer getCustomer();void drawCircle(int x, int y, int radius);boolean isLive()//boolean의 경우 is를 주로 앞에 붙인다.
클래스 명과 마찬가지로 범용적으로 통하는 경우를 제외하고는 되도록 축약어클래스 명과 마찬가지로 범용적으로 통하는 경우를 제외하고는 되도록 축약어를 사용하지 않는 것을 원칙으로 하며, 부득이하게 사용해야 할 경우 축약어는모두 대문자로 지정한다. 예) HTTP, ID
HTTPHeader getHTTPHeader();void setMessageID(MessageID msgID);
Refactoring - Renaming
네이밍 관례와 표준
1.3. 변수와 함수 파라미터에는 카멜 표기법을 사용한다.
int totalCount = 0;void SayHello(string name){{string fullMessage = "Hello " + name;...}
Refactoring - Renaming
네이밍 관례와 표준
1.4. 인터페이스에는 접두사 "I"가 포함된 파스칼 표기법을 따른다.
예 : IEntity
1.5. 변수명에 헝가리안 표기법을 사용하지 않는다.
이전에는 많은 프로그래머들이 변수명에 데이터 타입에 해당하는 접두사를 첨가하였다. 즉, 멤버변수에는 아래와 같이 m_ 을 접두사로 사용하는 것과 같은 헝가리안표기법을 사용했었다.
string m_sName;int nAge;
Refactoring - Renaming
네이밍 관례와 표준
1.6. 변수에 모든 의미를 충분히 담아라(약어를 사용하지 말것).
- 좋은 예string addressint salary
- 나쁜 예string namstring addrstring addrint sal
1.7. "i, n, s,..."와 같이 한 글자로 된 이름을 사용하지 말것.
i, n, s 보다는 index, temp 와 같은 이름을 사용한다.
한 가지 예외가 있다면 루프에서 반복을 의미하는 변수를 허용하는 경우이다.for ( int i = 0; i < count; i++ ){...}
Refactoring - 10) Merging Similar Functions
8) Lazy Class
->클래스를 생성할 때마다, 그것을 유지하고 이해하기 위한 비용이 발생한다.이 비용을 감당할만큼 충분한 일을 하지 않는 클래스는 삭제되어야 한다.
->추후에 기능이 확장되거나, 활용될 가치가 없다고 판단되면 Lazy Class!
Person
name
getTelephoneNumber()
TelephoneNumber
areaCodenumber
getTelephoneNumber()
Refactoring - 10) Merging Similar Functions
8) Lazy Class
class Person{private $_name; //이름private $_officeTelephoneNumber = new TelephoneNumber(); //회사전화(객체)
public function getName(){return $this->_name;
}
//전화번호가져오기 -> 전화객체에서public function getTelephoneNumber(){return $this->_officeTelephoneNumber->getTelephoneNumber();
}//전화객체가져오기 ->전화객체에서funcion getOfficeTelephone(){return $this->_officeTelephoneNumber;}
}
Refactoring - 10) Merging Similar Functions
8) Lazy Class
class TelephoneNumber{private $_number; // 개인고유번호private $_areaCode; // 지역번호//전화번호 가져오기 ; 지역번호 + 개인고유번호public function getTelephoneNumber(){return “(“.$this->_areaCode.”) ”. $this->_number
}public function getAreaCode(){return $this->_areaCode;return $this->_areaCode;
}
public function setAreaCode($arg){$this->_areaCode = $arg;
}public function getNumber(){return $this->_number;
}
public function setNumber($arg){$this->_number = $arg;
}}
Refactoring - 10) Merging Similar Functions
class Person{ //논리적 개념의 범위가 더욱 큰 Person으로 변경private $_number; // 개인고유번호private $_areaCode; // 지역번호private $_name; //이름, 원래 Person의 것
//전화번호 가져오기 ; 지역번호 + 개인고유번호public function getTelephoneNumber(){return “(“.$this->_areaCode.”) ”. $this->_number}
public function getAreaCode(){return $this->_areaCode;}
public function setAreaCode($arg){$this->_areaCode = $arg;}
public function getNumber(){return $this->_number;}
public function setNumber($arg){$this->_number = $arg;}
public function getName(){ //원래 Person의 것return $this->_name;
}}
Refactoring - 2) Extracting a method
Motive :메서드가 너무 길거나, 코드에 주석을 달아야만 의도를 이해할 수 있을 때 필요하다.( Bed Smell - Long Method, Too Many comments)
Why?
-> 1. 메서드가 적절히 잘게 쪼개져 있으면 다른 메서드에서 쉽게 사용 할 수 있다.
2. 재정의하기 쉽다2. 재정의하기 쉽다
Refactoring - 2) Extracting a method
How to?
-> 1. 목적에 부합하는 이름의 새 메서드를 생성한다.이때 메서드명은 원리가 아니라 기능을 나타내는 이름이어야 한다.
2. 기존 메서드에서 빼낸 코드를 새로 생성한 메서드로 복사한다.
3. 추출한 코드에서 기존 메서드의 모든 지역변수 참조를 찾는다.그것들을 새로 생성한 메서드의 지역변수나 매개변수로 사용 할 것이다.그것들을 새로 생성한 메서드의 지역변수나 매개변수로 사용 할 것이다.
4. 추출한 코드내에서만 사용되는 임시변수가 있다면,이를 새로생성한 매서드 안에 임시변수로 선언한다.
.
.
.
Refactoring - 2) Extracting a method
Enumeration컬렉션인 Vector, Hash의 elements 를 열거하는인터페이스
import java.util.Vectorimport java.util.Enumeration
public class Test{public static void main(String[]args){
Vector vt = new Vector();vt.add("one");vt.add(2);vt.add("셋");Enumeration et = vt.elements();while(et.hasMoreElements()){System.out.print(et.nextElement()+" ");}
}}
결과 :one 2 셋
Refactoring - 2) Extracting a method
Order
-Double amount //외상값 합-Date
+getAmount(); //
HostPrint
+ printOwing(){}+getAmount(); //+getDate();
Refactoring - 2) Extracting a methodOrder
-Double amount //외상값 합-Date
+getAmount(); //+getDate();
HostPrint
-String _name
+ printOwing(){}
void printOwing() {Enumeration e = _orders.elements();double outstanding = 0.0;
//배너 출력System.out.println (“****************”);System.out.println (“*****고객외상*****”);System.out.println (“*****고객외상*****”);System.out.println (“****************”);
//외상액 계산while (e.hasMoreElements()){Order each = (Order) e.nextElement(); //elements 추출outstanding += each.getAmount(); // elements였던 Order객체의 외상값합계추출}
//세부내역 출력System.out.println (“고객명 : ”+_name);System.out.println (“외상액 : ”+outstanding);
}
Refactoring - 2) Extracting a method
void printOwing() {Enumeration e = _orders.elements();double outstanding = 0.0;
printBanner();
//외상액 계산while (e.hasMoreElements()){Order each = (Order) e.nextElement();outstanding += each.getAmount();}
//세부내역 출력System.out.println (“고객명 : ”+_name);System.out.println (“외상액 : ”+outstanding);
}
void printBanner(){//배너 출력System.out.println (“****************”);System.out.println (“*****고객외상*****”);System.out.println (“****************”);
}
Refactoring - 2) Extracting a method
void printOwing() {Enumeration e = _orders.elements();double outstanding = 0.0;printBanner();printDetails(outstanding);
//외상액 계산while (e.hasMoreElements()){Order each = (Order) e.nextElement();outstanding += each.getAmount();}
}}void printBanner(){//배너 출력System.out.println (“****************”);System.out.println (“*****고객외상*****”);System.out.println (“****************”);
}void printDetails(double outstanding){//세부내역 출력System.out.println (“고객명 : ”+_name);System.out.println (“외상액 : ”+outstanding);
}
Refactoring - 2) Extracting a method
void printOwing() {
double outstanding = getOutstanding(); // 변수 초기값은 확실한 경우만 메모리에 할당된다.printBanner();printDetails(outstanding);}}void printBanner(){//배너 출력System.out.println (“****************”);System.out.println (“*****고객외상*****”);System.out.println (“****************”);
}void printDetails(double outstanding){//세부내역 출력//세부내역 출력System.out.println (“고객명 : ”+_name);System.out.println (“외상액 : ”+outstanding);
}
double getOutstanding(){//외상액 계산Enumeration e = _orders.elements(); //외상액 계산시만 사용될 예정이므로 local variable로double result = 0.0; // 지역변수 및 임시변수이므로 변수명 혼동을 피하기 위해 변경while (e.hasMoreElements()){Order each = (Order) e.nextElement();result += each.getAmount();
}return result;}
Refactoring - 2) Extracting a method
void printOwing(double previousAmount) {
double outstanding = previousAmount * 1.2;outstanding = getOutstanding(); // 변수 초기값은 확실한 경우만 메모리에 할당된다.printBanner();printDetails(outstanding);}}void printBanner(){//배너 출력System.out.println (“****************”);System.out.println (“*****고객외상*****”);System.out.println (“****************”);
}void printDetails(double outstanding){}void printDetails(double outstanding){//세부내역 출력System.out.println (“고객명 : ”+_name);System.out.println (“외상액 : ”+outstanding);
}
double getOutstanding(){//외상액 계산Enumeration e = _orders.elements(); //외상액 계산시만 사용될 예정이므로 local variable로double result = 0.0; // 지역변수 및 임시변수이므로 변수명 혼동을 피하기 위해 변경while (e.hasMoreElements()){Order each = (Order) e.nextElement();result += each.getAmount();
}return result;}
Refactoring - 9) Removing Violations to Layering Principles
dbPersons.php
PHP는 Dynamic Typing이 가능하다. 따라서 변수의 타입지정은값 할당 뒤 일어난다. -> 응용가능.(※내부 logic은 유사하다는 전제.)
Refactoring - 9) Removing Violations to Layering Principles
dbPersons.php
Parameter 2개인 함수는없어서 새로 만듬
Testing – 종류
• 보통 단위테스트 혹은 Unit Test라고 부른다.
• 모듈이나 객체, 프로그램과 같이 개별적으로 테스트가 가능한 단위에 대해서 테스트
• 우리나라 SI 거의 안 함
Component Test (컴포넌트 테스트)
• 컴포넌트 사이의 인터페이스를 테스트하는 것을 의미한다.
Integration Test (통합테스트)
• 컴포넌트 사이의 인터페이스를 테스트하는 것을 의미한다.
• UI와 서버 부분을 묶거나, 기능 사이에 연결관계를 테스트한다.
• 개발된 시스템이 제대로 동작하는지 확인.
System Test (시스템테스트)
• 고객이 원하는 대로 만들었는지 확인
Acceptance Test (인수테스트)
Testing – 종류
• 보통 단위테스트 혹은 Unit Test라고 부른다.
• 모듈이나 객체, 프로그램과 같이 개별적으로
테스트가 가능한 단위에 대해서 테스트
• 우리나라 SI 거의 안 함. – 착각함.
Component Test
(컴포넌트 테스트)
서비스 개발자는 jsp에서의 문제인지, class에서의 문제인지 확인가능
화면테스트 AddMovie.jsp AddManager.class
테스터는 전체의 과정을 알기 힘들다.
STUB
DRIVER
Testing – Unit test
Stub, driver =단위마다 테스트 코드(함수,메소드 작성)
(※DB의 경우 CRUD에 맞춰서)
개별 메소드마다 실행된다.개별 메소드마다 실행된다.예) Echo 기능의 메소드일경우 echo 실행.※만약 10000개 존재?->1만라인 실행 및 1만번 수행
Testing – Unit testUnitTestCase
….
generate_new_shift()assertEqual()assertTrue()assertFalse()…
테스트 메소드를모아놓은 클래스를 만든 후
상속시킨다.
Class TestSuite
Testing – Test suite
A test suite is a collection of “unit tests”
Class 1
메소드A
C
testA
Class 2
C
B
testC
testB
Testing – xUnit
Unit test를 위한 Framework.
xUnits Languages
JUnit, TestNG Java
NUnit,csUnit,MbUnit,MSTest
.NET
Test::Unit Ruby
CUnit CCUnit C
CppUnit C++
PHPUnit PHP
PyUnit Python
DbUnit Database
utPLSQL PL/SQL
leUnit JavaScript,DHTML
Test Driven Development - TDD
What? –Test the program before you write it. – Kent Beck프로그램 작성하기 전에 테스트 먼저 하라!
디자인 개발 테스트
기존 개발 절차
TestScript
개발개발 리팩토링
TDD 개발 절차
Test Driven Development - TDD
What?
TestScript
개발개발 리팩토링
1. TDD는 코드를 먼저 만드는 것이 아니라, Test Script를 먼저 만든다1. TDD는 코드를 먼저 만드는 것이 아니라, Test Script를 먼저 만든다
2. 그다음 실제 서버에서 수행되는 코드를 작성하는데, 먼저 만든 테스트스크립트
를 수행하면 PASS 하도록 코딩한다.
3. 코드작성을 마치고, 그 코드의 가독성, 유지보수성을 높이기 위해 리팩토링한다.
Test Driven Development - TDD
Test Script – 명시적인 코드로 개발 종료조건을 정해 놓은 것
class Calculator{
public function $sum($a, $b){return 0;
}}
class TestScript {
$testObject;
$test = new Calulator();$ts = new TestScript($test);$ts->test();
------결과--------$testObject;
public function __constant($obj){$this->testObject = $obj;}
public function test(){echo ($testObject->sum(10,20) == 30);echo ($testObject->sum(1,2) == 3);echo ($testObject->sum(-10,20) == 10);echo ($testObject->sum(0,0) == 0);
}
}
------결과--------
falsefalsefalsetrue
Debugging
재현가능성확보
단서의확보
개발지식이 충분하다면,단계별로 정확하게 진행이 가능하다.
하지만, 개발지식이 부족 할 경우무작위로 코드를 고쳐보고이전상태로 돌려보는 상황이 나타난다.
최악의 경우 검색으로 힌트를 얻어,소거법으로 하나하나 연관 없는 부분을
단서의분석
가설의수립
가설의검증
소거법으로 하나하나 연관 없는 부분을제거하기도 한다.
Debugging
원초적인 방법으로는
1. Console에 print.
2. Log.debug()와 같이 로거의 메소드를 호출하여
소스에 흔적이 남을 수 있다.
3. IDE tool을 이용하기
- Eclipse, VisualStudio 등등
Extending the Software for a New Project
New Use Case
요구사항 뭐지?
User Interface
그래서 뭐필요? ->스케치
Classes& Modules
기존에 있나?
냄새는?
Database
이미 정보가 있나?
테이블 더 필요?
CRUD Availability?
Security
보안정책에 위배?
User Help
사용자를 위한 안내는 어떻게 ?
Team Discussion
기술적으로 잘 될까?
빼먹은건 없을까?