•
테이블 활용 기법은 어떤 정보를 찾기 위해서 조건문을 사용하지 않고 테이블에 있는 정보를 검색하는 방식이다.
◦
조건이 간단할 때는 논리적인 명령문이 더 쉽고 직접적이나 조건문이 복잡해질수록 테이블 방식이 더 나을 것이다.
1. 테이블 활용 기법에서 일반적으로 고려해야할 사항
테이블을 활용한 기법의 두 가지 문제점
•
테이블에 있는 인테르리를 어떻게 참조할 것인가
◦
어떤 데이터는 테이블에 직접 접근하는데 사용할 수 있다.
▪
가령 데이터를 월별로 분류하는 경우, 월별 테이블에 입력하는 것이 간단하며 이들의 인덱스는 1부터 12가 될 것이다.
◦
어떤 데이터는 테이블 엔트리를 사용하는 것이 적합하지 않을 수 있는데, 주민등록번호를 이용해 데이터를 분류하는 경우, 999999-9999999 포맷의 엔트리를 테이블에 저장할 수 없다면 이는 다른 접근법을 선택해야 한다.
•
테이블에 무엇을 저장할지 설명해야 한다.
◦
테이블 참조 결과 자체가 데이터인 경우도 있다 그런 경우라면 테이블에 데이터를 저장해도 상관없다.
◦
테이블 참조 결과 자체가 어떠한 행위인 경우, 행위를 나타내는 코드를 저장하거나 행위를 구현하는 메소드에 대한 참조를 저장하라. 이 경우 테이블이 복잡해진다.
2. 직접 접근 방식
•
모든 테이블 검색 방식과 마찬가지로 지겁 접근 방식도 복잡한 논리 제어 구조를 대신해 사용할 수 있다.
•
이 방식은 테이블에서 원하는 정보를 찾기 위해 다른 곳으로 이동할 필요가 없기 때문에 직접 저근 방식이라고 한다.
월별 일수 예제
•
월별 일수를 구해야한다고 가정해보자. 물론 다음처럼 거대한 if 문으로 작성할 수 있다.
If ( month = 1 ) Then
days = 31
ElseIf ( month = 2 ) Then
days = 28
ElseIf ( month = 3 ) Then
days = 31
ElseIf ( month = 4 ) Then
days = 30
ElseIf ( month = 5 ) Then
days = 31
ElseIf ( month = 6 ) Then
days = 30
ElseIf ( month = 7 ) Then
days = 31
ElseIf ( month = 8 ) Then
days = 31
ElseIf ( month = 9 ) Then
days = 30
ElseIf ( month = 10 ) Then
days = 31
ElseIf ( month = 11 ) Then
days = 30
ElseIf ( month = 12 ) Then
days = 31 End If
Visual Basic
복사
•
데이터를 테이블로 사용하면 같은 기능을 더 이해하고 수정하기 쉽게 고칠 수 있다. enum을 사용해도 좋다.
Dim daysPerMonth() As Integer = _
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
Visual Basic
복사
◦
비주얼 베이직에서 사용하는 방식이다.
•
이처럼 데이터를 사용해 다수의 if 문을 직접 접근 방식으로 전환할 수 있다.
보험료 예제
•
의료보험료를 계산하는 프로그램에서 보험료가 나이, 성별, 결혼 여부, 흡연 여부에 따라 달라진다고 가정해보자.
•
보험료에 대한 논리적인 제어 구조를 작성해야 한다면 다음과 같이 작성할 것이다.
if ( gender == Gender.Female ) {
if ( maritalStatus == MaritalStatus.Single ) {
if ( smokingStatus == SmokingStatus.NonSmoking ) {
if ( age < 18 ) {
rate = 200.00;
}
else if ( age == 18 ) {
rate = 250.00;
}
else if ( age == 19 ) {
rate = 300.00;
}
...
else if ( 65 < age ) {
rate = 450.00;
}
else {
if ( age < 18 ) {
rate = 250.00;
}
else if ( age == 18 ) {
rate = 300.00;
}
else if ( age == 19 ) {
rate = 350.00;
}
...
else if ( 65 < age ) {
rate = 575.00;
}
}
else if ( maritalStatus == MaritalStatus.Married )
...
}
Visual Basic
복사
◦
이 코드는 논리 구조를 임의로 어느정도 생략했는데도 불구하고 복잡하다. 이 코드는 결혼한 여성이나 남성, 18세부터 65세 사이의 연령층 대부분의 조건을 생략했음에도 어렵다.
•
나이만이 아닌 배열에 모든 요소를 넣고 보험료를 입력하는 것이 낫다. 그러한 배열을 다음과 같이 선언할 수 있다.
Public Enum SmokingStatus
SmokingStatus_First = 0
SmokingStatus_Smoking = 0
SmokingStatus_NonSmoking = 1
SmokingStatus_Last = 1
End Enum
Public Enum Gender
Gender_First = 0
Gender_Male = 0
Gender_Female = 1
Gender_Last = 1
End Enum
Public Enum MaritalStatus
MaritalStatus_First = 0
MaritalStatus_Single = 0
MaritalStatus_Married = 1
MaritalStatus_Last = 1
End Enum
Const MAX_AGE As Integer = 125
Dim rateTable ( SmokingStatus_Last, Gender_Last, MaritalStatus_Last, _
MAX_AGE ) As Double
Visual Basic
복사
유연한 메시지 형식 예제
•
코드로 구현하기에 동적인 논리 구조에도 테이블을 사용할 수 있다.
•
파일에 저장된 메시지를 출력하는 메소드를 작성하고 있다고 가정해보자.
◦
파일은 보통 500개의 메시지를 포함하고 있으며 각 파일에는 20가지 종류의 메시지가 들어 있다. 메시지는 부표로부터 발생하고 수온과 부표의 위치 등을 제공한다.
◦
각 메시지는 필드를 여럿 가지고 있으며 메시지의 종류를 나타내는 ID를 포함하고 있는 헤더로 시작한다.
•
논리적 접근 방식
◦
논리적 접근 방식을 사용했다면 메시지를 읽어서 ID를 검사한 후 메시지를 읽고 해석하여 출력하는 메소드를 호출할 것이다.
▪
메시지의 종류가 20개라면 20개의 메소드가 존재할 것이며 메시지를 지원하는 하위 수준의 메소드도 여럿 작성해야할 것이다.
▪
메시지 형식이 바뀔 때마다 해당 메시지를 담당하는 메소드나 클래스의 코드를 변경해야 할 것이다.
◦
다음과 같이 각 메시지 타입을 조건문으로 검사하고 그에 해당하는 메소드를 호출하는 형태로 의사코드가 작성된다.
While more messages to read
Read a message header
Decode the message ID from the message header
If the message header is type 1 then
Print a type 1 message
Else if the message header is type 2 then
Print a type 2 message
...
Else if the message header is type 19 then
Print a type 19 message
Else if the message header is type 20 then
Print a type 20 message
Visual Basic
복사
•
객체지향적인 접근법
◦
논리적인 조건문 코드들을 객체의 상속 구조에 숨길 수 있겠지만 그 구현 자체는 여전히 복잡하다.
◦
다음과 같은 의사코드가 작성된다.
While more messages to read
Read a message header
Decode the message ID from the message header
If the message header is type 1 then
Instantiate a type 1 message object
Else if the message header is type 2 then
Instantiate a type 2 message object
...
Else if the message header is type 19 then
Instantiate a type 19 message object
Else if the message header is type 20 then
Instantiate a type 20 message object
End if
End While
Visual Basic
복사
•
테이블을 활용한 접근법
◦
테이블을 활용한 접근법은 이런 경우에 대해서 다른 접근법들에 비해 훨씬 경제적이다.
▪
메시지를 읽는 메소드는 각 메시지의 헤더를 읽어 ID를 해석하고 Message 배열에서 메시지 설명을 찾은 다음 메시지를 포매팅하기 위해 항상 같은 메소드를 호출해주면 끝이다.
▪
테이블을 활용한 접근법을 사용하면 각 메시지 형식을 코드로 작성하는 대신 테이블에 기술해둘 수 있다.
◦
다음과 같은 의사코드를 작성할 수 있다.
While more messages to read
Read a message header
Decode the message ID from the message header
Look up the message description in the message-description table
Read the message fields and print them based on the message description
End While
Visual Basic
복사
◦
상속과 다형성을 사용한다고 해서 항상 좋은 설계가 되는 것은 아니므로 주의해서 사용하자. 그리고 해당 해결책은 객체지향도 기능 위주도 아닌 참조 테이블을 잘 사용한 것이다.
•
참조 키 변경하기
◦
앞에서 살펴본 세 예제에선 테이블에 접근하기 위해 데이터를 바로 사용할 수 있었다. 즉 messageID를 변경없이 키값으로 사용할 수 있었다.
◦
이 방법이 간단하고 빠르기 때문에 항상 테이블에 직접 접근하고 싶어한다. 하지만 조회 시 messageID가 아니라 coordinate를 사용해야 한다면? 직접적인 접근이 불가능해진다.
▪
따라서 참조 키 변경이라는 주제가 나오게 되었다. 키 값을 변경하는 방법은 다양하다.
◦
키 값을 변경하는 방법은 다양하며 다음과 같은 방법들이 존재한다.
▪
키 변환 기능을 메소드로 작성한다.
•
데이터를 키로 변환하는 연산을 메소드로 작성하는 방법으로 자바는 키와 값 쌍을 관리하는 데 사용할 수 있는 HashMap을 제공한다.
▪
직접 접근할 수 있도록 키 값을 변환한다.
•
요지는 키 값이 될 수 있도록 데이터에 연산을 수행하는 방법인 것 같은데,, 적절한지는 잘 모르겠다.
3. 인덱스 접근 방식
•
때때로 Age를 테이블의 키 값을 변환하는 것처럼 간단한 수학적 변환만으로는 충분하지 않은 경우가 있다. 그러한 경우 인덱스 접근 방식이 적합하다.
•
인덱스를 사용하면 인덱스 테이블에 있는 키를 참조하기 위해서 원본 데이터를 인덱스로 사용하고 데이터를 참조하기 위해서 인덱스 테이블의 값을 사용한다.
•
인덱스 접근 방식은 다음 두 가지 장점을 가진다.
◦
주 참조 테이블에 있는 각 엔트리가 크다면 많은 공간이 낭비되는 주 참조 테이블을 만드는 대신 인덱스 배열을 만드는 것이 공간을 더 적게 사용한다.
◦
인덱스를 사용함으로써 공간을 절약하지 못한다 하더라도 주 테이블에 있는 엔트리보다 인덱스에 있는 엔트리를 다루는 것이 더 간단한 경우가 존재한다.
4. 단계적 접근 방식
•
단계적 접근 방식은 계단에 따라 수준을 결정하여 엔트리를 분류한다.
•
이 접근 방식은 다른 테이블을 활용하는 방식보다 불규칙한 데이터를 더 잘 다룰 수 있다는 장점을 제공한다.
•
다음은 단계적 접근 방식을 사용할 때 고려할 사항이다.
◦
종결점을 확인하라.
▪
각 단계의 최댓값에 해당하는 경우를 처리했는지 확인해야 한다.
▪
<와 <=를 혼동하지 않도록 한다.
◦
순차 검색법 대신 이진 검색법 사용을 고려하라.
◦
단계적 접근 방식 대신 인덱스 접근 방식을 고려해보라.
▪
실행 속도가 중요한 경우라면 인덱스 접근 방식이 더 나을 수 있다.
요점 정리
•
테이블을 복잡한 논리 코드와 상속 구조에 대한 대안을 제공한다. 프로그램의 논리나 상속 트리가 혼란스럽다고 생각한다면 참조 테이블을 사용하여 단순화할 수 있는지 확인해본다.
•
테이블을 사용할 때 한가지 고려할 핵심은 테이블 접근법을 결정하는 것이다. 직접 접근 방식이나 인덱스 접근 방식, 단계적 접근 방식을 사용하여 테이블에 접근할 수 있다.
•
테이블을 사용할 때는 테이블에 무엇을 입력할지 결정하는 게 매우 중요하다.