Содержание сайта
Главная Новичку Цитаты Реализации Статьи Документация
Компании Программы Ссылки Обсуждение Обсуждение 2 Гостевая

Dolphin Smalltalk, Part II.
Продолжаем рассказ о Dolphin Smalltalk XP. В данной статье будут продемонстрированы некоторые уникальные возможности, возможные только в динамической среде разработки.

Bouncing Balls - Refactoring

В поставку Dolphin Smalltalk входит демонстрационное приложение Bouncing Balls. Чтобы его запустить, необходимо открыть папку Sample Applications из главного окна среды и там выбрать иконку Bouncing Balls.

Bouncing Balls

Откроется окно с двадцатью скачущими шариками, имеющие случайные координаты и скорость, и раскрашенные в один из трех цветов.

Оставим окно открытым, так, чтобы в дальнейшем видеть, что в нем происходит, и перейдем к следующему шагу.

Классы этого приложения можно найти, используя стандартные средства Package Browser или System Browser. В нашем случае второе подходит больше, т.к. нам необходим доступ к исходному коду классов. В списке установленных пакетов необходимо отыскать пакет BouncingBalls. Справа появится перечень классов, которые в него в ключены. В нашем случае их два - BouncingBallView и Ball.

Bouncing Balls

Как известно, Dolphin Smalltalk постоен на базе визуальной библиотеки MVP (Model-View-Presenter), в которой данные отделены от представления/управления. В случае приложения BouncingBall роль представления играет класс BouncingBallView, а моделью является экземпляр класса OrderedCollection. Это можно увидеть, заглянув в метод BouncingBallView class>>defaultModel.
И, соответственно, экземпляры Ball заносятся в коллекцию для хранения информации о шариках.

Настало время первой демонстрации. Существенным является то, что демонстрационное приложение все время работает на фоне.

Найдите в классе BouncingBallView метод step. В первой строчке указано имя самого метода. Перейдите ко второй строчке и введите там команду:

Bouncing Balls
	self halt.

Наличие завершающей точки существенно, т.к. это обозначение конца операции в языке Smalltalk, также, как в человеческом языке обозначается конец предложения. Теперь нажмите правую кнопку мыши в тексте метода и выберите первую команду - Accept. Можно также воспользоваться комбинацией клавиш Ctrl+S.

Если это проделать, то в этот же момент появится окно с ошибкой и предложением выбрать четыре альтернативы - Debug, Resume, Terminate и Copy. На данный момент нас интересует команда Debug.

Bouncing Balls

При ее выборе появится окно отладчика с сообщением Hard coded breakpoint. И оно покажет точно на наш введенный оператор. При этом, если посмотреть на демонстрационное приложение, то, окажется, что все шарики застыли на месте. Отладчик остановил управление этого процесса там, где мы поставили жесткую точку останова.

На месте этой точки останова может случиться любая другая ошибка. Но в любом случае, наше поведение будет примерно одинаковым - мы можем исправить ошибку непосредственно в отладчике. В нашем случае необходимо удалить строчку, которая вызвала ошибку, как и раньше, выбрать команду Accept и продолжить выполнение командой Go (горячая клавиша F5). При этом окно отладчика исчезнет и демонстрационное приложение будет выполняться как прежде, как будто ничего и не произошло.

Стоит сказать, что на сегодняшний день существует немало средств разработки, которые позволяют делать нечто подобное. В среде Microsoft Visual C++ 6.0 эта возможность называется Debug & Continue. Но, как было видно, в Smalltalk не существует паузы на компиляцию, программа готова к работе практически сразу, как только введен ее исходный код. И такой возможностью Smalltalk обладал еще с середины 70-х, как и многими другими, о которых пойдет речь ниже.

Bouncing Balls

Рассмотрим несколько более сложный пример.

Если взглянуть на метод BouncingBallView>>step, то он может показаться большим и трудночитаемым. Сразу, что бросается в глаза - это большой цикл. Такие методы подлежат рефакторингу, чтобы упростить процесс чтения/сопровождения.

Первое, что приходит на ум в данной ситуации - применить рефакторинг "извлечь метод". В состав Dolphin Smalltalk XP стандартно входит Refactoring Browser, который упрощает рутинную работу.

Для начала, необходимо выделить содержимое блока операторов в квадратных скобках [ :each | ... ]. После этого следует вызвать контекстное меню и выбрать Refactorings -> Extract Method....

Появится окно, которое попросит ввести имя нового метода, причем у него должен быть один параметр each. Поэтому нам нужно ввести бинарный оператор или имя с двоеточием на конце, пусть это будет stepBall:. После ввода появится новый метод с соответствующим именем, а тело цикла исходного метода упростится до одного вызова. При этом, шарики в окне демонстрационного приложения все время продолжали прыгать, только на одно мгновение произошла задержка на момент выполнения рефакторинга. Как мы уже видели, неверное изменение в работающем методе может вызвать отладчик. У нас этого не произошло, значит все в порядке.

