![]() |
Определение следующей цели
Давайте определимся, с тем, чего мы будем добиваться на этом этапе и критерях его окончания.
Тот факт, что редактор не показывает нам ошибки нетипизированного доступа вовсе не означает, что в коде их нет. Неявный нетипизированный доступ - это применение наборов переменных представляющих одну сущность вместо применения объекта такого типа, который отражает сущность. К примеру, точку на плоскости в координатах x=10, y=15 можно представить разными способами: Код AS3:
Пройдемся по классам и отметим для себя такие случаи: Класс SVGDisplayInFlash метод getShapes: - массивы хранят данные, а не объекты, представляющие сущности. Класс Math2 метод getQuadBez_RP: - в аргументах передаются точки вместо кривой Безье 3го порядка; - внутри метода имеются обращения к массивам данных вместо обращений к сущностям. метод intersect2Lines: - в аргументах передаются точки вместо отрезков; метод midpoint: - в аргументах передаются координаты вместо отрезка; метод bezierSplit: - в аргументах передаются координаты вместо кривой Безье 3го порядка; - возвращаемое значение содержит массивы данных вместо кривых Безье 3го порядка. Класс PathToArray метод makeDrawCmds: - в аргументах и в теле метода широко используются массивы данных вместо классов, представляющих сущности. Класс String2 случаев скрытого нетипизированного доступа нет. Итак, наша задача на следующем шаге - избавиться от случаев скрытого нетипизированного доступа. |
Следуя нашим правилам, начинаем с методов, правка которых вызовет наименьшее влияние на проект.
Этип критериям лучше всего подходит приватный метод midpoint: у него правильно типизированное возвращаемое значение, а поскольку он приватный, то аргументы для него будут изготовлены в этом же классе. Методология та-же, что и применятась ранее: вызываем ошибку и исправляем ее. Продублируем и закомментируем строку объявления метода. На память. Заменим все аргументы метода на один (line:LineSVG). Разумеется, такого типа не существует и, поэтому редактор подсветит ошибки. Выделяем LineSVG и комбинацией CTRL+1 вызываем quick fix, соглашаемся на предложение создать класс LineSVG. Сохраняем его, возвращаемся. Честно говоря, глядя на код хочется пойти по более короткому, хотя и теоретически опасному пути: немедленно перенести метод midpoint в класс LineSVG, поскольку он явно завистлив к данным этого класса и не использует данных текущего класса. Ну, что-ж, сократим путь. Переносим вместе с комментариями. Теперь, собственно, нужно определиться с тем, что будет из себя представлять этот класс и как будет создаваться. Задаем конструктор, метод инициализации экземпляра класса и get set методы доступа к стартовой и конечной точкам отрезка. После этого делаем метод midpoint публичным и не статическим и реализуем аналогичное поведение, но с использованием стандартных методов. Заодно исправим комментарии к методу. В итоге получаем такой класс: Код AS3:
Теперь можно приступить к исправлению образовавшихся ошибок в методе bezierSplit. |
Исправим все строки, в которых применяется midpoint. Поступим следующим образом:
- продублируем и закомментируем верхнюю; - удалим ошибочный вызов метода; - вместо него впишем создание объекта LineSVG с пустыми new Point(); - из верхней строки скопируем пары координат и соответственно вставим в new Point() - добавим вызов метода midpoint() Результат должен получиться таким: Код AS3:
В итоге получаем отсутствие ошибок, а это значит, что мы можем протестировать плоды наших усилий. Ошибок нет, переходим к типизации возвращаемого значения и аргументов. |
создаем класс CubicBezierSVG
В качестве аргументов методу bezierSplit передается четыре пары координат x и y, описывающих одну сущность - кривую Безье третьего порядка.
Чтобы описать эту сущность, создаем класс, в котором описываем базовые свойства кривой: Код AS3:
Для этого просто скопируем метод в класс, продублируем и закомментируем верхний - на память. Переименовываем метод в split, и делаем его публичным и не статическим. Удаляем аргументы. Редактор расцвел массой ошибок. Исправим их, заменив создание объектов Point из координат на соответствующие объекты Point текущего класса. Для этого подглядываем в аргументы закомментированного класса: там точки идут по парам представляя контрольные точки кривой Безье. Точки заменяем в том порядке, в котором они идут в аргументах закомментированного метода bezierSplit. В итоге избавляемся от всех ошибок и видим, что можем удалить объявление точек p1 и p2 и заменить их непосредственно на startPoint и endPoint. Для этого копируем startPoint в буфер обмена, удаляем строку инициализации p1, и там, где подсветилась ошибка вставляем из буфера обмена startPoint. Затем делаем то-же самое с p2. Заменяем вложенные массивы на создание объектов CubicBezierSVG. После чего можем удалить закомментированный метод. Затем мы можем заменить все new Point(...) на ранее полученные точки. Полученный результат должен быть таким: Код AS3:
Код AS3:
|
Тестирование нового метода
Прежде чем заменять вызовы старого метода на новый, мы обязательно(!!!) должны протестировать наш новый метод split.
Это ключевой и, как вы убедитесь, совсем не лишний шаг в выбранном способе рефакторинга. Создавая новый метод мы имеем право делать всё что нам заблагорассудится с новым кодом, но старый код не имеем права трогать. И, когда новый метод готов, мы тестируем его. Тестирование нового метода обязательно производится заменой всей логики старого метода на вызов нового метода. Продублируем метод Math2.bezierSplit и закомментируем верхний, чтобы было легко откатиться в случае ошибки. После чего удалим всю старую логику и заменим на новую: Код AS3:
|
Задержка по пути
Оказывается рановато заменять старые вызовы на новые.
Взглянув на метод Math2.getQuadBez_RP видим, что предварительно стоит заняться удалением локальных переменных p1, c1, c2, p2, которые дублируют точки, передаваемые в аргументах. Для этого комментируем строку инициализации переменной и заменяем подсвечивающиеся ошибки на соответствующий аргумент. После чего удаляем ненужные закомментированные строки и получаем в итоге вот такой метод: Код AS3:
|
И вот, наконец можем заменить вызов метода Math2.bezierSplit на метод split класса CubicBezierSVG.
Дублируем весь код, находящийся внутри блока if (до строки с else) и закомментируем верхний. Чтобы использовать метод split требуется экземпляр объекта CubicBezierSVG. Создаем его, заменяем метод со старого на новый и задаем новый тип переменным bezier0 и bezier1: Код AS3:
Переименуем переменную bezier0 на firstHalf. Редактор кода подсвечивает ошибки и мы идем по ним, заменяя имя и обращение к точке, к которой осуществляется доступ. Проделываем то-же самое с переменной bezier1, заменив ее имя на secondHalf. Получаем в итоге: Код AS3:
|
Рефакторинг intersect2Lines
Я напомню цель текущего шага: удаление случаев скрытого нетипизированного доступа.
Следующей мишенью наших действий станет метод Math2.intersect2Lines. Этот случай очень похож на предыдущий. Но, как я и обещал, чтобы разнообразить наш инструментарий способ рефакторинга будет выбран иной. Вырежем и вставим метод в класс LineSVG, сделаем его публичным. Сохраним оба документа (CTRL+SHIFT+S). Используя панель Problems перейдем на строку с ошибкой и добавим "LineSVG." перед вызовом метода. Поскольку мы намерены избавиться от скрытого нетипизированного доступа в аргументах метода, для начала снизим зависимость кода метода от аргументов. В самом начале метода объявим два объекта first и second типа LineSVG и создадим их используя аргументы метода. Везде далее в коде заменим использование аргументов на доступ через объекты LineSVG. Теперь аргументы используются только для создания объектов LineSVG, чего мы и добивались. Сделаем метод не статическим: удаляем static из объявления метода. Сохраняем документ, переходим на ошибку используя панель Problems. Создаем экземпляр LineSVG и от его имени вызываем метод intersect2Lines: Код AS3:
Заменим аргументы на один: second : LineSVG и удалим в теле метода объявление second. Перейдем на ошибки в методе getQuadBez_RP. Скопируем строку объявления startArm, переименуем переменную в endArm и скопируем параметры из вызова метода intersect2Lines. После этого параметры заменим на endArm. В результате наших действий имя метода перестало отражать его суть. Переименуем в getLineIntersection и исправим вызов метода. В итоге, измененная чать метода Math2.getQuadBez_RP будет выглядеть так: Код AS3:
Удалим объявления временных переменных ссылающихся на существующие значения.Подробно процесс на примере: - закомментируем строку var x1 : Number = start.x; - скопируем start.x в буфер обмена; - выделим первую ошибку: обращение к x1; - CTRL+F, ставим фокус в поле Replace With, CTRL+V, в нем должна появиться строка "start.x"; - отмечаем чек боксы Case Sensitive и Whole Word - жмем Replace All Впрочем, вам возможно будет удобнее заменить выделением и вставкой. Далее также поступаем с переменными y1, x4, y4 и получаем такой код: Код AS3:
Заменяем dx1 на currentDistanceX, а dx2 на targetDistanceX, исправляя подсвечивающиеся ошибки сразу после каждого переименования. Пробуем поставить const вместо var. Ошибок нет, так и оставим. Идем дальше вниз по коду. Добавляем фигурные скобки блоку if. Думайте что хотите, но я уверен, что if без фигурных скобок снижает читабельность кода, а пользы никакой. В вычислении переменных m1 и m2 видим, что используются вычисления, аналогичные currentDistanceX и targetDistanceX. Объявим аналогичные локальные константы currentDistanceY и targetDistanceY и присвоим им соответствующие значения скопировав из вычислений. Затем заменим вычисления на эти константы: Код AS3:
Код AS3:
В итоге имеем вот такой метод: Код AS3:
Потому, что программировать не надо бояться, программировать радоваться надо. А если серьезно, то обратите внимание на то, что мы уже довольно давно работаем с кодом, но до сих пор так и не вникали в суть его логики. Более того, если вы обратили внимание, в процессе рефакторинга код понемногу сам нам рассказывает о себе. |
рефакторим getQuadBez_RP
Вернемся в класс Math2.
Здесь мы видим сиротливо приютившийся метод getQuadBez_RP и мы понимаем, что из-за его завистливости к данным других объектов и вселенского одиночества в классе, он обречен на перемещение, а класс будет удален. Поскольку в первую очередь мы намерены избавить метод от скрытого нетипизированного доступа в аргументах, то видим, что заменяться они будут на объект CubicBezierSVG. Туда и будем перемещать. Правда, мы видим, что метод также использует класс LineSVG и, вполне возможно, что он будет завистлив к данным этого класса. Но это не проблема. Мы впоследствии сможем переместить, если потребуется. Итак, приступим. Перемещаем метод вместе с комментариями в класс CubicBezierSVG, сохраняем все документы и идем исправлять образовавшиеся ошибки в окне Problems. Не буду расписывать - вы и сами знаете что делать. Тестируем. Затем удаляем класс Math2, при этом мысленно благодарим его за труд, который он делал в течение своей короткой, но очень яркой и полезной жизни. Возвращаемся к методу getQuadBez_RP. Как и в предыдущем случае, нам вначале потребуется избавиться от зависимости кода от аргументов метода, которые мы будем заменять на объект CubicBezierSVG. Для этого вначале метода создаем экземпляр класса CubicBezierSVG: Код AS3:
Чтобы гарантировать себя от невнимательности, действуем по простой схеме: - переименовываем аргумент; - новое имя используем только в инициализации объекта source; - остальные обращения заменяем на доступ через объект source. Вот что в итоге получилось: Код AS3:
Удаляем ключевое слово static, сохраняемся и идем исправлять ошибки. Принцип, как всегда прост: - вначале метода объявляем переменную: Код AS3:
Код AS3:
- заменяем обращение к статическому методу на обращение через экземпляр source. - переходим к следующей ошибке, пока они не иссякнут. - тестируем проект. - не забываем радоваться тому, как у нас ловко всё получается. |
А теперь можно заняться удалением теперь уже ненужных аргументов.
Заменим создание объекта source на присвоение ему this: Код AS3:
До тех пор, пока использовались аргументы, в методе создавались новые объекты CubicBezierSVG. А как только перешли на использование this наша невнимательность выползла наружу: мы не добавили объекты, от имени которых рекурсивно вызывается метод getQuadBez_RP. Исправим. Для начала откатимся назад до рабочего состояния: Код AS3:
Протеституем, убедимся, что всё работает. Вот участок кода, который требует вмешательства: Код AS3:
В этот момент мы должны остановиться и сказать себе: это не рефакторинг. Это действия по изменению логики приложения. К таким действиям мы должны подходить с совсем другими правилами. |
| Часовой пояс GMT +4, время: 10:22. |
Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.