Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0 > Статьи

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Закрытая тема
Старый 10.03.2008, 15:46
Iv вне форума Посмотреть профиль Отправить личное сообщение для Iv Посетить домашнюю страницу Iv Найти все сообщения от Iv
  № 1  
Iv
 
Аватар для Iv

Регистрация: Apr 2001
Адрес: Moscow
Сообщений: 1,475
Arrow Портируем, рефакторим, оптимизируем

В нескольких топиках обсуждались вопросы оптимизации кода и возникла идея рассмотреть это на конкретном примере: взять готовый код, причесать и оптимизировать. Поскольку предложенный пакет классов на AS2, то добавился еще один шаг - портирование на AS3.

Собственно код, который будем использовать взят с сайта Helen Triolo: http://www.flash-creations.com/notes...svgtoflash.php
Немаловажным моментом является то, что Helen разрешает (даже приветствует) подобные действия с ее кодом и своими действиями мы не нарушаем ее законных интересов.
Хочется, чтобы процесс был коллективным, но чтобы как-то упорядочить и на выхлопе получить не тонну обсуждений, а что-то вроде статьи, прошу придерживаться следующего регламента:

- до полного окончания прошу никого в этот топик не писать; Если вы хотите получать уведомления, просто в левом верхнем углу кликните на иконку "Подписаться на эту тему".
- я выкладываю код - результат очередного этапа, с пояснениями что сделано и зачем.
- предложения, вопросы, обнаруженные ошибки участники скидывают мне на мыло: ivan.dembicki на gmail, с сабжем "Flasher.ru - Портируем, рефакторим, оптимизируем".
- мы их приватно обсуждаем, затем я резюмирую здесь результат, разумеется, с указанием авторства.
- выкладывается исправленный код с пояснениями что сделано и зачем.
- после этого переходим к следующему этапу.

Буду очень благодарен, если кто-то из модераторов согласится помочь в поддержании порядка - удалении нерегламентированных постов.

Процесс делим на этапы:
I. Портируем
II. Рефакторим
III. Оптимизируем

Поехали.
__________________
http://realaxy.com


Последний раз редактировалось Iv; 10.03.2008 в 16:18.
Старый 10.03.2008, 16:15
Iv вне форума Посмотреть профиль Отправить личное сообщение для Iv Посетить домашнюю страницу Iv Найти все сообщения от Iv
  № 2  
Iv
 
Аватар для Iv

Регистрация: Apr 2001
Адрес: Moscow
Сообщений: 1,475
По умолчанию Подготовка

Заходим на сайт http://www.flash-creations.com/notes...svgtoflash.php идем в конец страницы, открываем окно downloads и скачиваем себе на комп svgtoflash.zip - он 11-й по списку.

Создаем новый AS3 проект (я использую FDT и вам рекомендую), называем его SVGToFlash, затем в винде открываем папку SVGToFlash и закидываем в нее содержимое ZIP файла. В FDT выделяем папку SVGToFlash и жмем F5.
Должна получиться структура файлов как на прилагаемой картинке.
Название: InitStructure.gif
Просмотров: 5788

Размер: 6.8 Кб
__________________
http://realaxy.com


Последний раз редактировалось iNils; 10.03.2008 в 16:29.
Старый 10.03.2008, 16:57
Iv вне форума Посмотреть профиль Отправить личное сообщение для Iv Посетить домашнюю страницу Iv Найти все сообщения от Iv
  № 3  
Iv
 
Аватар для Iv

Регистрация: Apr 2001
Адрес: Moscow
Сообщений: 1,475
По умолчанию Портирование. Задачи

Теперь мы можем приступисть к этапу портирования проекта на AS3.

Задача этого этапа:
при минимальном количестве изменений в проекте сделать его работоспособным.

На этом этапе мы стараемся по возможности не касаться логики приложения, его структуры и именований.
Не забываем: мы нацелены на то, чтобы проект просто запустился под AS3 и дал результаты, аналогичные AS2.
__________________
http://realaxy.com

Старый 10.03.2008, 18:01
Iv вне форума Посмотреть профиль Отправить личное сообщение для Iv Посетить домашнюю страницу Iv Найти все сообщения от Iv
  № 4  
Iv
 
Аватар для Iv

Регистрация: Apr 2001
Адрес: Moscow
Сообщений: 1,475
По умолчанию Начинаем портировать

