TheArtandScienceofSmalltalk:Chapter 14

From 흡혈양파의 번역工房
Revision as of 12:54, 3 December 2013 by Onionmixer (talk | contribs) (내용 구문오류 수정)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
제 14 장 개발 툴 사용하기

개발 툴 사용하기

스몰토크 개발 환경과 그것이 제공하는 툴은 스몰토크의 강력한 기능에 기여하는 주요인 중 하나다. 하지만 기본 기능을 학습하고 나면 막히기가 쉽다. 재래식 언어에서처럼 견디고 가능한 한 생산적으로 만들어주기에 충분한 지식이 있으면서도 이용할 수 있는 기능의 일부만 사용하고 있을 것이다!


본장은 기본을 상기시켜주는 것을 목적으로 하나, 좀 더 중요한 것은 개발 툴의 '고급(advanced)' 기능을 몇 가지 살펴보도록 장려하는 데 있다. 스몰토크에 관한 저서이므로 사용자 인터페이스 툴이나 데이터베이스 툴보다는 (기본 이상을 활용하도록 노력하라는 원칙은 똑같이 적용되지만) VisualWork의 프로그래밍 툴에 집중할 것이다. 이러한 툴은 코드를 작성할 때뿐만 아니라 시스템 코드를 살펴볼 때 사용되기도 한다. 디버깅에도 사용되지만 이는 다음 장에서 디버깅 기법과 함께 집중적으로 다루어야할 만큼 중요하다.


브라우저 사용하기

개발 환경에 제공되는 브라우저는 클래스 계층구조에 대한 창(window)이다. 이는 표준 클래스 라이브러리와 본인의 확장부분(extension)-본인의 프로그램-까지 포함한다. 제 1부, 스몰토크의 과학에서 다양한 브라우저를 이용하는 기술을 소개한 바 있다. 시스템을 탐구하거나 매뉴얼을 읽으면 더 많은 내용을 발견할 수 있을 것이다. 여기서는 매우 유연한 툴을 최대한으로 활용하는 방법과 시스템 내 클래스에 대한 자신의 관점을 실제로 가능하게 하는 방법을 살펴볼 것이다.


첫 번째이자 가장 분명한 것은 수많은 브라우저의 사용이 된다. 하나의 창만 열어 놓고 시스템을 훑어보면서 고군분투하는 사람이 얼마나 많은지 놀라울 따름이다. 물론 화면 크기에 따라 다르지만 (스몰토크에선 클수록 좋다는 사실은 이미 알아챘을 것이다), 한 번에 하나의 브라우저만 사용한다면 개발 환경을 최대한으로 활용하지 못하는 것이다.


시스템을 탐구하고 있다면 최소한 두 개의 시스템 브라우저를 열고 화면을 모두 차지하도록 하라. 그러면 하나는 조사 중인 대상을 집중으로 하고, 나머지 하나는 무언가를 검색할 때 항상 살펴보아야 할 관련 사항들을 팝업시켜 조사할 수 있다.


브라우저에도 여러 유형이 있음을 기억하라. 하나의 카테고리에 있는 클래스만 살펴보는 데 시스템 브라우저를 사용 중이라면 카테고리 브라우저를 사용해보라 (카테고리 리스트에서 operate 메뉴의 spawn 사용). 약간 다른 레이아웃에 익숙해져야 하긴 하지만 카테고리의 리스트를 표시하지 않아서 화면 공간에 여유가 생긴다. 이와 비슷하게 클래스 브라우저에 두 가지가 있는데, 프로토콜 브라우저와 메서드 브라우저가 그것들이다. 각 브라우저는 클래스 라이브러리 구조의 한 수준(level)을 제거하기 때문에 이 또한 작업할 필요가 있는 내용에 집중하도록 화면 공간을 절약한다. 특히 단일 메서드를 작업하고 있는데 계속해서 돌아와야 한다면 메서드 위에 메서드 브라우저를 켜놓는 것은 어떤가?


클래스 계층구조를 보고 싶다면 클래스 리스트의 operate 메뉴에서 hierarchy를 선택할 수 있다. 하지만 (카테고리별로 구조화된 것이 아니라) 상속 계층구조에 따라 구조화된 클래스를 살펴봐야 할 경우 spawn hierarchy를 선택해 계층구조 브라우저를 열어야 한다. 특히 계층구조를 바라보는 것이 좋다면 Advanced Programming ObjectKit 에 따라오는 full browser 를 마음에 들어할 것이다. 이는 분명 특정 클래스가 구현하고 상속한 메서드를 살펴보는 동시 상속 계층구조를 보는 기능을 클래스 라이브러리에 대한 카테고리 기반의 뷰와 결합한다.


