ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 06.11.2023
Просмотров: 895
Скачиваний: 6
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
360 следования, который включает в себя: выделение класса, перемещение метода, подъем метода и подъем поля.
Когда начинать рефакторинг? Рефакторинг обычно применяется при добавлении новой функции. Причина, по которой стоит проводить рефакторинг, добавляя новую функцию, это возможно несовместимый или неясный дизайн кода для добавления новых функций. Рефакторинг следует применять, если требуется исправить ошибку. При исправлении ошибок польза рефакторинга в том, что код становиться более понят- ным. Если получается сообщение об ошибке, то это признак необходи- мости рефакторинга, потому что код не был достаточно ясным, и разра- ботчик не смог увидеть ошибку. Целесообразно применять рефакторинг при разборе кода. Разбор кода – это хорошая практика, когда в команде разработчики проверяют код друг друга.
Как начать рефакторинг? Нужно четко убедиться, над какой ча- стью кода будет производиться рефакторинг. Нужно точно знать, какую часть кода могут затронуть изменения. Определить методы, с помощью которых будет производиться рефакторинг. Выписать эти методы и для каждого составить последовательность шагов, которые будет необхо- димо выполнить. Проделать эту работу один раз для каждого метода, чтоб быть уверенным, что ничего не пропущено. Большинство методов рефакторинга уже имеют порядок действий и описание применения, ознакомьтесь с этими методами и применяйте их.
Как не поломать рабочий код? Постройте набор тестов для перера- батываемой части кода. Тесты важны, так как даже при последователь- ном проведении рефакторинга можно допустить ошибки, тесты помогут исключить возможные ошибки. Проводя рефакторинг, можно полагать- ся на тесты. Старайтесь покрыть тестами достаточную часть кода для работы функции, тесты должны быть как чистые, проверяющие вычис- ления правильных данных, так и грязные, посылающие в тест недопус- тимые, не ожидаемые данные.
Когда рефакторинг не нужен? Иногда рефакторинг не нужен. На- пример, когда надо переписать программу с нуля. Иногда имеющийся код настолько запутан, что подвергнуть его рефакторингу, конечно, можно, но проще начать все с самого начала. Явный признак необходи- мости переписать код – это его неработоспособность. Это обнаружива- ется при его тестировании, когда ошибок так много, что сделать код устойчивым не удается. Другой случай, когда следует воздержаться от рефакторинга, это близость даты завершения проекта. Однако прибли- жение срока окончания работ – единственный случай, когда можно от- ложить рефакторинг, ссылаясь на недостаток времени.
Каталог методов рефакторинга и примеры рефакторинга. Большой каталог методов рефакторинга можно найти на refactoring.com вместо примеров кода, тут применяются примеры на языке UML. Также, хоро- ший каталог методов рефакторинга можно найти на wikipeadia, каждый метод снабжен примером на C#. Применение методов рефакторинга требует хорошего знания ООП, умения писать тесты, быть терпеливым,
361 делая рефакторинг небольшими шагами, проверять каждый шаг и по- стоянно учиться.
Каждый программист должен хорошо владеть таким инструментом как рефакторинг. Хорошее знание рефакторинга поможет писать код не только для машин, но и для людей. Такой код легкий в понимании и сопровождении, такой код написан для людей, а не для машин, рефак- торинг – это одна из ключевых ежедневных обязанностей программи- ста.
Автор статьи [6] дает несколько советов для проведения рефакто- ринга:
1. Всегда выполняйте рефакторинг короткими шагами с перерывом на перекомпиляцию и запуском тестов. Чем меньше ваши шаги, тем лучше вы локализуете потенциальные ошибки и тем быстрее вы их уст- раните. То, что ошибки будут, можно не сомневаться.
2. Проводите рефакторинг снизу вверх, особенно, если у вас длинная и запутанная цепочка наследования классов. Старайтесь всегда сначала производить изменения в потомственных классах, прежде чем присту- пать к базовым классам.
3. Вы должны знать основные методы рефакторинга, для этого сове- тую вам купить книгу Мартина Фаулера – “Рефакторинг”.
4. У вас всегда должна быть цель, с которой вы производите рефак- торинг, не делайте его там, где он не нужен или только, если это не пер- воочередная задача. Чем лучше вы понимаете, зачем вы это делаете, тем качественнее будет результат.
5. Не увлекайтесь рефакторингом (рефакторинг – не панацея!) [21], рефакторинг не добавляет функционала в программу, поэтому и каких либо видимых результатов вы также не получите. Делайте перерывы для того, чтоб сделать, что то, что можно увидеть и оценить. Тогда ваш руководитель будет вами доволен.
6. Любой вид рефакторинга можно сделать за 5, 20 минут, максимум за один час. Но в основном рефакторинг является комплексной задачей, которая может выполняться в течение недель или месяцев над дейст- вующим проектом. Идея в том, что двигаться нужно постепенно и не- большими шагами, и возможно уделяя этому не больше одного часа в день. Это хороший метод рефакторинга, потому как не занимает много времени и убедить начальство в необходимости будет намного проще.
7. В долгосрочной перспективе у вас будет красивый и легко сопро- вождаемый код. Код который написан для людей, а не для машин. Код, которым вы можете гордиться и показывать в пример. Код, который работает, так как вы этого хотите, и все это за невысокую цену рефакто- ринга.
1 ... 29 30 31 32 33 34 35 36 37
8.2. Рефакторинг, проектирование и
производительность программ
В своей монографии [32] М. Фаулер отмечает, что рефакторинг иг- рает особую роль в качестве дополнения к проектированию. Большин-
362 ство начинающих программистов (в том числе и автор этой монографии в свое время) пишут программу и доводят ее до конца. Со временем становится ясно, что если заранее подумать об архитектуре программы, то можно избежать последующей дорогостоящей переработки. Поэтому программисты привыкают к этому стилю предварительного проектиро- вания. Многие считают, что проектирование важнее всего, а програм- мирование представляет собой механический процесс. Аналогией про- екта служит технический чертеж, а аналогией кода – изготовление узла.
Но программа весьма отличается от физического устройства. Это более гибкий объект. Программа значительно более податлива и цели- ком связана с обдумыванием. Существует утверждение, что рефакто- ринг может быть альтернативой предварительному проектированию. В крайнем сценарии проектирование вообще отсутствует. Первое реше- ние, пришедшее в голову, воплощается в коде, доводится до рабочего состояния, а потом обретает требуемую форму с помощью рефакторин- га. Такой подход фактически может действовать. Действительно есть программисты, которые так работают и получают в итоге систему с очень хорошей архитектурой.
Тех, кто поддерживает экстремальное программирование, часто изо- бражают пропагандистами такого подхода. Подход, ограничивающийся только рефакторингом, применим, но не является самым эффективным.
Даже «экстремальные» программисты сначала разрабатывают некую архитектуру будущей системы. Они пробуют разные идеи с помощью
CRC-карт или чего-либо подобного [7], пока не получат внушающего доверия первоначального решения. Только после этого приступают к кодированию, а затем к рефакторингу. Смысл в том, что при использо- вании рефакторинга изменяется роль предварительного проектирова- ния. Если не рассчитывать на рефакторинг, то ощущается необходи- мость как можно лучше провести предварительное проектирование.
Возникает чувство, что любые изменения проекта в будущем, если они потребуются, окажутся слишком дорогостоящими. Поэтому в пред- варительное проектирование вкладывается больше времени и усилий – во избежание таких изменений впоследствии. С применением рефакто- ринга акценты смещаются. Предварительное проектирование сохраня- ется, но теперь оно не имеет целью найти единственно правильное ре- шение. Все, что от него требуется, – это найти приемлемое решение. По мере реализации решения, с углублением понимания задачи становится ясно, что наилучшее решение отличается от того, которое было принято первоначально. Но в этом нет ничего страшного, если в процессе участ- вует рефакторинг, потому что модификация не обходится слишком до- рого.
Важным следствием такого смещения акцентов является большее стремление к простоте проекта. До введения рефакторинга в свою рабо- ту, как отмечает автор монографии [32], он всегда искал гибкие реше- ния. Для каждого технического требования он рассматривал возможно- сти его изменения в течение срока жизни системы. Поскольку измене- ния в проекте были дорогостоящими, он старался создать проект, спо-
363 собный выдержать изменения, которые можно было предвидеть. Недос- таток гибких решений в том, что за гибкость приходится платить. Гиб- кие решения сложнее обычных. Создаваемые по ним программы в це- лом труднее сопровождать, хотя их легче перерабатывать в том направ- лении, которое предполагалось изначально.
И даже простые решения не избавляют от необходимости разбирать- ся, как модифицировать проект. Для одной-двух функций это сделать не очень трудно, но изменения происходят по всей системе. Если преду- сматривать гибкость во всех этих местах, то вся система становится значительно сложнее и дороже в сопровождении. Весьма разочаровыва- ет, конечно, то, что вся эта гибкость и не нужна. Потребуется лишь ка- кая-то часть ее, но невозможно заранее сказать какая. Чтобы достичь гибкости, приходится вводить ее гораздо больше, чем требуется в дей- ствительности.
Рефакторинг предоставляет другой подход к рискам модификации.
Возможные изменения все равно надо пытаться предвидеть, как и рас- сматривать гибкие решения. Но вместо реализации этих гибких реше- ний следует задаться вопросом: «Насколько сложно будет с помощью рефакторинга преобразовать обычное решение в гибкое?» Если, как чаще всего случается, ответ будет «весьма несложно», то надо просто реализовать обычное решение. Рефакторинг позволяет создавать более простые проекты, не жертвуя гибкостью, благодаря чему процесс про- ектирования становится более легким и менее напряженным. Научив- шись в целом распознавать то, что легко поддается рефакторингу, о гибкости решений даже перестаешь задумываться. Появляется уверен- ность в возможности применения рефакторинга, когда это понадобится.
Создаются самые простые решения, которые могут работать, а гибкие и сложные решения по большей части не потребуются.
С рефакторингом обычно связан вопрос о его влиянии на производи- тельность программы. С целью облегчения понимания работы програм- мы часто осуществляется модификация, приводящая к замедлению вы- полнения программы. Это важный момент. Многие разработчики про- граммных систем не пренебрегают производительностью в пользу чис- тоты проекта или в надежде на рост мощности аппаратной части. Про- граммное обеспечение часто отвергалось как слишком медленное, а бо- лее быстрые машины устанавливают свои правила игры. Рефакторинг, несомненно, заставляет программу выполняться медленнее, но при этом делает ее более податливой для настройки производительности.
Секрет создания быстрых программ, если только они не предназна- чены для работы в жестком режиме реального времени, состоит в том, чтобы сначала написать программу, которую можно настраивать, а за- тем настроить ее так, чтобы достичь приемлемой скорости. М. Фаулер отмечает три подхода к написанию быстрых программ. Наиболее труд- ный из них связан с ресурсами времени и часто применяется в системах с жесткими требованиями к выполнению в режиме реального времени.
В этой ситуации при декомпозиции проекта каждому компоненту выде- ляется бюджет ресурсов (по времени и памяти). Компонент не должен
364 выйти за рамки своего бюджета, хотя разрешен механизм обмена вре- менными ресурсами. Такой механизм жестко сосредоточен на соблюде- нии времени выполнения. Это важно в таких системах, как, например, кардиостимуляторы, в которых данные, полученные с опозданием, все- гда ошибочны. Данная технология избыточна в системах другого типа, например в корпоративных информационных системах.
Второй подход предполагает постоянное внимание. В этом случае каждый программист в любой момент времени делает все от него зави- сящее, чтобы поддерживать высокую производительность программы.
Это распространенный и интуитивно привлекательный подход, однако он не так хорош на деле. Модификация, повышающая производитель- ность, обычно затрудняет работу с программой. Это замедляет создание программы. На это можно было бы пойти, если бы в результате получа- лось более быстрое программное обеспечение, но обычно этого не про- исходит. Повышающие скорость усовершенствования разбросаны по всей программе, и каждое из них касается только узкой функции, вы- полняемой программой.
С производительностью связано то интересное обстоятельство, что при анализе большинства программ обнаруживается, что большая часть времени расходуется небольшой частью кода (известное правило 80/20
– на 20% кода затрачивается 80% времени работы программы). Если в равной мере оптимизировать весь код, то окажется, что 90% оптимиза- ции произведено впустую, потому что оптимизировался код, который выполняется не слишком часто. Время, ушедшее на ускорение про- граммы, и время, потерянное из-за ее непонятности – все это израсходо- вано напрасно [35].
Третий подход к повышению производительности программы осно- ван как раз на этой статистике. Он предполагает создание программы с достаточным разложением ее на компоненты без оглядки на достигае- мую производительность вплоть до этапа оптимизации производитель- ности, который обычно наступает на довольно поздней стадии разра- ботки и на котором осуществляется особая процедура настройки про- граммы. Начинается все с запуска программы под профайлером, кон- тролирующим программу и сообщающим, где расходуются время и па- мять.
Благодаря этому можно обнаружить тот небольшой участок про- граммы, в котором находятся узкие места производительности. На этих узких местах сосредоточиваются усилия, и осуществляется та же самая оптимизация, которая была бы применена при подходе с постоянным вниманием. Но благодаря тому, что внимание сосредоточено на выяв- ленных узких местах, удается достичь больших результатов при значи- тельно меньших затратах труда. Но даже в этой ситуации необходима бдительность. Как и при проведении рефакторинга, изменения следует вносить небольшими порциями, каждый раз компилируя, тестируя и запуская профайлер. Если производительность не увеличилась, измене- ниям дается обратный ход. Процесс поиска и ликвидации узких мест