Подготовка FLA файла.

Открываем во Flash файл svg_displayinflash.fla.
Изменяем настройки файла:
File - Publish Settings - Flash
устанавливаем FlashPlayer 9 и ActionScript 3.0
Заходим в настройки ActionScript 3.0 и устанавливаем все галочки кроме Strict Mode.
OK.OK.

Затем добавляем папку src в путь к классам:
Edit - Prefences - ActionScript - Actionscript 3.0
добавляем строку ./src и выставляем ее второй по порядку. OK.

Выделяем кадр actions и закомментируем единственную строку кода
// #include "svg_displayinflash.as"

Затем задаем Document class: SVGDisplayInFlash, Flash ругнется отвечаем OK.

На этом пока заканчиваются изменения во FLA файле, сохраняем.

Переходим в FDT,
в проекте создаем папку src, добавляем ее в class path: правый клик на папке, Source Folder - Add to Classpath.

Создаем в этой папке новый класс: SVGDisplayInFlash - если помните, мы класс с этим именем задали как Document Class.
Поскольку у нас в руте есть именованые объекты holder и msg, инициализируем их в этом классе:
Код AS3:
package {
	import flash.display.MovieClip;
	import flash.text.TextField;
 
	public class SVGDisplayInFlash extends MovieClip {
 
		private static const HOLDER_NAME:String = "holder";
		private static const MESSAGE_NAME:String = "msg";
 
		private var holderMc:MovieClip;
		private var messageTxt:TextField;
 
		public function SVGDisplayInFlash() {
			initInstance();
		}
 
		private function initInstance():void {
			trace("SVGDisplayInFlash.initInstance()");
			initStageObjects(); 
		}
 
		private function initStageObjects():void {
			holderMc = this[HOLDER_NAME] as MovieClip;
			messageTxt = this[MESSAGE_NAME] as TextField;
			trace("SVGDisplayInFlash.initStageObjects()");
			trace("\t", holderMc, messageTxt);
		}
	}
}
Сейчас, если мы во Flash скомпилируем проект, то в окне output получим вот такой текст:

Код HTML:
SVGDisplayInFlash.initInstance()
SVGDisplayInFlash.initStageObjects()
	 [object MovieClip] [object TextField]
Добейтесь того, чтобы всё стработало именно так.
__________________
http://realaxy.com


Последний раз редактировалось iNils; 20.12.2010 в 13:17.
Старый 10.03.2008, 18:17
Iv вне форума Посмотреть профиль Отправить личное сообщение для Iv Посетить домашнюю страницу Iv Найти все сообщения от Iv
  № 5  
Iv
 
Аватар для Iv

Регистрация: Apr 2001
Адрес: Moscow
Сообщений: 1,475
По умолчанию Повторяем структуру

Для того, чтобы файлы AS2 нам не мешались, создадим папку temp и забросим все AS2 файлы в эту папку.

Затем создадим иерархию папок com.itechnika.svg и создадим пустые классы Math2, PathToArray, String2.

В итоге должна получиться вот такая картина происходящего:

(спасибо, iNils за помощь в публикации материалов)
Вложения
Тип файла: zip Structure2.zip (40.9 Кб, 470 просмотров)
__________________
http://realaxy.com


Последний раз редактировалось Iv; 10.03.2008 в 22:34.
Старый 10.03.2008, 20:20
Iv вне форума Посмотреть профиль Отправить личное сообщение для Iv Посетить домашнюю страницу Iv Найти все сообщения от Iv
  № 6  
Iv
 
Аватар для Iv

Регистрация: Apr 2001
Адрес: Moscow
Сообщений: 1,475
По умолчанию Портирование классов пакета com.itechnika.svg

Порядок портирования классов определяестя следующим образом: вначале портируем классы, которые не требуют других классов проекта.

Затем переходим к тем классам, которые используют только портированные классы.
Внутри классов действуем по этой же схеме: вначале портируем те функции, которые не используют других пользовательских функций, и затем переходим к функциям, которые используют уже портированные.

Следуя этой логике, портирование классов начнем с Math2.
Для этого откроем созданный нами пустой класс Math2, и рядом AS2 версию этого класса.
Скопируем содержимое AS2 класса кроме первой и последней строки и вставим в тело AS3 класса.

Оценим степень разрухи: всё не так уж и страшно. Явных ошибок FDT не нашел, только подсветил отсутствие или неверную типизацию.