하나 이상의 브라우저를 사용할 때 경고해야 할 한 가지 중요한 사항이 있다. 한 브라우저에서 메서드의 코드를 수정 중인데 동일한 메서드가 다른 브라우저에서 열려 있는 경우, 다른 브라우저들은 새 메서드 정의부를 반영하기 위해 update 메시지를 자동으로 업데이트하지 않을 것이다. 이 브라우저들 중 하나를 골라 코드를 다시 변경하고 accept 연산을 실행하면 앞의 변경내용은 모두 잃을 것이다. 이를 실행 시에는 주의를 기울여 절망적인 상태로 빠지지 않도록 한다.


해결 방법 찾기

스몰토크에서 자신 있게 할 수 있어야 하는 중요한 일들 중 하나는 시스템 내 코드의 해결 방법을 모색하는 것이다. 개발 환경은 이를 실행하기 위한 모든 방법을 제공한다. 사실 무언가를 찾는 방법-여느 개발자들이든 유용하다고 생각하는 방법-은 거의 개발 환경에 포함되어왔다. 유용하지만 유일하게 당신이 할 수 없는 일은 특정 문자의 문자열, 특히 주석의 일부를 소스 코드에서 찾는 일이다. 하지만 스몰토크는 다른 언어들에 비해 소스의 컨텍스트에 대해 훨씬 더 많이 알고 있으므로 (무언가가 메시지인지, 변수로의 참조인지, 클래스로의 참조인지 등을 인지) 이러한 기능의 결여는 사실 문제되지 않는다.


우리가 살펴보게 될 검색 기능 대부분은 다양한 브라우저를 통해 접근된다. 이는 모두 시스템 브라우저에서 이용 가능하며, 브라우저의 타입마다 적절한 하위집합을 이용할 수 있다. 이러한 명령 중 일부는 런처의 Browse 메뉴에서도 이용 가능하다.


아래 다이어그램은 양식화된 시스템 브라우저를 표시하고, 각 메뉴로부터 우리가 관심 있는 명령을 표시한다. 물론 이러한 메뉴 각각에는 다른 많은 명령들도 존재한다. 바라건대 지금쯤 이러한 명령들 대다수가 어떤 일을 하는지는 발견했을 것이다 (그렇지 않다면 노력해보길 바란다). 여기서는 검색(navigation) 명령을 몇 가지 시도하도록 장려하고자 한다.


카테고리 페인의 좌측에서 시작해 find class... 명령이 있다. 해당 명령을 이용해 당신이 이름을 알고 있는 클래스를 확인하기 위해 이동할 수 있다. 큰일이 아닌 듯 들리지만, 클래스명을 필요로 하는 경우 별표(*)를 와일드카드로 사용할 수 있음을 기억하라. 클래스의 이름을 알고 있다면 타이핑을 줄여줄 뿐만 아니라 (결정적 오타의 위험성도 감소), 이름의 일부를 짐작함으로써 클래스의 검색을 가능하게 해준다. 스몰토크의 명명 규칙에 익숙해지면 (특히 앞장의 조언을 따른다면) 이러한 사실을 이용해 당신이 찾는 유형의 일을 수행하는 클래스를 찾을 수 있을 것이다.


Ass image 14 01.png
시스템 브라우저의 검색(navigation and search) 명령.


다음으로, 클래스를 선택했다면 클래스 리스트 내 메뉴는 인스턴스 변수로의 참조, 그 클래스 변수로의 참조, 또는 클래스 자체로의 참조까지 검색하도록 해준다. 앞의 두 가지 중 하나를 선택하면 검색하고자 하는 참조 대상의 변수명을 요구할 것이다. 그러면 세 개 명령 모두 검색을 실행하고, 특별한 유형의 브라우저가 뜨면서 (다음 페이지의 다이어그램과 같은) 변수 또는 클래스에 대한 참조가 발견된 메서드를 모두 표시한다. 이러한 유형의 브라우저를 메서드 리스트 브라우저라고 부르는데, 이는 어떤 검색 쿼리에 대한 응답으로 생성되었다는 사실에 따라 연관된 메서드 집합을 표시하는 데 사용된다. 이러한 종류의 브라우저는 꽤 자주 목격할 것이다. 다른 모든 종류의 브라우저와 마찬가지로 코드 페인에는 모두 동일한 코드 개발 기능들이 있음을 기억하라.


이러한 '~로의 참조' 명령이 모든 참조를 잡아내지 못하는 상황이 있음을 인지해야 한다. 이러한 상황은 참조가 런타임 시에만 표시되고 정적인(static) 코드에선 표시되지 않을 때 발생한다. 예를 들어, 런타임 시 객체를 (그것이 주로 상주하는 잘 알려진 객체 변수 외에) 다른 변수로 넣은 후 참조를 다시 시작할 경우, 브라우저가 그러한 참조를 찾아낼 것이라고 기대해선 안 된다 (그 이름을 검색하는 것이 아니다). 물론 그 변수로의 참조를 대신 검색하는 것은 항상 가능하다. 앞장에서 제공한 조언을 따라 하나의 accessing 메서드 내(또는 두 개의 메서드-get에 하나와 set에 하나) 변수로 직접 접근할 때도 발생한다. 그러면 당신이 찾게 될 해당 변수에 대한 유일한 참조는 accessing 메서드에 있을 것이다. 이 과정을 간략하게 살펴볼 것이다.