Bouncing Balls

Продолжим далее. Если взглянуть на метод stepBall:, то у него тоже есть проблема - он подпадает под anti-pattern VerbSubject. Это означает, что метод выполняет действие над сторонним объектом, в то время, как сам объект должен его реализовывать.

На этот раз воспользуемся рефакторингом Extract to Component. Сначала выделим тело метода, кроме последней строки ^self invalidate. Она, очевидно, относится к компетенции самого объекта. После этого активизируем рефакторинг через контекстное меню - Refactorings -> Extract to Component....

Он предложит список полей, в которые можно извлечь новый метод. Выберите аргумент each.

После этого будет предложен список классов, куда извлекать метод. В нашем случае это только Ball.

После этого нужно будет ввести имя аргумента, который заменит объект self исходного метода. Введите aView.

И, наконец, имя нового метода с одним аргументом. Пусть это будет stepInView:.

На этом рефакторинг завершен. Класс BouncingBallView теперь содержит только самые простые методы, и логика движения шарика перенесена в класс Ball. В то время как само приложение продолжает работать.


Bouncing Balls - Inspecting

В предыдущем примере демонстрационное приложение подверглось преобразованиям, которые изменили его структуру, но не изменили поведение. Как известно, такие преобразования называются рефакторингом. Теперь мы попробуем сделать нечто другое - попробуем изменить состояние программы не трогая ее исходного кода. Такой процесс называется инспектированием.

Для начала нам нужно получить доступ к объектам приложения. В предыдущем примере у нас это получилось с помощью жесткой точки останова. Т.е. один из способов - воспользоваться отладчиком. Попробуем пойти по-другому.

Bouncing Balls

Откроем средство под названием Flipper Inspector и перейдите к третьем закладке Visual Object Finder. На ней находится иконка с лупой, которую нужно потащить мышью и бросить в окно с шариками. Икно покажет, что найден объект a BouncingBallView. После этого необходимо переключиться на вторую страницу закладки, в правом поле ввести self model и вызвать команду Inspect (комбинация Ctrl+I).

Должно открыться окно инспектора объектов для объекта an OrderedCollection. Оно будет содержать двадцать объектов a Ball, представляющих шарики в окне демонстрационного приложения.

К этому окну инспектора можно прийти и другим путем, не используя Flipper Inspector. Для этого необходимо открыть окно Workspace и ввести:

	BouncingBallView allInstances

Таким образом можно получить список всех объектов указанного класса. Чтобы просмотреть их, нужно вызвать команду Inspect. Должен появится список из одного элемента, если, конечно, запущена только одна копия демонстрационного приложения. В указанном списке следует выбрать этот единственный элемент, в правом поле ввести self mode и снова сделать Inspect.

Bouncing Balls

Любой из указанных способов приводит нас вот к такому окну инспектора. Каждый из шариков можно просмотреть и изменить. Например, раскройте поля первого шарика, выделите поле velocity, перейдите в правое поле, и измените его содержимое на 0 @ 0. После этого вызовите комманду Accept. При этом в окне приложения один из шариков должен застыть на месте. Т.е. изменяя содержимое объектов можно непосредственно влиять на ход выполнения программы, даже если она не находится под отладчиком.

Теперь верните выделение на сам объект an OrderedCollection. Очистите правое поле и введите:

	self select: [ :ball | ball position y < 150 ]

Если выражение не помещается на одну строку, то его нужно выделить, т.к. без выделения среда Smalltalk пытается выполнить только текущую строку. Выделение позволяет выполнить многострочные выражения.

Теперь если выполнить Inspect, то появится окно инспектора, содержащее шарики с координатой y, меньшей 150 на момент выполнения команды. В этом можно убедиться, выполнив команду несколько раз подряд.

Bouncing Balls

Теперь измените выражение следующих образом:

	self removeAll:
		(self select:
			[ :ball | ball position y < 150 ])

И если теперь вызвать команду Execute (комбинация Ctrl+E), то шарики, которые попали в верхнюю полосу окна, неожиданно исчезнут.


Заключение

На этом простом примере можно получить представление, как происходит разработка в среде Smalltalk. Программа является не просто набором исходным текстов, сохраненных на диске, а реально работающими объектами.
Написание программы заключается в последовательном изменении состояния ее объектов/классов, в любой момент времени в систему можно внести практически любое изменение, осутствует привычный цикл разработки edit-compile-run-debug. Программист не тратит время на низкоуровневые детали, вся разработка состоит только лишь из стадии выполнения/инспектирования.

Все эти характеристики делают Smalltalk исключительно эффективным языком с непревзойденными средствами разработки.




Есть комментарии? Пишите.