На этом этапе мы не будем приводить этот код в порядок, поскольку наши изменения могут повлиять на другие классы.
Проделаем аналогичную операцию с остальными классами в папке svg.
Класс String2, а его мы портируем вторым, также не доставил никаких хлопот.
В классе PathToArray потребовалось только импортировать XMLNode:
import flash.xml.XMLNode;

Тестирование.
На данном этапе мы не можем качественно протестировать соответствие кода стандартам AS3. Но минимальный тест всё-таки сделать необходимо.

Поскольку класс PathToArray использует и Math2 и String2, то нам для теста достаточно создать экземляр такого класса для того, чтобы компилятор Flash сказал свое веское слово.

Для того, чтобы создать экземпляр класса PathToArray нам потребуется посмотреть с какими параметрами он вызывается.
С этой целью найдем исходный ZIP файл, распакуем его в папочку на рабочем столе, откроем класс PathToArray и добавим трейсы:
Код AS3:
public function PathToArray(svgNode:XMLNode, dCmds:Array) {
	trace(svgNode)
	trace("-----------")
	trace(dCmds)
	trace("=====================")
	..................
Компилим AS2 проект, видим, что первый параметр - узел XMLNode (копируем один из них, что покороче), а второй параметр может быть пуст (это запомним).

Теперь можем добавить тест. В классе SVGDisplayInFlash добавим метод testPathToArray:
Код AS3:
private function testPathToArray():void {
	const path:String = "<path fill='#ED1C24' d='M261.5,52.3c11.9,3.2-5.2,21,32.9,31.6C288.5,35.5,261.5,52.3,261.5,52.3z' />";
	const foo:XMLDocument = new XMLDocument(path);
	new PathToArray(foo.firstChild, []);
}
и добавим его вызов в методе initInstance.

Результатом компиляции станет ругань компилятора. При ближайшем рассмотрении видим, что нет ничего страшного: дважды он ругается на то, что Number не может быть undefined и несколько раз на дублирование объявления переменных. Это несложно исправить.
В соответствующих местах заменяем проверку на равенство undefined на функцию isNaN:
Код AS3:
// if (thisColor == undefined) {
if (isNaN(thisColor)) {
И удаляем лишние var в дублирующихся объявлениях переменных в классах SVGDisplayInFlash и Math2.
Компилируем еще раз и убеждатемся в том, что компилятор не выдает ошибок.
Если это так, то можем переходить к следующей части.
__________________
http://realaxy.com


Последний раз редактировалось iNils; 20.12.2010 в 13:17.
Старый 11.03.2008, 02:24
Iv вне форума Посмотреть профиль Отправить личное сообщение для Iv Посетить домашнюю страницу Iv Найти все сообщения от Iv
  № 7  
Iv
 
Аватар для Iv

Регистрация: Apr 2001
Адрес: Moscow
Сообщений: 1,475
По умолчанию Финальный этап портирования

На этом этапе мы портируем svg_displayinflash.as, который представляет собой код инициализации приложения.
Код состоит из двух функциональных частей: загрузка данных в SVG формате и отрисовка полученного пути. Загрузка данных - дело известное, начнем с этого. Добавим в класс SVGDisplayInFlash методы инициализации загрузки и обработчик полученных данных:
Код AS3:
private function getSVGData(url:String):void {
	const loader:URLLoader = new URLLoader();
	loader.addEventListener(Event.COMPLETE, onSVGLoaded);
	loader.load(new URLRequest(url));
}
 
private function onSVGLoaded(event:Event):void {
	const loader:URLLoader = event.target as URLLoader;
	const data:String = loader.data as String;
	const svg:XML = new XML(data);
	trace(svg.toXMLString());
}
Обратите внимание на то, что мы можем немедленно протестировать загрузку данных, что и сделаем, добавив в initInstance вызов метода getSVGData, передав ему в качестве параметра url файла данных:
getSVGData(SVG_DATA_URL);

Если в результате компиляции не возникло проблем, то можем переходить к следующему шагу: портированию метода getShapes и процедуре его вызова.
Копируем и вставляем этот метод в класс SVGDisplayInFlash и видим, что FDT подсвечивает множество ошибок. Как это ни странно, но это очень хороший признак, что основная масса ошибок пришлась на последний этап портирования и говорит о правильно избранной стратегии действий. Сейчас у нас развязаны руки и мы можем вносить правки в код, не волнуясь о том, что это может чем-то навредить остальной части проекта. Однако мы не забываем, что на этом этапе наша задача - сделать код работоспособным с минимальными изменениями.
Копируем и вставляем объявления переменных, делаем их приватными. Если мы внимательны, то увидим, что переменная x будет конфликтовать со свойством мувиклипа, в котором мы ее объявили. Если мы невнимательны, то компилятор Flash об этом нам напомнит при первом же тесте.
Переименуем ее в svg:
Код AS3:
private var svg:XMLDocument = new XMLDocument();
private var conv:PathToArray;
private var paths:Array;
private var nPathNodes:Number;
Затем заменяем создание мувиклипа на добавление спрайта и получаем ссылку на объект graphics:
Код AS3:
// holder.createEmptyMovieClip("p"+iPath, iPath+1);
 
const drawLayer:Sprite = new Sprite();
holderMc.addChild(drawLayer);
const drawTarget:Graphics = drawLayer.graphics;
После этого заменяем все обращения holder["p"+iPath] на drawTarget.

Приступаем к портированию обработки загруженных данных. Пока мы можем пропустить обработку ошибок, поэтому просто переносим строки инициализации из оригинального метода xmlLoaded в метод onSVGLoaded:
Код AS3:
msg.text = "";
paths = x.firstChild.firstChild.childNodes;
nPathNodes = paths.length;
getShapes(0);
Заменяем msg на messageTxt и x на svg.
Добавляем парсинг полученных данных перед первым обращением к объекту svg:
Код AS3:
svg.ignoreWhite = true;
svg.parseXML(data);
Вот то, что в итоге должно было быть добавлено в класс:
Код AS3:
private var svg:XMLDocument = new XMLDocument();
svg.ignoreWhite = true;
private var conv:PathToArray;
private var paths:Array;
private var nPathNodes:Number;
 
private function onSVGLoaded(event:Event):void {
	const loader:URLLoader = event.target as URLLoader;
	const data:String = loader.data as String;
 
	messageTxt.text = "";
 
	svg.parseXML(data);
	paths = svg.firstChild.firstChild.childNodes;
	nPathNodes = paths.length;
 
	getShapes(0);
}
 
private function getShapes(iPath:Number):void {
	var dCmds:Array = new Array();
	var d:Array;
	var dp:Array;
 
	conv = new PathToArray(paths[iPath], dCmds);
 
	// draw the shapes in clips in holder movieclip
	// holder.createEmptyMovieClip("p"+iPath, iPath+1);
 
	const drawLayer:Sprite = new Sprite();
	holderMc.addChild(drawLayer);
	const drawTarget:Graphics = drawLayer.graphics;
 
	for (var i:Number=0; i<dCmds.length; i++) {
		d = dCmds[i];
		dp = d[1];
		switch (d[0]) {
			case "F" :
				drawTarget.beginFill(dp[0], dp[1]);
				break;
			case "S" :
				drawTarget.lineStyle(dp[0], dp[1], dp[2]);
				break;
			case "M" :
				drawTarget.moveTo(dp[0], dp[1]);
				break;
			case "L" :
				drawTarget.lineTo(dp[0], dp[1]);
				break;
			case "C" :
				drawTarget.curveTo(dp[0], dp[1], dp[2], dp[3]);
				break;
		}
	}
	// repeat til all paths have been read
	if (++iPath < nPathNodes) getShapes(iPath);
}
Тестируем изменения. Если видим на экране попугая, то всё хорошо. Если нет, а вполне возможно что в ходе объяснений я что-то пропустил или был неточен, то для такого случая я приаттачу необходимые файлы.

Что же нам позволило даже не вникая в суть кода добиться успеха? Методология. Мы следовали простым принципам и в каждый момент делали только то, что соответствовало нашей стратегии:

- мы портировали код в строгом порядке: вначале портировались классы не использовавшие других пользовательских классов, только затем классы, использовавшие уже портированные классы, до тех пор, пока таким образом не закончили последний.
- мы не изменяли код без крайней на то необходимости и оставили это на самый последний момент.
- мы тестировали код при первой возможности.

Чего мы избегали:
- мы не пытались улучшить код, добавить недостающую типизацию, или изменить логику кода.
Мы оставили это для следующих этапов: рефакторинга и оптимизации.
Вложения
Тип файла: zip SVGToFlash.zip (17.8 Кб, 435 просмотров)
__________________
http://realaxy.com


Последний раз редактировалось iNils; 20.12.2010 в 13:19.
Старый 11.03.2008, 18:39
Iv вне форума Посмотреть профиль Отправить личное сообщение для Iv Посетить домашнюю страницу Iv Найти все сообщения от Iv
  № 8  
Iv
 
Аватар для Iv

Регистрация: Apr 2001
Адрес: Moscow
Сообщений: 1,475
Cool Начинаем рефакторить

Итак, после успешного портирования мы переходим к следующему этапу - рефакторингу.

Вначале давайте определимся с тем, что такое рефакторинг, зачем он нужен, и затем перейдем к задачам, которые у нас стоят на этом этапе.

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

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

Обратите внимание на то, что здесь ни слова не говорится об увеличении производительности кода, поскольку этот процесс, как правило, затрагивает логику программы, что на этапе рефакторинга недопустимо.

Знающие люди могут возразить против самой постановки задачи: рефакторинг не один большой этап, а регулярно выполняемая процедура в процессе программирования.
Я, конечно в курсе, но первый рефакторинг после портирования - довольно цельный и объемный этап работ не сопоставимый с обычным рефакторингом, проводящимся в процессе написания программы. Именно поэтому мы уделяем ему такое внимание, что даже выделяем в отдельный этап.

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

Как уже было сказано выше, на этапе рефакторинга нас не интересует производительность приложения, но очень важны другие свойства кода. Этим требованиям более всего отвечает направление на возможность развития проекта в будущем вплоть до редактора svg файлов.

А самой первой задачей рефакторинга станет наведение элементарного порядка в коде, до такой степени, что FDT перестанет нам подсвечивать ошибки.
__________________
http://realaxy.com

Старый 11.03.2008, 19:53
Iv вне форума Посмотреть профиль Отправить личное сообщение для Iv Посетить домашнюю страницу Iv Найти все сообщения от Iv
  № 9  
Iv
 
Аватар для Iv

Регистрация: Apr 2001
Адрес: Moscow
Сообщений: 1,475
По умолчанию рефакторим String2

Первый класс, который мы поправим - String2. Он самый короткий, и не использует других наших классов. И для примера я поподробнее остановлюсь на самом процессе.

Подсвечиваются всего три ошибки: в методе shrinkSequencesOf не задана типизация локальных переменных. Зададим ее:
Код AS3:
var len:int = s.length;
var idx:int = 0;
var idx2:int = 0;
var rs:String = "";
Затем все объявления var заменим на const (пользуйтесь возможностью автоматического поиска и замены). Затем все переменные, которые подсветили ошибку присвоения, обратно заменим на var.

Займемся именованием. Для начала заменим имена аргументов функции. Думать тут особо не надо, поскольку автор позаботилась о комментариях: s заменяем на originalString, ch заменяем на characterToBeFound.

Затем, поскольку сокращений мы не любим, заменим:
len на length
idx на startIndex
idx2 на endIndex
rs на resultString

Также добавим фигурные скобки вложенному while.

Давайте сравним, что было и что стало:

Код AS3:
 // БЫЛО
public static function shrinkSequencesOf(s:String, ch:String):String {
	var len = s.length;
	var idx = 0;
	var idx2 = 0;
	var rs = "";
 
	while ((idx2 = s.indexOf(ch, idx) + 1) != 0) {
		// include string up to first character in sequence
		rs += s.substring(idx, idx2);
		idx = idx2;
 
		// remove all subsequent characters in sequence
		while ((s.charAt(idx) == ch) && (idx < len)) idx++;
	}
	return rs + s.substring(idx, len);	
}
 
// СТАЛО
public static function shrinkSequencesOf(originalString:String, characterToBeFound:String):String {
	const length:uint = originalString.length;
	var startIndex:int = 0;
	var endIndex:int = 0;
	var resultString:String = "";
 
	while ((endIndex = originalString.indexOf(characterToBeFound, startIndex) + 1) != 0) {
		// include string up to first character in sequence
		resultString += originalString.substring(startIndex, endIndex);
		startIndex = endIndex;
 
		// remove all subsequent characters in sequence
		while ((originalString.charAt(startIndex) == characterToBeFound) && (startIndex < length)) { 
			startIndex++;
		}
	}
	return resultString + originalString.substring(startIndex, length);	
}
Да, новый метод не так лаконичен. Он более объемен, но и более читабелен.
Обратите внимание на еще один положительный фактор: в процессе мы всё еще не изменяли логику программы, но уже начали более детально знакомиться с проектом.
К тому моменту, когда мы закончим рефакторинг мы будем довольно неплохо представлять что в проекте имеется, где находится и как примерно работает.
__________________
http://realaxy.com


Последний раз редактировалось iNils; 20.12.2010 в 13:19.
Старый 11.03.2008, 21:53
Iv вне форума Посмотреть профиль Отправить личное сообщение для Iv Посетить домашнюю страницу Iv Найти все сообщения от Iv
  № 10  
Iv
 
Аватар для Iv

Регистрация: Apr 2001
Адрес: Moscow
Сообщений: 1,475
По умолчанию рефакторинг класса PathToArray

Следующий класс для причесывания - PathToArray. Он хоть и дает большое количество ошибок, однако подавляющее большинство - по одинаковой причине, и их можно исправить без существенных усилий.

В методе extractCmds динамически создается объект, содержащий перечень значений стандартных цветов. Эти цвета неизменны, а объект может быть использован неоднократно. Это прекрасный повод сделать объект статической константой и инициализировать его в теле класса. Так и поступим.
Вырезаем из метода всю инициализацию объекта colors, до строчки yellowgreen : 0x9acd32 включительно и вставляем с тело класса непосредственно после объявления класса.
Затем изменяем объявления и переносим закрывающую скобку в конец присвоений значений цветам. Должно получиться так:

Код AS3:
private static const colors:Object = {
	colors.blue=0x0000ff;
	........
	colors.yellowgreen=0x9acd32;
}
Разумеется, это неверно, и мы поиском и заменой (но не используя replace all) вначале удаляем строку "colors.", затем заменяем "=" на ":" и, в конце ";" на ",".

В итоге должно получиться так:

Код AS3:
private static const colors:Object = {
	blue:0x0000ff,
	........
	yellowgreen:0x9acd32
}
Теперь, нас этот объект не очень интересует и, если нажать волшебное сочетание клавиш SHIFT+CTRL+F, то всё перечисление из столбца превратится в одну строку и не будет занимать три экрана.

Изучив текущее состояние увидим, что очень много ошибок дает нетипизированный доступ к атрибутам. Что-ж, создадим специальный метод доступа и заменим на него обращения к атрибутам.

Код AS3:
private function getAttribute(node:XMLNode, attributeName:String) : String {
	return node.attributes[attributeName];
}
Процесс может оказаться утомительным и подверженым ошибкам. Чтобы этого избежать изучаем обращения к объекту attributes и видим, что строка кода всегда выглядит как "node.attributes.". Это дает нам возможность применить автозамену:
заменяем "node.attributes." (с точкой на конце!) на "getAttribute(node, ", в результате чего редактор расцветет массой ошибок. Это очень хорошо. Кликая на красные точки справа от скроллера мы переходим от ошибки к ошибке и ставим закрывающую скобку сразу после первого слова, следующего за "node". Заодно берем это слово в кавычки, поскольку это имя атрибута.

В процессе мы обнаруживаем еще одну прелесть рефакторинга: мы обнаружили ошибку несоответствия типов в строке:
Код AS3:
hasRotate = getAttribute(node, "transform").indexOf("rotate");
Обратите внимание, что за внешне безобидным отсутствием типа пряталась куда более серьезная ошибка - несоответствие типа. Игнорирование малой ошибки может повлечь за собой большую.

При обнаружении ошибки нужно четко понимать, что процесс рефакторинга останавливается и начинается другой процесс - исправление ошибки логики.
Обнаружение ошибки - серьезное происшествие и очень хорошее: будучи скрытой мы могли голову сломать откуда она берется и найти только с большим трудом.

В данном случае это локальная ошибка, не влекущая за собой цепочку других. Но всё-таки рассмотрим ее отдельно.
__________________
http://realaxy.com


Последний раз редактировалось iNils; 20.12.2010 в 13:20.
Создать новую тему Закрытая тема Часовой пояс GMT +4, время: 06:38.
Быстрый переход
  « Предыдущая тема | Следующая тема »  
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 06:38.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.