클래스를 선택할 때는 프로토콜 페인 operate 메뉴에서 find method...를 이용해 해당 클래스에 의해 구현되는 메서드의 알파벳순으로 된 리스트를 (때로는 거대한 크기) 생성할 수 있다. 그 리스트에서 메서드를 선택하면 브라우저에 표시될 것이다. 리스트는 클래스에 의해 상속된 메서드가 아니라 클래스에서 구현된 메서드를 포함하고 있음을 기억하라. 계층구조를 (계층구조 브라우저를 이용해) 수동으로 검색하는 방법과, 앞에서 클래스가 이해하는 전체 메서드 집합을 볼 때 사용한다고 언급한 바 있는 전체(full) 브라우저를 이용해도 좋다.


Ass image 14 02.png
누가 update: 를 실행하는지 요청하여 생성된 메서드 리스트 브라우저


가장 우측에 있는 메뉴는 아마도 시스템에서 작동 방법을 찾는 데 가장 유용한 명령을 포함할 것이다. 특정 메서드를 보고 있을 때 senders를 선택하면 메시지 표현식에서 특정 메서드명이 (선택자) 나타나는 곳을 모두 표시할 것이다. 이는 accessing 메서드를 통해 변수로의 참조를 찾는 방법이다. 경고: 시스템은 그것이 표시한 표현식이 당신이 지금 보고 있는 메서드이며 당신이 실제로 호출하게 될 메서드인지 알려줄 수 없다. 그 이유는 메시지가 전송되는 객체의 클래스에 따라 좌우되기 때문이다-이는 런타임 전까지는 알려지지 않는다 (다형성을 기억하는가? 기억할 수 없다면 제 2장을 다시 참조하라). 하지만 어떠한 메시지가 자신의 메서드를 호출할 수 있을 것인지 이해할 것이며, 당신의 메서드가 이전에 전혀 호출된 적이 없는지도 확인할 수 있다.


반복적으로 senders 명령을 이용하면 코드를 '거꾸로' 올라가면서 어떠한 메서드가 특정 메시지를 전송하는지, 누가 그러한 메서드를 호출하는지 등을 볼 수 있다. 시스템 코드를 탐구하기에 매우 유용한 방식이다.


하지만 여기 또 '알아야 할 점(gotcha)'이 있다. 메서드를 호출하는 데 perform: 을 사용한 경우, 메서드에 대한 그 참조는 개발 환경에서 확인할 수 없다. 기껏해야 메서드명이 소스 코드에서 리터럴 기호로 나타날 뿐이다 (최악의 경우 런타임 시 생성된다). 구문적으로 선택자가 아니므로 senders 명령에 의해 보일 수 없다.


inst var refs...와 senders 명령을 이용해 주기적으로 코드를 검색한 후 '죽은(dead)' 변수와 메서드를 제거하는 방법을 (perform: 을 통해서만 호출되는 메서드가 없다는 가정 하에) 고려할지도 모르겠다. 이는 다른 사람이 당신의 코드를 더 읽기 쉽도록 만드는 데 기여하는 또 다른 방법이다.


implementors 명령은 당신이 보고 있는 메서드를 구현한 클래스를 모두 보여줄 것이다. 이러한 기능은 당신이 보고 있는 클래스 이외에 특정 메시지를 전송할 수 있는 대상으로 무엇이 있을지 확인할 때 유용하다. 단, 당신이 보게 될 것은 '이해자(understanders; 메서드를 상속하는 모든 클래스)'에 해당하는 긴 리스트가 아니라 구현자(implementors)임을 기억하라.


이 메뉴에서 마지막에 해당하는 message 명령은 메시지가 전달되는 순서를 따르는 데 매우 강력하다. 특정 메서드를 살펴보고 있는데 그것이 다른 메서드를 몇 개 호출한다고 가정해보자 (대부분의 메서드가 그러하듯이!). messages를 선택하면 당신이 보고 있는 메서드가 사용하는 선택자의 리스트를 표시할 것이다. 그 중 하나를 선택하면 해당 메서드의 구현부를 모두 표시한 브라우저가 팝업될 것이다. 관심이 있는 한 가지를 선택해 코드를 살펴보고 다시 message를 이용하여 구현부에서 당신이 찾는 행위가 무엇이든 그것이 실제로 발생하는 곳으로 따라가 보자. 때때로 스몰토크의 메서드는 자신의 좀 더 일반적인 버전을 호출할 것이다. 이는 실제로 작업이 완료되기 전에 몇 회 반복될 수 있다. message 명령은 이러한 메시지 전송 사슬(chain)을 매우 쉽게 따르도록 해준다. 실제로 senders는 호출을 거꾸로 따르도록 허용하는 반면 messages는 전방향으로 따르도록 해준다.


