Умение разбираться в коде Чужих или как правильно делать рефакторинг

visibility 386
26 Сен 2020г. в 08:09

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

Как вы считаете, что объединяет все программы в мире, что у них есть общего? Если отбросить такие очевидные вещи, что они написаны людьми на каком-либо языке программирования и состоят из символов, используемых в этом языке, то останется еще одно важное свойство. Что, кроме языка, отличает текст программы от текста книги? Да, книга нужна для того, чтобы ее читать, а не выполнять, но есть еще одно важное отличие. Любая программа, чтобы продолжать существование, вынуждена изменяться! И касается это абсолютно всего, начиная с модных мобильных приложений и вплоть до корневых компонентов операционных систем. Можно сказать, что код, создаваемый программистом, как бы адресован другим программистам (или самому себе в будущем). Вы думаете я что-то помню о коде проектов над которыми работал пять лет назад? Да я ничего не помню даже о том, что писал полгода назад!

Реализация программы должна быть проста и понятна не только вам в момент написания, но и каждому, кто впервые с ней встретится

Именование



В литературе по программированию вы можете найти много рекомендаций по именованию различных программных объектов. Основная же идея состоит в том, чтобы имена были осмысленными.

Имя функции должно отражать то, что она делает. Имя переменной должно отражать то, что в ней будет храниться

Принцип Разделения Ответственности



Есть такое замечательное правило:

Если для функции сложно подобрать имя, то ее нужно переписать (разбить на подфункции)

И еще один хороший принцип:

Одна функция — одна задача

Уровни Абстракции



Работая с кодом в одиночку также необходимо задумываться об уровнях абстракции. Таким образом мы помогаем самим себе в будущем. У программистов есть такое понятие: “закладывать в архитектуру", то есть заранее предусмотреть некую ситуацию, и, когда заказчик попросит что-то сделать, код уже будет максимально готов к таким изменениям. Разделение по уровням абстракции - это один из способов быть готовым к возможным новым требованиям. Нужно сделать нотификации для Айфона? Отлично, мы уже сделали их для Андроида. Теперь остается наладить соединение с новой платформой, а сами нотификации делать не придется - они уже у нас есть.

Не повторяйся



DRY - золотое правило программирования, значение которого трудно переоценить. Множество различных приемов программирования, таких как абстракции, наследование, композиция, разделение ответственности, паттерны проектирования и сама парадигма ООП (объектно-ориентированное программирование) во многом были сделаны для того, чтобы избежать повторений в коде. Такая, на первый взгляд, тривиальная задача порой ставит разработчика в очень сложные ситуации. Давайте рассмотрим как это происходит и какие виды дублирования бывают.

Дублирующее значение

Есть такой “анти-паттерн проектирования», как Магическое число. Допустим, переменная price умножается на число 0.13 и записывается в переменную tax. В этом случае можно догадаться, что tax - это коэффициент налога (13% налог НДФЛ). Любой российский разработчик знает величину подоходного налога и присутствие такого числа рядом с переменной price никого не удивит. И все-таки это - Магическое число! Во-первых, разработчик, незнакомый с российскими законами, не поймет откуда оно взялось. Во-вторых, величина налога НДФЛ в любой год может измениться, и тогда придется переделывать все участки кода, где данное число дублировано.

Подобные магические числа, как правило, повторяются в коде неоднократно. Но даже если сейчас оно имеется в единственном экземпляре, то велика вероятность, что в будущем нам снова придется его использовать. Так почему бы сразу не создать из него переменную?!




Любое значение должно присутствовать в коде в одном экземпляре

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

Дублирующие блоки кода

C данной проблемой нередко сталкиваются даже профессиональные разработчики. Представьте, что перед вами стоит задача создать процедуру, похожую на какую-либо уже имеющуюся. Действительно, легче и быстрее скопировать блок кода, чем выносить его в отдельную функцию и вызывать ее в нужном месте. Но сколько такой подход может создать проблем! Изменение этого блока необходимо применять сразу в двух, а часто в трех и более местах, куда был скопирован код. А если вынести этот код в отдельную функцию, то, кроме очевидной выгоды от отсутствия дублирования, мы приобретаем еще несколько менее очевидных, но не менее важных преимуществ.

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

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

Не копируйте код! Выносите его в отдельную функцию

Дублирующее поведение

Данный вид дублирования сложнее всего уловить в коде. Чтобы его успешно избегать, требуется опыт. В паттерне проектирования “Шаблонный метод” представлен замечательный способ, которым можно бороться с дублирующим поведением, почитайте про него. В этой статье я не буду ставить перед собой задачу пересказать реализацию этого шаблона проектирования, а просто расскажу о проблеме дублирующего поведения, и как ее можно решить данным способом.

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

Здесь две процедуры не только имеют общую стратегию поведения, но также имеют один общий этап. Реализовав поведение этих процедур в абстрактном базовом классе, мы вполне можем переместить в него код их общих этапов, наподобие этапа “Оповещение” в табличке, что будет удобно для совместного использования этого кода. А выделение основных схожих этапов в базовом классе упростит создание новых процедур.

Если вы видите, что создаваемые вами процедуры имеют схожее поведение, то попробуйте определить его в родительском (базовом) классе данных процедур

Рефакторинг



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

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

Но знать эти правила часто оказывается недостаточным. Создавая код, требуется много времени, чтобы он не просто работал, но и выглядел хорошо. Даже очень опытные разработчики часто переписывают свои функции много раз перед тем, как предоставить стабильную версию кода.

Создавая код, стремитесь к простоте и выразительности



Оставить комментарий

Ваше имя::


Комментарий::




Ничего не найдено