Создание игр » Featured, Теория » Рефакторинг кода
Рефакторинг кода
Рефакторинг (Refactoring) кода это процесс изменения исходного кода программы, не затрагивающий её поведения и ставящий целью облегчить понимание её работы и/или упростить её дальнейшую поддержку. Обычно рефакторинг любой программы это внесение небольших изменений в её код, каждое из которых не меняет само поведение программы, но как-то упрощает и/или улучшает код. При этом очень важно, что бы рефакторинг выполнялся именно небольшими частями, т.к. когда программист меняет небольшую часть кода – ему значительно проще проследить за правильностью изменений и не наделать ошибок. Если же рефакторить сразу большие участки кода, то есть очень большая вероятность наделать ошибок, в результате которых программа может вообще перестать работать. Правда, то, что правки должны быть небольшими, вовсе не означает, что рефакторинг это лишь замена имён переменных или перемещение небольших участков кода из одного места программы в другое – рефакторинг позволяет полностью переработать всю программу, включая и логику её поведения, главное при этом – вносить изменения небольшими частями и тогда всё будет в порядке.
Цели рефакторинга
Наверное, Вы спросите меня, к чему в вообще это пишу? А к тому, что, если Вы внимательно смотрите исходники примеров исходных текстов к каждому уроку – Вы, наверное, заметили, что я часто меняю что-то в коде, иногда по мелочам, а иногда довольно заметно. Это потому что я сам применяю рефакторинг и хочу, что бы и у Вас это вошло в привычку.
Как я уже сказал – основная цель рефакторинга это сделать код проще и понятнее. Если после переработки код не стал лучше и понятнее – значит вы либо делали не рефакторинг, либо он не удался. При этом не путайте понятие рефакторинга с оптимизацией. В результате оптимизации код становится быстрее, но совсем не обязательно проще и понятнее, рефакторинг же служит именно для упрощения и улучшения читаемости кода.
Какой код надо рефакторить
Рефакторить можно и, часто, нужно, любой код – чаще всего надо просто полагаться на своё чутьё, если какой-то код кажется Вам не очень удачным или Вам кажется, что через неделю Вы уже забудете что делает тот или иной участок кода – скорее всего, этому коду требуется рефакторинг. Я попробую сформулировать основные правила, основываясь на которых, Вы можете понять, что ваш код требует переработки:
- Если в вашей программе есть дублирование кода, то почти наверняка требуется рефакторинг. Дублирующийся код в программе – основной источник ошибок. Если в вашей программе какое-то действие выполняется в нескольких разных местах, но одним и тем же кодом – просто вынесите этот код в отдельную функцию и вызывайте её. Иначе высока вероятность того, что однажды Вы отредактируете исходник в одном месте, но забудете исправить аналогичный код в другом и возникнут ошибки.
- В вашей программе есть очень длинные методы/функции. Как правило, человек не может полностью воспринимать и оценивать правильность кода, если этот код занимает больше 2-3 десятков строк. Такие методы и функции следует разделять на несколько более мелких и делать одну общую функцию, которая будет последовательно вызывать эти методы. Никогда не пытайтесь сократить длину кода записывая по несколько операторов в одной строке!!! Это один из самых худших вариантов организации программы и я вам даю 100% гарантию, что такой код в итоге прведёт к ошибкам!
- Длинный список параметров функции/метода/конструктора. Большое количество параметров обычно не только усложняет понимание того, что, что делает этот метод или функция, но и усложняет понимание кода, использующего эти функции. Если Вам реально нужно, что бы функция принимала очень много параметров – просто вынесите эти параметры в отдельную структуру (либо класс), дав этой структуре разумное и понятное имя, и передавайте функции ссылку (либо указатель) на объект этой структуры или класса.
- Большие классы так же требуют рефакторинга. Если у Вас в программе есть один или несколько больших (больше пары-тройки десятков строк кода) классов, Вам следует немедленно разделить их на более мелкие и включить объекты этих классов в один общий класс. Причина этого та же самая, что и в предыдущем пункте.
- Слишком много временных переменных так же являются признаком плохого кода, который требует рефакторинга. Как правило, много временных переменных встречаются в излишне “раздудых” функциях – когда Вы сделаете рефакторинг таких функции, скорее всего и количество временных переменных в каждой из них станет меньше и код станет значительно понятнее и удобнее
- Много “беспорядочно” хранящихся данных, которые связан логически и их можно было бы объединить в структуру, либо класс. Логически связанные данные всегда стоит хранить в структурах/классах, даже если это всего 2-3 переменных – хуже от этого никому не станет, а вот код станет значительно понятнее.
- Если объекты одного класса слишком много/часто обращаются к (ссылаются на) данным другого объекта – Вам следует пересмотреть функционал объектов. Возможно, Вы приняли неверное архитектурное решение и его надо поменять как можно раньше, пока эта ошибка не расползлась по всему коду.
- Старайтесь не хранить слишком много глобальных переменных. Если же Вам и в самом деле нужно именно столько и никак не меньше глобальных объектов – попробуйте хотя бы сгруппировать их в структуры/классы, либо хотя бы просто вынесите их в отдельный namespace – тогда шанс того, что вы случайно используете какую-то переменную по ошибке станет значительно ниже.
Когда применять рефакторинг?
На этот вопрос есть очень простой ответ: всегда. Занимайтесь рефакторингом при малейшей возможности – рефакторинг улучшает ваш код и, потратив на него сегодня 5 минут, Вы завтра сэкономите на поиске ошибок час. Самый простой метод применения рефакторинга такой: каждый раз, когда вы что-то меняете в программе – добавляете новую функцию, класс, просто объявляете переменную, или Вам надо поменять пару строк в какой-то функции – посмотрите на соседний код, находящийся выше и ниже того участка, с которым Вы работаете сейчас. Проверьте, может быть, в этот код можно внести какие-то изменения, что бы он стал ещё более понятным и/или простым, может быть Вы найдёте в нём какие-то логические ошибки или Вам в голову придёт при каком сочетании параметров код может дать сбой. Если Вы увидели что-то подобное, то займитесь рефакторингом. Но не следует скакать по коду из конца в конец – если Вы пришли что-то добавить в код или поменять – сначала сделайте то, зачем Вы пришли, а потом уже занимайтесь рефакторингом. Иначе в итоге Вы можете вообще забыть, зачем вы открыли исходник.
Когда заканчивать рефакторинг?
Постарайтесь не заболеть “синдромом рефакторинга”. Если Вы сделали код, посмотрели вокруг и всё Вас устраивает – не надо рыскать по коду в поисках “чего бы тут ещё зарефакторить”. Если Вам нечем заняться – сходите в спортзал, покатайтесь на машине, сходие в клуб или хотя бы просто попейте пивка. Делать рефакторинг только потому что Вам лень делать что-либо ещё – это очень плохая привычка.
Рефакторинг кода
Термин рефакторинг означает изменение исходного кода программы без изменения его внешнего поведения. Иногда под рефакторингом ошибочно подразумевают изменение кода с заранее оговоренными правилами отступа, перевода строк, внесения комментариев и прочими визуально значимыми изменениями, которые никак не отражаются на процессе компиляции, с целью обеспечения лучшей читаемости кода – это не рефакторинг, это просто подгонка кода под коде-стайл проекта.
Рефакторинг изначально не предназначен для исправления ошибок и/или добавления новой функциональности – он вообще не должен менять поведение вашей программы и именно это помогает избежать ошибок и, в будущем, облегчить добавление новой функциональности в программу. Рефаткоринг выполняется только для улучшения понятности кода и/или изменения его структуры, для удаления “мёртвого” (старого, уже не нужного, оставленного “на всякий случай”) кода – для того, чтобы в будущем код было легче поддерживать и развивать ваш код. Например, добавление в программу нового поведения может оказаться сложным с существующей структурой — в этом случае Вы можете сначала выполнить необходимый рефакторинг, а уже затем добавить новую функциональность.
Так же это может быть перемещение дынных из одного класса в другой, вынесение фрагмента кода из метода и превращение его в самостоятельный метод или даже перемещение кода по иерархии классов. Каждый отдельный шаг может показаться элементарным, но совокупный эффект таких малых изменений в состоянии радикально улучшить проект или даже предотвратить распад плохо спроектированной программы.
В экстремальном программировании и других подобных гибких методологиях, рефакторинг является неотъемлемой частью цикла разработки программы: разработчики то создают новые тесты и функциональность, то выполняют рефакторинг кода для улучшения его логичности и прозрачности, и снова циклически повторяют – новые тесты/код, рефакторинг, новые тесты/код, рефакторинг и т.д. Автоматическое юнит-тестирование позволяет программистам убедиться, что рефакторинг не разрушил существующую функциональность, т.е. что он был проведён правильно и без ошибок.
Помощь в рефакторинге
Существенную помощь в рефакторинге могут оказать IDE, плагины к IDE, а так же системы контроля версий. IDE и плагины к ней, например, могут подсвечивать разработчику те строчки кода, которые он изменил с момента последней записи исходного кода на диск. Таким образом, программисту становится визуально понятно, над каким кодом он уже поработал, а какой код пока не трогал – это позволяет, при проверке “в голове” правильности написания кода, сосредоточиться на более узком фрагменте исходного кода, а не на всей программе – если даже открытый файл в длину имеет 1000 и более строк, программист с помощью IDE легко найдёт те несколько строк программы, которые он только что поменял, даже если они находятся в разных концах исходного текста.
Системы контроля (а точнее оболочки для них) версий при этом позволяют программисту, помимо всего прочего, сравнивать его текущий код с предыдущими версиями этого же кода. Чаще всего они даже могут визуально оформить различия между текущим и прошлыми исходниками – например, подсветить новый код зелёным, удалённый код нарисовать красный и/или зачёркнутым, посмотреть всю историю развития кода, прочитать комментарии, которые делались при заливке апдейтов исходников в систему контроля версий и многое другое. В общем, эти системы очень удобная штука и они могут помочь в том числе и при проведении рефакторинга.
Вместо заключения или как научиться рефакторингу
Если честно, я не знаю как научиться рефакторингу. Могут лишь посоветовать Вам делать так же, как, в своё время делал я – просто акцентируйте внимание на рефакторинге, не забывайте о нём. Старайтесь всегда помнить о том, что ваша цель не только написать новый код, но и улучшить старый и задача улучшения при этом отнюдь не менее (а может даже и более) важная, чем создание нового кода. После пары-тройки недель ежедневных тренировок привычка рефакторить код станет вашей неотъемлемой частью и, после этого, качеству вашего кода позавидуют очень многие программисты, которые до сих пор не применяют рефаткоринг.
Возможно, Вам первое время будет казаться, что рефакторинг занимает слишком уж много времени и сил, и что именно он не позволяет Вам найти время на дальнейшее развитие вашей программы. Однако, это мнение ошибочно – на самом деле, рефакторинг наоборот, ускоряет развитие программы, т.к. со временем Вы всё больше и больше экономите времени на том, что отрефакторенный код будет для Вас же самих намного понятнее, удобнее, он будет содержать в разы меньше ошибок и, в итоге, на одних только исчезнувших ошибках или недочётках кода (которые могли бы потом привести к ошибкам), Вы будете экономить огромное количество времени. Кстати, этот факт подтверждён исследованиями таких больших и уважаемых компаний, как IBM, HP, Microsoft, Sony и многих других.
Очень нужная статья, спасибо!
Согласен!
ArchiDevil, Antony, спасибо! Надеюсь, она окажется и практически полезной…
На работе близится дедлайн, а я всё заглядываю, когда же новая статься появиться:) Скучаю по новым урокам)
Antony, эти дни был немного занят. Новые статьи появятся либо завтра вечером, либо послезавтра
Да уже, как не терпеливые дети прям:)
Можно ещё вопрос: я нахожусь в самом зачаточном состоянии освоения Direct3D, не вредно ли будет почитывать статейки и по OpenGL (причём о старом – 2)? Или это как пытаться усидеть на двух стульях? Посоветуйте, пожалуйста.
Вреда от этого точно не будет. Главное, что бы не возникло путанницы – она, как раз, возникнуть может. DirectX и OpenGL вобщем-то вещи достаточно (и даже более чем) похожие, но отличия в деталях резализации – именно из-за этого может возникнуть небольшая путаница но, наверное, со временем она пройдёт.
Я правда, если честно, не совсем понимаю, зачем начинать изучение сразу с DirectX и OGL одновременно – мне кажется, это очень неудобно. Значительно проще сначала разобраться с одним API, а второй потом можно детально изучить за недельку-две, основываясь на знаниях о другом АПИ – это будет и проще, и быстрее, и логичнее. ИМХО
Большое спасибо – приму в сведению!
Когда статьи появятся?
“либо завтра вечером, либо послезавтра”
3d max вчера “помер”, сидел до 5 утра, но так и не решил проблему. если сегодня разберусь – сегодня будет урок.