마지막으로 살펴볼 브라우저 메뉴 명령은 코드 페인의 operate 메뉴에 위치한다. 마우스를 이용해 메서드에서 코드 한 조각을 선택 후 explain 명령을 선택하면 시스템은 잠시 멈춰 당신이 선택한 내용에 대한 '설명'을 제공한다. 메서드에서 상당히 논리적 조각을 선택해야 하지만 (무작위로 된 문자 시퀀스를 선택할 수 없다), 운이 좋다면 당신이 선택한 내용이 인스턴스 변수, 혹은 클래스 변수, 혹은 메서드 선택자, 혹은 다른 것이라고 알려줄 것이다.


설명(explanation)과 관련해 주목해야 할 사항이 몇 가지 있다. 첫째, 시스템은 당신이 보고 있는 코드로 설명을 삽입할 것이다. 하지만 시스템은 그것이 삽입하는 텍스트가 확실히 선택되었는지 확인하며, 그에 따라 삭제를 위해선 <delete> 키만 누르면 된다. 둘째, 설명은 주로 스몰토크 코드의 정보(snippet)를 포함하는데, 이것을 평가할 경우 설명하는 대상에 관한 더 많은 정보가 담긴 또 다른 브라우저를 하나 팝업시킬 것이다. explain 함수는 심지어 설명을 주석과 코드로 구조화하여 그거의 하위부분(subpart)을 선택하지 않아도 되게끔 해준다. 더 많은 정보를 원할 경우 do it으로 explain 명령을 따르면 된다. 그리고 <delete>를 누르면 다시 설명을 제거한다. 이는 브라우저에서 가장 유용한 기능들 중 하나로, messages 명령과 같이 주기적으로 사용해야 한다. 마지막 팁은 브라우저와 관련된다 (혹은 사실 어떤 코드 뷰와도 관련된다). 시스템에서 유용하게 제공하는 몇 개의 단축키가 있다. 매뉴얼에 전체 목록에 포함되어 있으나 여기서는 가장 유용한 두 가지 단축키만 소개하겠다. 표현식을 괄호로 싸고 싶다면 마우스로 표현식을 선택하고 <escape> 키를 누른 후 여는 괄호 문자를 입력하라. 시스템이 자동으로 표현식을 괄호로 닫을 것이다.


