SmalltalkBestPracticePatterns:Appendix A
Jump to navigation
Jump to search
- Appendix A Quick Reference
Composed Method | 프로그램을 메서드로 분해하는 방법은? | 하나의 식별 가능한 작업을 실행하는 메서드들로 프로그램을 분해하라. 모든 연산은 추상화(abstraction)와 동일한 수준에 있는 메서드에 유지하라. 이는 자연스럽게 각각이 몇 개의 줄로 이루어진 작은 다수의 메서드로 이루어진 프로그램을 도출할 것이다. |
Constructor Method | 인스턴스 생성을 어떻게 표현하는가? | 정보가 많은(well-informed) 인스턴스를 생성하는 메서드를 제공하라. 필요한 파라미터를 모두 그러한 메서드들로 전달하라. |
Constructor Parameter Method | 파라미터로부터의 인스턴스 변수를 Constructor Method로 설정하는 방법은? | 모든 변수를 설정하는 단일 메서드를 코딩(code)하라. 그리고 “set”를 다음에 변수의 이름을 붙여라. |
Shortcut Constructor Method | Constructor Method가 너무 길 때 새 객체를 생성하기 위한 외부 인터페이스는 무엇인가? | Constructor Method에 대한 argument 중 하나를 향해 객체 생성을 메시지로 표현하라. 개발 중인 시스템마다 Shortcut Construct 메서드를 추가할 때는 그 수를 3개 이하로 하라. |
Conversion | 어떻게 한 객체의 포맷에서 다른 객체의 포맷으로 정보를 변환하는가? | 한 객체의 프로토콜만 덮어씌우기보다 객체를 다른 객체로 변환하라. |
Converter Method | 하나의 객체를 프로토콜은 같지만 포맷이 다른 객체로 단순 변환시키려면 어떻게 표현하는가? | 변환될 객체에 새 객체로 변환시키는 메서드를 제공하라. 메서드 이름은 리턴되는 객체의 클래스 앞에 “as”를 붙여 명명하라. |
Converter Constructor Method | 한 객체가 프로토콜이 다른 객체로 변환되는 것을 어떻게 표현하는가? | 변환될 객체를 argument로 취하는 Constructor Method를 만들어라. |
Query Method | 객체의 속성 시험을 표현하는 방법은? | 부울값을 리턴하는 메서드를 제공하라. 속성 이름 앞에 “be”ㅡis was, will 등ㅡ를 붙여 명명하라. |
Comparing Method | 객체들을 어떻게 서로 관련시켜 정렬할까? | argument 전에 수신자에게 명령해야 하는 경우 “≤”를 구현하여 true를 리턴하라. |
Reversing Method | 어떻게 부드러운 메시지 흐름을 코딩하는가? | 파라미터 상에서 메서드를 코딩하라. 그 이름은 원본 메시지로부터 도출한다. 본래 수신자를 새 메서드에 대한 파라미터로 취하라. 본래 수신자에게 원본 메시지를 전송함으로써 메서드를 구현하라. |
Method Object | 코드의 여러 행이 다수의 argument와 임시 변수를 공유하는 경우 어떻게 메서드를 코딩하는가? | 메서드의 이름을 딴 클래스를 생성하라. 여기에 본래 메서드의 수신자에 대한 인스턴스 변수, 각 argument, 각 임시 변수를 제공하라. 본래 수신자와 메서드 argument를 취하는 Constructor Method를 제공하라. 그리고 본래 메서드의 body를 복사하여 구현되는 인스턴스 메서드, #compute를 하나 부여하라. 이 메서드 대신 새로운 객체의 인스턴스를 생성시키고 #compute를 전송하는 메서드로 교체하라. |
Execute Around Method | 함께 실행해야 하는 액션들을 어떻게 표현하는가? | Block을 argument로 취하는 메서드를 코딩하라. 처음 호출해야 하는 메서드 이름 앞에 “During: aBlock”를 붙여 메서드를 명명하라. Execute Around 메서드의 body에서 첫 번째 메서드를 호출하고, 블록을 평가한 후 두 번째 메서드를 호출하라. |
Debug Printing Method | 기본 인쇄 메서드를 어떻게 코딩하는가? | printOn:을 오버라이드하여 객체의 구조에 관한 정보를 프로그래머에게 제공하라. |
Method Comment | 메서드에 어떻게 주석을 달 것인가? | 코드에서 명확하지 않은 중요한 정보는 메서드의 시작점에서 주석으로 전달하라. |
Message | 계산을 호출하는 방법은? | 명명된 메시지를 전송하고, 수신하는 객체가 그 메시지에 대한 결정을 내리도록 하라. |
Choosing Message | 여러 대안책 중 하나를 실행하는 방법은? | 각 객체가 하나의 대안책을 실행하는 여러 종류의 객체들 중 하나로 메시지를 전송하라. |
Decomposing Method | 계산의 부분을 어떻게 호출하는가? | 여러 개의 메시지를 “self”로 전송하라. |
Intention Revealing Message | 구현부가 간단할 때 어떻게 의도를 전달하는가? | “self”로 메시지를 전송하라. 메시지의 이름을 정하여 작업이 이루어지는 방법(how)보다는 어떤 작업을 완료하길 원하는지(what) 전달하도록 하라. 메시지에 대해 단순한 메서드를 코딩하라. |
Intention Revealing Selector | 메서드의 이름을 무엇으로 정하는가? | 메서드가 행하는 작업을 따라 이름을 정하라. |
Dispatched Interpretation | 두 객체 중 하나의 객체가 표현을 감추길 원한다면 두 객체는 어떻게 협력할 수 있는가? | 고객이 코딩된 객체로 메시지를 전송하도록 하라. 인코딩된 객체가 디코딩된 메시지를 전송하는 곳으로 파라미터를 전달하라. |
Double Dispatch | 두 개의 클래스 군의 교적(cross product), 다수의 case가 있는 계산을 어떻게 코딩할 수 있는가? | argument에 메시지를 전송하라. 수신자의 클래스 이름을 선택자 이름 앞에 붙여라. 수신자를 argument로서 전달하라. |
Mediating Protocol | 서로 독립된 채로 남아있어야 하는 두 객체 간 상호작용을 어떻게 코딩할 것인가? | 객체들 간 프로토콜을 정제하여 사용된 단어들의 일관성을 확보하라. |
Super | 슈퍼클래스 행위를 어떻게 호출할 수 있는가? | “self” 대신 “super”로 메시지를 전송함으로써 슈퍼클래스에서 코드를 명시적으로 호출하라. 메시지에 해당하는 메서드는 전송하는 메서드를 구현하는 클래스의 슈퍼클래스에서 발견될 것이다. |
Extending Super | 메서드에 대한 슈퍼클래스 구현부에 추가하는 방법은? | 메서드를 오버라이드하고 오버라이딩 메서드 내 “super”로 메시지를 전송하라. |
Modifying Super | 슈퍼클래스의 메서드에 대한 행위를 수정하지 않고 일부만 변경하는 방법은? | 메서드를 오버라이드하고 “super”를 호출한 후, 결과 수정을 위해 코드를 실행하라. |
Delegation | 객체가 상속 없이 구현부를 공유하는 방법은? | 작업 중 일부를 다른 객체로 전달하라. |
Simple Delegation | 이해관계가 없는(disinterested) 위임을 호출하는 방법은? | 메시지를 변경하지 않은 채 위임하라. |
Self Delegation | 위임하는 객체로의 참조를 필요로 하는 객체로 위임을 구현하는 방법은? | “for:”라 불리는 추가 파라미터에서 위임하는 객체를 (예: “self”) 전달하라. |
Pluggable Behavior | 객체의 행위를 어떻게 파라미터화하는가? | 다른 행위를 트리거할 때 사용할 변수를 추가하라. |
Pluggable Selector | 간단한 인스턴스 특정적 행위를 어떻게 코딩하는가? | 실행할 선택자를 포함하고 있는 변수를 추가하라. Role Suggesting Instance Variable Name 앞에 “Message”를 붙여라. 선택자를 실행하는 Composed Method를 생성하라. |
Pluggable Block | 고유의 클래스를 가질 만한 가치가 없는 복합 Pluggable Behavior(플러그 가능한 행위)를 어떻게 코딩하는가? | Block을 저장하기 위해 인스턴스 변수를 추가하라. Role Suggesting Instance Variable Name 이름 앞에 “Block”을 붙여라. Pluggable Behavior(플러그 가능한 행위)를 호출하기 위한 Block의 평가를 위해 Composed Method를 생성하라. |
Collecting Parameter | 여러 메서드의 협력적 결과인 집합체를 어떻게 리턴하는가? | 결과를 수집하는 파라미터를 모든 서브메서드에 추가하라. |
Common State | 상태, 즉 클래스의 모든 인스턴스에 존재하게 될 다른 값들을 어떻게 표현하는가? | 클래스에서 인스턴스 변수를 선언하라. |
Variable State | 인스턴스마다 존재가 다양한 상태를 어떻게 표현하는가? | 일부 인스턴스만 갖게 될 변수들을 “properties”라 불리는 인스턴스 변수에 저장된 Dictionary에 넣어라. 프로퍼티에 접근하기 위해선 “propertyAt: aSymbol”과 “propertyAt: aSymbol put: anObject”를 구현하라. |
Explicit Initialization | 인스턴스 변수를 어떻게 기본 값으로 초기화하는가? | 모든 값을 명시적으로 설정하는 “initialize” 메서드를 구현하라. 클래스 메시지 “new”를 오버라이드하여 새로운 인스턴스에서 호출할 수 있도록 하라. |
Lazy Initialization | 인스턴스 변수를 어떻게 기본 값으로 초기화하는가? | 변수에 대해 Getting Method를 작성하라. 필요 시 Default Value Method를 이용해 초기화하라. |
Default Value Method | 변수의 기본 값을 어떻게 표현하는가? | 값을 리턴하는 메서드를 생성하라. 변수 이름 앞에 “default”를 붙여서 메서드를 명명하라. |
Constant Method | 상수를 어떻게 코딩하는가? | 상수를 리턴하는 메서드를 생성하라. |
Direct Variable Access | 어떻게 인스턴스 변수의 값을 얻고 설정하는가? | 변수에 직접적으로 접근하여 설정하라. |
Indirect Variable Access | 어떻게 인스턴스 변수의 값을 얻고 설정하는가? | Getting Method와 Setting Method를 통해서만 그 값에 접근하고 설정하라. |
Getting Method | 인스턴스 변수로의 접근성은 어떻게 제공하는가? | 변수의 값을 리턴하는 메서드를 제공하라. 변수와 동일한 이름을 제공하라. |
Setting Method | 인스턴스 변수의 값은 어떻게 변경하는가? | 메서드에 변수와 동일한 이름을 제공하라. 단일 파라미터를 취하고 값이 설정되도록 하라. |
Collection Accessor Method | 컬렉션을 보유하는 인스턴스 변수로 어떻게 접근성을 제공하는가? | Delegation으로 구현되는 메서드를 컬렉션에 제공하라. 메서드의 이름을 정하려면 컬렉션 이름을 컬렉션 메시지로 추가하라. |
Enumeration Method | 컬렉션 요소로 안전하고 일반적인 접근성을 제공하는 방법은? | 컬렉션 요소마다 하나의 Block을 실행하는 메서드를 구현하라. 메서드 이름은 컬렉션 이름과 “Do:”를 합쳐서 명명하라. |
Boolean Property Setting Method | 부울 프로퍼티는 어떻게 설정하는가? | “be”로 시작하는 두 개의 메서드를 생성하라. 하나는 프로퍼티명을 갖고 있고 나머지 하나는 그렇지 않다. 고객이 현재 상태에 대해 알고 싶지 않다면 “toggle”을 추가하라. |
Role Suggesting Instance Variable Name | 인스턴스 변수를 어떻게 명명하는가? | 계산에서 인스턴스 변수가 하는 역할에 따라 명명하라. 변수가 Collection을 보유한다면 이름은 복수로 나타내라. |
Temporary Variable | 추후 메서드 내에서 표현식의 값을 사용하려면 어떻게 값을 저장하는가? | 통용범위와 확장범위가 단일 메서드인 변수를 생성하라. 메서드 선택자 바로 아래에서 선언하라. 그리고 표현식이 유효해지는 즉시 할당하라. |
Collecting Temporary Variable | 후에 메서드에서 사용되도록 점차적으로 값을 수집하는 방법은? | 복잡한 열거에서 객체들을 수집하거나 합쳐야 하는 경우, 컬렉션 또는 합친 값을 유지하기 위해 임시 변수를 사용하라. |
Caching Temporary Variable | 메서드의 성능을 어떻게 향상하는가? | 임시 변수가 유효해지는 즉시 표현식의 값으로 설정하라. 메서드 나머지 부분에 표현식 대신 변수를 사용하라. |
Explaining Temporary Variable | 메서드 내에서 복합 표현식을 간소화하는 방법은? | 복합 표현식에서 subexpression을 꺼내라. 그 값을 복합 표현식 이전에 임시 변수로 할당하라. 복합 표현식에서 대신 변수를 사용하라. |
Reusing Temporary Variable | 표현식의 값이 변경될 때 메서드 내 여러 장소에서 표현식을 사용하는 방법은? | 표현식을 한 번 실행하고 임시 변수를 설정하라. 메서드 나머지 부분에 표현식 대신 변수를 사용하라. |
Role Suggesting Temporary Variable Name | 임시 변수를 무엇이라 부르는가? | 계산에서 임시 변수의 역할에 따라 이름을 붙여라. |
Collection | 일대다(one-to-many) 관계는 어떻게 표현하는가? | Collection을 이용하라. |
Ordered Collection | 생성 시 크기를 결정할 수 없는 Collections은 어떻게 코딩하는가? | OrderedCollection을 동적으로 크기가 조정된 기본 Collection으로서 이용하라. |
Run Array | 한 행에 동일한 요소를 여러 번 포함하는 Array 또는 OrderedCollection을 어떻게 압축적으로(compactly) 코딩하는가? | Run Array을 이용해 동일한 요소의 long run을 압축(compress)하라. |
Set | 유일한 요소들로 구성된 Collection을 어떻게 코딩하는가? | Set를 이용하라. |
Equality Method | 새로운 객체들에 대한 동등성(equality)을 어떻게 코딩하는가? | Set에 객체들을 넣은 후 Dictionary 키로서 이용하거나 동등성을 정의하는 다른 객체와 함께 이용하는 경우, "="라 불리는 메서드를 정의하라. “=”의 구현부를 보호하여 호환 가능한 클래스의 객체들만 동등성 시험을 받도록 하라. |
Hashing Method | 새로운 객체들이 hashed Collections와 올바르게 작동하도록 보장하는 방법은? | “=”를 오버라이드하고 hashed Collection의 객체를 사용하는 경우, “hash"를 오버라이드해야 동일한 두 객체가 동일한 해시 값을 리턴한다. |
Dictionary | 한 종류의 객체를 다른 종류의 객체로 어떻게 매핑하는가? | Dictionary를 이용하라. |
Sorted Collection | 컬렉션은 어떻게 정렬하는가? | SortedCollection을 이용하라. “<=” 이외의 기준으로 정렬을 원할 경우 그 정렬 블록(sort block)을 설정하라. |
Array | 요소의 수가 고정된 컬렉션은 어떻게 코딩하는가? | Array를 이용하라. “new: anInteger”를 이용해 당신이 생각하기에 필요한 요소의 수만큼 공간을 갖고 있도록 생성하라. |
Byte Array | 0..255 또는 128..127 범위의 수들로 이루어진 Array를 어떻게 코딩하는가? | Byte Array을 이용하라. |
Interval | 숫자의 컬렉션을 어떻게 순차적으로 코딩하는가? | 시작, 정지, 선택적 단계 값으로 Interval을 이용하라. Shortcut Constructor Methods Number>>to: 와 to:by: 가 당신을 대신해 Intervals를 빌드해준다. |
Is Empty | 컬렉션이 비어있는지는 어떻게 시험하는가? | 컬렉션이 비어있는지 시험하려면 (요소가 없는지) isEmpty를 전송하라. 컬렉션에 요소가 있는지를 시험하려면 notEmpty를 사용하라. |
Includes: | 컬렉션에서 어떻게 특정 요소를 검색하는가? | includes:를 전송하고 검색할 객체를 전달하라. |
Concatentation | 두 개의 컬렉션을 어떻게 합치는가? | 두 번째 컬렉션을 argument로 한 “,”를 첫 번째 컬렉션으로 전송하여 두 컬렉션을 합쳐라. |
Enumeration | 어떻게 컬렉션에 걸쳐 코드를 실행하는가? | 컬렉션에 걸쳐 계산을 퍼뜨리기 위해서는 열거 메시지를 사용하라. |
Do | 컬렉션 내 각 요소에 대한 코드를 어떻게 실행하는가? | 컬렉션의 요소를 반복하도록 컬렉션에 do:를 전송하라. one argument 블록을 argument로서 do: 로 전송하라. 각 요소마다 한 번씩 평가될 것이다. |
Collect | 컬렉션 내 각 객체로 전송되는 메시지의 결과를 어떻게 작동시키는가? | 본래 컬렉션의 각 요소를 이용해 collect: 로 전달된 블록을 평가한 결과를 요소로 하는 새 컬렉션을 collect:를 이용해 생성하라. |
Select/Reject | 컬렉션의 일부를 필터링하는 방법은? | 흥미로운 요소들만 포함하는 새 컬렉션을 리턴하기 위해선 select:와 reject:를 사용하라. 새 컬렉션을 열거하라. 둘 다 부울값(Boolean)을 리턴하는 one argument Block을 취하라. Select:는 Block이 true를 리턴하는 요소들을 제공하고, reject:는 Block이 false를 리턴하는 요소들을 제공한다. |
Detect | 컬렉션을 어떻게 검색하는가? | 컬렉션에 detect:를 전송함으로써 컬렉션을 검색하라. 블록 argument가 true로 평가하는 첫 번째 요소가 리턴될 것이다. |
Inject:into: | Collection을 반복하는 동안 어떻게 실행 중인 값을 유지하는가? | 실행 중인 값을 유지하려면 inject:into:를 사용하라. 첫 번째 argument를 초기 값으로 하라. 두 번째 argument는 2 요소(two element) 블록으로 만들어라. 블록 arguments를 “sum”과 “each”라고 불러라. 블록이 실행 값의 다음 값을 평가하도록 하라. |
Duplicate Removing Set | 컬렉션에서 중복내용은 어떻게 제거하는가? | Collection으로 “asSet"을 전송하라. 그 결과 모든 중복내용이 제거될 것이다. |
Temporarily Sorted Collection | Collection을 여러 정렬 중 하나를 이용해 표현하는 방법은? | “asSortedCollection”을 Collection으로 전송함으로써 Collection의 정렬된 복사본을 리턴하라. 기본 정렬 순서를 원할 경우 “asSortedCollection: aBlock”을 전송하라. |
Stack | 스택을 어떻게 구현하는가? | OrderedCollection을 이용해 Stack을 구현하라. |
Queue | 큐를 어떻게 구현하는가? | OrderedCollection을 이용해 큐(queue)를 구현하라. |
Searching Literal | 코드를 작성할 때 몇 개의 알려진 리터럴 객체 중 하나를 검색하는 방법은? | 당신이 찾고 있는 요소가 포함되어 있는지 리터럴 Collection으로 물어보라. |
Lookup Cache | 복잡한 Detect 또는 Select/Reject 루프를 최적화하는 방법은? | 비용이 많이 드는 검색 또는 필터 메서드의 이름 앞에 “lookup”을 붙여라. Dictionary를 보유하는 인스턴스 변수를 캐시 결과에 추가하라. 변수의 이름은 검색 이름 앞에 “Cache”를 붙여 명명하라. 검색(search)의 파라미터들을 Dictionary의 키(key)로 만들고, 검색의 결과를 값으로 만들어라. |
Parsing Stream | 간단한 파서(parser)는 어떻게 작성하는가? | Stream을 인스턴스 변수에 넣어라. 모든 파싱 메서드가 동일한 Stream으로부터 작동하도록 하라. |
Concatenating Stream | 어떻게 여러 Collections를 결합하는가? | 다수의 Collections를 결합 시 Stream을 사용하라. |
Simple Superclass Name | 상속 계층구조의 루트(root)로 예상되는 클래스를 어떻게 명명하는가? | 설계 시 목적을 전달하는 하나의 단어로 슈퍼클래스를 명명하라. |
Qualified Subclass Name | 새로운 서브클래스를 어떻게 명명하는가? | 계층구조의 서브클래스 이름은 슈퍼클래스명 앞에 형용사를 붙여서 명명하라. |
Inline Message Pattern | 메시지 패턴은 어떻게 포맷팅하는가? | 명시적 행 바꿈 없이 메시지 패턴을 작성하라. |
Type Suggesting Parameter Name | 메서드 파라미터를 뭐라고 부르는가? | 가장 일반적으로 예상되는 클래스명 앞에 “a” 또는 “an”을 붙여 파라미터를 명명하라. 동일하게 예상되는 클래스에 하나 이상의 파라미터가 존재하는 경우 클래스명 앞에 기술적 단어를 붙여라. |
Indented Control Flow | 메시지는 어떻게 들여쓰는가? | zero 또는 one argument 메시지를 그들의 수신자와 동일한 행에 넣어라. 2개 또는 그 이상의 키워드가 있는 메시지의 경우 각 키워드/argument 쌍을 자체 행에 넣고 한 탭만큼 들여써라. |
Rectangular Block | 블록을 어떻게 포맷팅하는가? | 블록을 직사각형으로 만들어라. 꺾쇠괄호를 직사각형의 상단 좌측과 하단 우측 모서리로서 사용하라. 블록 내 statement가 간단할 경우 블록은 한 행에 들어맞는다. statement가 복잡한 경우 블록을 고유의 행에 가져와 들여 써라. |
Guard Clause | 조건(condition)이 지속되는 경우 실행되어선 안 되는 코드는 어떻게 포맷팅하는가? | 명시적 리턴으로 one-branch 조건문을 포맷팅하라. |
Conditional Expression | 두 개의 분기(branch)가 값을 할당하거나 리턴하는 조건 표현식은 어떻게 포맷팅하는가? | 조건문을 포맷팅하여 그들의 값이 메서드의 의도를 분명히 전달하는 곳에 사용하도록 하라. |
Simple Enumeration Parameter | 파라미터를 열거 블록으로 어떻게 호출하는가? | 파라미터를 “each”라고 불러라. 중첩된 열거 블록을 가진 경우 모든 파라미터명 앞에 설명적 단어를 붙여라. |
Cascade | 다수의 메시지를 어떻게 동일한 수신자로 포맷팅하는가? | 동일한 수신자로 여러 개의 메시지를 전송하기 위해서는 Cascade를 사용하라. 메시지들은 세미콜론으로 구분하라. 각 메시지는 고유의 행에 놓고 한 탭만큼 들여 써라. zero 또는 one argument로 된 메시지에는 Cascades만 사용하라. |
Yourself | 마지막 메시지가 메시지의 수신자를 리턴하지 않을 경우 어떻게 Cascade의 값을 사용하는가? | Cascade의 값이 필요한데 마지막 메시지가 수신자를 리턴하지 않는 경우, “yourself” 메시지를 Cascade 앞에 덧붙여라. |
Interesting Return Value | 언제 메서드 끝에서 값을 명시적으로 리턴하는가? | 수신자가 값을 사용하도록 의도한 경우에만 값을 리턴하라. |