이 기법은 다른 '괄호치기(bracketing)' 문자에도 적용된다 (", ', E, {, <). 이것을 실행취소(undo)하려면 괄호치기된 표현식을 선택하여 (괄호치기된 문자를 포함하는 것이 아니라), <escape>를 입력한 후 여는 괄호 문자를 입력하라. 시스템이 자동으로 괄호를 제거할 것이다. 두 번째 단축키는 코드 뷰에서 <control>-t 또는 <control>-f를 입력 시, 시스템이 자동으로 ifTrue: 또는 ifFalse: 를 삽입할 것이다. 두 가지 단축키에 익숙해지면 다른 에디터에서 이러한 기능이 왜 없는지 궁금해질 것이다!


인스펙터 이용하기

클래스에 있어 브라우저 툴은 인스턴스에 있어 인스펙터와 같다. 인스펙터를 자유롭게 이용함으로써 (아래 다이어그램 참조) 코드가 생성한 인스턴스는 어떤 모양인지, 무엇을 결정하는지를 잘 이해할 수 있다.


Ass image 14 03.png
특정 객체를 검색하고 검사하기 위해 인스펙터의 '사슬'을 이용.


인스펙터를 여는 방법에는 여러 가지가 있다. 마우스로 표현식을 선택하고, operate 메뉴에서 inspect를 선택하면 표현식을 평가하고 결과에 인스펙터를 열 것이다. 표현식은 단일 객체가 될 수 있음을 기억하라. 예를 들어, 워크스페이스에 입력된 전역 변수명을 선택하고 operate 메뉴에서 inspect를 실행하면 변수가 포함하는 객체에 인스펙터가 열릴 것이다.


인스펙터를 열었다면, 검사한 객체 내 변수를 선택 시 새 메뉴를 팝업하여 해당 객체에 새 인스펙터를 열 수 있다. 이는 인스펙터를 양호하게 사용하는 데 있어 핵심이다. 변수를 반복 선택하고 새 인스펙터를 열면 객체들이 어떻게 연관되는지 보여주는 객체들의 '사슬'을 따라가면서 자신이 원하는 객체를 찾을 수 있다. 20개 또는 그 이상의 인스펙터를 열어야 하더라도 괜찮다. 필요한 인스펙터를 주의하여 열어두고 나머지는 닫으면 된다.


객체 참조의 사슬을 따라가면 당신이 찾고자 하는 객체를 거의 찾을 수 있다. 이 과정에서 가장 까다로운 부분은 첫 인스펙터를 열어두는 것이다. 이를 위한 한 가지 방법으로, 어떤 객체로든 inspect 메시지를 전송하여 인스펙터를 열어둘 것을 기억하는 방법이다. 이는 디버깅 중에 자신의 코드로 들어오게 되는 객체를 살펴보고 싶을 때 유용하다. myObject inspect 와 같은 표현식을 적절한 메서드로 삽입하기만 하면 된다. 디버깅 시 인스펙터를 사용하는 것은 다음 장에서 상세히 다룬다.


첫 번째 인스펙터를 열어두는 또 다른 방법으로는 당신이 열어둔 창의 모델, 뷰, 또는 컨트롤러를 검사하도록 window 메뉴를 수정하는 방법이 있다. 이 자체만으로 흥미로운 연습이 된다. 수정을 완료하면 이것이 매우 유용하게 시스템을 탐구할 수 있는 방법임을 깨달을 것인데, 특히 시스템의 사용자 인터페이스와 자신의 인터페이스 구성을 알아보는 데 유용할 것이다. 힘든 일은 아니지만 본장의 마지막에 '모범 답안'을 실어 도움을 주고자 한다.


Ass image 14 04.png
일부 코드를 실행하는 데 사용되는 인스펙터로, 이번 경우 Smalltalk SystemDictionary 내에서 실제 클래스인 모든 객체들을 뽑아낸다.


인스펙터에서도 코드를 실행할 수 있음을 잊지마라. 코드는 검사하는 객체의 컨텍스트에서 실행된다. 따라서 객체로 메시지를 전송하고 싶다면 self 로 전송하라. 앞 페이지에 실린 다이어그램과 같이 인스펙터의 우측 페인에 표현식을 입력한 후 operate 메뉴에서 do it, print it, 또는 inspect를 이용하라.


워크스페이스 이용하기

워크스페이스는 '스크래치패드'에 매우 유용하다. 이를 이용해 작은 코드 단편을 테스트해보거나 애플리케이션을 작동시키는 데 필요한 표현식을 유지한다. 개발 환경의 다른 모든 툴과 마찬가지로 원하는 수만큼 열어둘 수 있다. window 메뉴에 relabel as...를 이용함으로써 워크스페이스 창의 제목을 변경할 수도 있다.


애석하게도 저장된 이미지의 일부를 제외하고는 워크스페이스 창의 내용을 저장할 수 없다. 이러한 면이 불편하긴 하지만 클래스 내 하나 또는 그 이상의 '스크래치패드' 메서드를 생성하여 워크스페이스에 있던 코드를 이러한 메서드로 넣은 후 클래스를 file-out하는 방법이 있다. 워크스페이스에 있던 코드가 특히 해당 클래스의 테스트 혹은 연습과 관련되어 있었다면 file-out되는 클래스가 기존 클래스들 중 하나가 될 수도 있겠다. 아니면 해당 테스트 코드를 보관하기 위한 특수 클래스를 생성하는 방법도 있다.


워크스페이스에 코드의 완전한(self-contained) 단편을 작성하고 있다면 메서드에서와 동일한 방식으로-수직 막대(ㅣ)문자를 이용하여-임시 변수를 정의할 수 있다. 단, 이러한 변수들은 한 번의 do it, print it, 또는 inspect와 같은 길이만큼만 지속된다. 조금 더 오래 갖고 놀 객체를 유지하고 싶다면 전역 변수를 이용해도 문제가 없다. 표현식의 결과를 대문자로 시작하는 변수로 할당하기만 하면 시스템은 그것을 전역으로 정의하길 원하는지 물을 것이다. 이후에 전역 변수를 제거하길 원할 경우 전역 변수 Smalltalk를 검사하라. 이는 SystemDictionary 라는 클래스의 인스턴스를 (사실 유일한 인스턴스다) 포함한다. 당신의 변수를 검색하여 좌측 페인 내 operate 메뉴를 이용하여 제거할 수도 있다. 쉽게 찾을 수 있도록 전역 변수 이름 앞에는 같은 이름을 붙이면 도움이 된다 (MyView, MyFile, MyWidget과 같이 명명).


시스템 내 거의 모든 텍스트 뷰는 워크스페이스로 사용할 수 있음을 명심하라. 표현식을 빠르게 입력하여 평가해야 하는 경우 (예: MyClass initialize) 아무 곳에나-워크스페이스, 브라우저, 디버거, 트랜스크립트-입력하라. 평가하고 난 후에는 필요 시 cancel 또는 <delete> 키를 이용해 제거할 수 있다. 이 방법은 열린 워크스페이스를 찾거나 새 워크스페이스를 여는 것보다 훨씬 빠르다.


VisualWorks 의 구버전과 (2.0 버전 이하) ObjectWorks 에는 시스템 워크스페이스(system workspace)이라는 것이 있다. 이는 VisualWorks 2.0 이 현재 런처 메뉴를 통해 제공하는 기능들을 전부 실행하는 유용한 코드 정보를 모두 포함한다. 스몰토크 구버전을 사용 중이라면 시스템 워크스페이스를 조사해볼 필요가 있겠다.


코드의 성능 조정하기

앞장에서는 코드의 효율성을 향상시킬 수 있는 코딩 기법을 몇 가지 살펴보았다. 여기서는 개선이 필요한 영역을 확인하도록 도와주고 그것을 개선할 수 있었음을 증명해주는 툴을 살펴볼 것이다.


코드의 성능은 두 가지 요인, 코드가 얼마나 효율적인지와 코드가 실행되는 머신이 얼마나 빠른지에 따라 좌우된다. VisualWorks 개발 환경은 이러한 것-타이밍(timing), 벤치마킹(benchmarking), 프로파일링(profiling)-을 측정하는 세 가지 방식을 제공한다. 이 중 벤치마킹과 프로파일링은 Advanced Programming ObjectKit 에 속하므로 해당 추가 선택 항목이 없다면 이론의 듣기만 가능할 것이다.


코드 타이밍

다음 표현식을 평가하고 결과를 인쇄 또는 검사함으로써 어떤 코드의 조각을 실행할 때 스몰토크가 소요하는 시간을 맞출 수 있다. 블록 내 주석에 시간을 맞추고자 하는 코드를 교체하기만 하면 된다. 이를 실행하는 여러 방법을 비교하기 위해 아래의 표현식을 이용하라.

Time millisecondsToRun; ["Your code goes here."3.


코드를 실행하는 데 소요되는 시간에 철저하게 영향을 미칠 수 있는 요인에 여러 가지가 있음을 기억하라. 여기에는 당신이 호출하는 메서드가 메서드 캐시에 있는지, 이미지 일부 또는 전체가 보조기억 장치로 옮겨졌는지 (swap out) 여부가 (가상 메모리가 있을 경우) 포함된다. 따라서 그러한 모든 과학적 테스트와 마찬가지로 여러 번 반복하여 최고, 최저, 평균값을 적절하게 취하는 것이 좋겠다. 여러 번 코드를 실행하도록 (가령 1000회) 코드를 작성하고 결과 시간을 적절하게 나눌 수도 있겠다.


벤치마킹

코드가 실행 중인 컴퓨팅 플랫폼의 기본 성능을 평가할 수 있도록 VisualWorks 는 당신이 실행할 수 있는 편리한 벤치마크 집합을 제공한다. 이것은 시스템의 모든 유형의 기능을 검사하고, 결과를 보고한다. 어떤 벤치마크가 실행될 것인지, 결과는 어떻게 보고될 것인지 제어할 수 있다. 플랫폼 구성을 변경할 때 (메모리 또는 프로세서 속도 변경) 시스템이 어떻게 다르게 실행되는지 비교하기 위해 벤치마크를 이용할 수도 있다. 애플리케이션을 실행하게 될 플랫폼의 성능과 당신이 개발 중인 플랫폼의 성능을 비교하길 원할 수도 있다.


프로파일링

VisualWorks가 제공하는 세 번째 성능 평가 툴은 프로파일러(profiler)이다. 프로파일러에는 두 가지 종류가 있다-코드에 소요되는 시간을 살펴보기 위한 시간 프로파일러, 코드 내 메모리가 어디로 할당되는지를 살펴볼 수 있는 할당 프로파일러. 두 가지 모두 당신이 제공하는 코드의 블록에서 작용한다. 코드를 여러 번 실행하고, 통계적 표본추출 기법을 이용해 무엇이 일어나는지 모니터한다. 이러한 점 때문에 당신은 수반하는 문서를 순서대로 읽어야만 유효한 결과를 얻기 위한 반복 횟수와 표본 크기를 올바로 얻을 수 있다.


Ass image 14 05.png
시간 프로파일러에 의해 생성된 계층적 시간 프로파일.


프로파일러는 앞 페이지의 다이어그램에서 표시된 것과 유사한 계층적 분할(hierarchical breakdown) 형태로 결과를 생성한다. 무슨 일이 일어나는지 이해하기 위해서는 제공된 툴을 이용해 이를 살펴볼 수 있다. breakdown은 총액(total)의 퍼센트로 할당 또는 횟수를 표시한다. breakdown 부분을 늘이거나 (일반 글씨체) 줄이면 (굵은체) 살펴보는 데 도움이 될 것이다.


다이어그램은 시스템 코드의 일부에서 프로파일러를 실행한 결과를 표시하지만 자신의 코드에 프로파일러를 사용할 경우 시스템이 어디서 시간을 소요하는지와 관련해 예상치 못한 일이 발생할 수 있다. 프로파일러를 이용하고 결과에 따라 조치를 취함으로써 상당한 개선이 가능하다. 하지만 변경을 하기 전과 후에 코드를 꼭 프로파일링하도록 하라. 그래야만 실제로 개선되었는지 여부와 개선의 범위를 정확히 알 수 있다.


이미지 관리하기 (혹은 작업 분실하지 않기!)

스몰토크 개발 환경은 애플리케이션을 개발하기 위한 매우 강력한 방법들을 제공한다. 이 방법들을 최대한 활용하면 매우 생산적일 가능성이 있다. 또한 간단한 예방을 하지 않으면 작업한 내용을 한순간에 날리는 수도 있다! 이번 절에 실린 조언은 쓴 경험을 바탕으로 한다.


VisualWorks 에는 몇 가지 매우 강력한 코드 관리 툴이 있지만 자신의 요구가 너무 복잡하거나 비용이 많이 들 경우 VisualWorks에 포함된 기능만으로도 완벽히 훌륭한 작업을 수행할 수 있다. 따라서 스몰토크는 작업을 저장하는 두 가지 방법을 제공한다-'이미지 저장(save-image)' 기능과, 파일의 file-out 기능.


첫 번째 규칙은 '이미지 저장' 기능을 사용하는 것이다. 이 기능은 가끔씩 사용하도록 하라-특히 시스템에 결정적인 변경을 실행하기 전에 사용하라. 꽤 속도가 빠른 컴퓨터를 사용하고 있고 자신의 이미지가 너무 크지 않을 경우 (따라서 저장에 시간이 많이 소요되지 않도록) 최소 30분마다 '이미지 저장'을 해야 한다. 반복하기 싫은 변경을 적용한 이후, 그리고 시스템에 손상을 줄 수 있는 행동을 실행하기 이전에도 이미지를 저장하라. 이에 해당하는 작업으로는 시스템 메서드의 재정의를 들 수 있는데, 특히 사용자 인터페이스의 작동 방식을 수정하는 경우가 해당된다. 창 열기를 처리하는 코드 손상시키기, 시스템이 당신에게 알려줄 통지자를 열도록 하기, 손상된 코드를 호출하도록 야기하기, 통지자를 열도록 야기하기를 통해 절대 복구할 수 없는 루프로 빠지기가 매우 쉽다... 어느 순간 화면은 제거할 수 없는 알림으로 뒤덮인다! '이미지 저장' 기능의 사용에 더해 완료된 코드의 복사본을 이미지 외부에서 유지할 수 있도록 file-out 기능도 활용해야 한다. 이는 필요하다고 증명되면 처음부터 이미지를 재빌드할 수 있도록 확보한다. 사실 개발 도중에 쓰레기 수집기(garbage collector)가 도달할 수 없는 쓰레기가 생성되었을 때 이를 정리하거나, 더 이상 재생성 방식을 인식하지 못하는 이상한 인스턴스에 의존하지 않도록 확보하기 위해서라도 이미지를 주기적으로 재빌드하는 것은 꽤 좋은 생각이다.


.image를 관리할 때 중요한 또 다른 한 가지는 changes 파일을 절대 삭제하지 않는 것이다. 이 파일은 모든 이미지 파일에 따라옴을 눈치챌 것인데, 당신이 추가하거나 수정한 소스 코드를 모두 포함한다. 메서드를 변경할 때마다 새 소스 코드가 changes 파일의 끝에 추가된다. 파일에 있었던 오래된 버전은 파일에 계속 남는다. 사실상 이는 당신이 실행한 변경내용에 대한 히스토리의 로그를 얻게 됨을 의미한다. 이러한 로그는 이미지에 영구적인 효과를 미치는 do its를 포함한다 (예: 전역 변수의 정의).


이미지가 손상되면 (그리 어려운 일도 아니다), 복구를 위해 change list (아래 다이어그램 참조)라 불리는 툴을 사용할 수 있다. 이는 시스템에서 가장 신비로운 툴들 중 하나인데 어쩐지 사용하기가 거북하지만 거의 말 그대로 당신의 목숨을 구해줄 수 있으므로 사용 방법을 학습하는 편이 나을 것이다. 이미지의 손상되지 않은 가장 최신 버전부터 시작해 런처에서 Changes 메뉴에서 change list를 열어라. 깨진 이미지의 changes 파일을 툴로 읽어오기 위해서는 상단 좌측 페인에 operate 메뉴에서 file in/out->read file/directory 명령을 이용하라. 이후 이미지의 재구성을 위해 해당 파일 조각을 선택적으로 다시 볼 수 있다. 운이 좋으면 이미지가 손상되기 직전까지의 모든 것을 다시 볼 수 있을 것이다. 볼 수 없다 하더라도 한참 찾아봐야 한다. 완료되면 새 파일에 대해 즉시 '이미지 저장'을 실행하도록 하라 (마지막 작업 버전을 오버라이드하지는 말라).


Ass image 14 06.png
changes 파일로부터 이미지를 재빌드하는 데 사용되는 change list 툴.


이번 장을 통해, 스몰토크 개발 환경에서 프로그래밍 툴의 사용을 향상시키는 다양한 방법들을 살펴보았다. 특히 시스템 브라우저 및 그와 유사한 툴에서 검색 명령을 사용하는 방법을 살펴보았다. 이들은 메시지 전송을 전방향, 후방향으로 따르도록 해주는데, 이는 시스템 클래스들 중 하나가 (심지어 자신만의 클래스까지) 어떻게 작동하는지 이해할 때 큰 도움이 된다.


뿐만 아니라 인스펙터를 여는 방법과 (아래 내용 참조) 객체 인스턴스를 탐구하기 위해 인스펙터의 '사슬'을 사용하는 방법도 살펴보았다. 인스펙터에서 코드도 실행 가능함을 기억하라.


워크스페이스는 모든 사람이 다른 방식으로 사용하지만 공통적인 방식 한두 가지를 살펴보면서 시스템 내 어떤 텍스트든 임시 워크스페이스로 사용 가능함을 언급하였다.


앞장에서 효율적인 코드를 작성하는 법에 관한 토론에 따라, 자신만의 코드의 성능과 그것을 실행하는 컴퓨터의 성능을 어떻게 측정하는지도 살펴보았다.


마지막으로, 단순히 '이미지 저장'과 file out 기능을 이용해 작업한 내용을 손실하는 파국을 피하는 방법을 고려하였다. 최악의 상황이 발생하면 change list 툴을 이용해 changes 파일로부터 작업을 복구할 수 있다는 내용도 학습하였다.


우리가 논한 내용을 어느 정도 시도해보면 더 효율적인 프로그래머가 될 수 있을 뿐만 아니라 클래스 라이브러리를 탐구하고 이해하는 자신의 능력 또한 향상됨을 발견할 것이다. 이러한 탐구와 이해기술은 스몰토크 개발 환경의 전력을 인식하는 데 있어 매우 중요하다.


때마침 우리가 여기서 살펴본 모든 툴과 명령은 다음 장의 주제에 해당하는 디버깅 시에도 똑같이 유용한 것이다.


부록: Window Menu 수정하기

이번 장에서 우리는 당신이 보고자 하는 객체에 인스펙터를 열기 힘든 경우가 종종 있다고 언급한 바 있다. 이 문제에 대해 몇 가지 해결책이 있는데, 그 중 하나는 다음과 같다.


다음 페이지에 보면 스몰토크 코드 일부가 있다. 해당 코드를 열거된 바와 정확히 똑같이 파일에 (브라우저가 아닌-스몰토크 파일 에디터 또는 다른 에디터를 사용) 입력한 후 이미지로 file in하라.


그러면 모든 창의 window 메뉴에 새로운 하위메뉴(sub-menu)를 추가하는 데 필요한 수정을 할 수 있을 것이다. 하위메뉴에 위치한 세 개의 명령은 window의 모델, window 객체 자체, 또는 window의 컨트롤러를 검사하도록 해준다. 그곳에서 특정 모델 객체 또는 창 내부에 있는 특정 뷰를 검색할 수 있다.


코드는 StandardSystemController의 initialize 메서드를 새로운 하위메뉴 inspectMenu를 포함하는 새 메뉴를 ScheduledBlueButtonMenu(클래스 변수)로 넣는 메서드로 대체한다. 그리고 세 개의 inspect 명령을 구현하기 위해 세 개의 메서드를 StandardSystemController로 추가한다. File-in은 마지막으로 새 메뉴를 생성하기 위해 StandardSystemControll로 initialize를 전송하는 일을 한다.


해당 코드는 VisualWorks의 1.0와 2.0 버전에서는 (그리고 ObjectWorks 의 4.0과 4.1 버전) 잘 작동하는 듯 보이지만 모든 것이 그렇듯 자신의 시스템에서 올바로 작동할 것이라는 보장은 할 수 없다. 본인의 책임 하에 사용해보라.

'StandardSystemController class methodsFor: 'class initialization'

initialize

	| inspectMenu |

	inspectMenu := PopUpMenu
		labels: 'model\window\controller' withCRs
		values: #(#inspectModel ftinspectWindow #inspectController).

	ScheduledBlueButtonMenu := PopUpMenu
		labels: 'relabel as...\refresh\move\resize\fronfcback\collapse\inspect\close' withCRs
		lines: #(18)
		values: ((OrderedCollection wifchAll:
			#(#newLabel ftdisplay #move #resize ftfront ftback ftcollapse)}
				add: inspectMenu; add: ftclose; yourself).! 1

!StandardSystemController methodsFor: 'menu messages' 1

	inspectModel
		model inspect.1

	inspectWindow
		view inspect.!
	inspectConfcroller
		self inspect.1 !

StandardSystemController initialize.


Notes