Найти тему
Я, Golang-инженер

#35. О рефакторинге и указателях на массивы

Оглавление

Это статья об основах программирования на Go. На канале я рассказываю об опыте перехода в IT с нуля, структурирую информацию и делюсь мнением.

Хой, джедаи и амазонки!

В предыдущем посте я рассказывал об астериске и амперсанде в Go. Сегодня применю знания об указателях для возвращения из функции значений для массива - синтаксис для массива может запутать по сравнению с обычными переменными типа int или string.

Также рассмотрим элементы рефакторинга кода, в т.ч для функций, и начнём, пожалуй с этого. Go!

1. Рефакторинг

Рассмотрим три элемента рефакторинга. Но сперва познакомимся с определением в том виде, как его понимаю я:

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

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

Овладевание инструментами рефакторинга - полезный навык IT-разработчика. Почитать о рефакторинге можно, например, в этой статье от школы Скиллбокс или в этой от журнала "КОД" Яндекс Практикума.

А теперь о трёх элементах рефакторинга, с которыми познакомился:

1.1. Изменение наименования переменных

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

Мем
Мем

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

Далее посмотрим на код без рефакторинга:

Код
Код

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

Запускаем код и смотрим, что он делает:

Выполнение кода в терминале
Выполнение кода в терминале

Итак, эта программа рисует псевдографикой Ёлочку. О ёлочке можно почитать здесь.

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

Вопрос: что делать - если программа сложнее в десять раз и её результат не выводится в терминал? Трудно вспомнить для чего этот код вообще писался.

Ответ: Разбираться в коде. В этом поможет рефакторинг.

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

Код с говорящими именами
Код с говорящими именами

Итак, ранее в циклах у нас были переменные-итераторы i и j. Полезно дать им другие имена, чтобы облегчить понимание кода. Также переменным a и b мы присвоили свои имена, сигнализирующие о том, что хранится в переменных: высота и ширина (Ёлочки).

Изменяя имена переменных, мы даём лучшее понимание кода, что делает наш код "чище".

1.2. Длина функции

Хорошая функция - короткая функция. Что значит короткая? Она помещается на экране компьютера целиком.

Экран компьютера тоже растяжимое понятие, и я встречал более конкретное предложение: длина функции - не более 15 строк.

В нашем предыдущем примере длина функции main 18 строк. Лаконичнее будет вывести печать псевдографикой в терминал в отдельную функцию:

Код с добавленной функцией
Код с добавленной функцией

Итак, хотя количество строк для этого конкретного кода увеличилось, но важно помнить - количество строк не показатель качества кода. В таком виде программа должна быть понятнее, особенно если программа сложнее в 3-5-10 раз.

Что ещё хочу сказать - в IDE имена переменных (функций и прочее) можем менять в автоматизированном режиме, т.е. не изменять имя каждой переменной копипастом (ctrl+c & ctrl+v):

1.2.1. Простая замена

Аналогична работе в офисных приложений типа Word - где мы меняем все упоминания фразы на другую фразу. Но тут будет другая проблема - мы можем заменить часть фразы в длинном имени.

Допустим, в предыдущем коде мы решили функцию printFir путём обычной автоматизированной замены, первую часть имени print заменить на printing:

Автоматизированная замена
Автоматизированная замена

Проблема в том, что меняя print на printing, мы изменили ту часть кода, которую трогать нельзя - а именно изменили fmt.Print на fmt.printing - программа не будет работать.

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

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

1.2.2. Замена имени

Полезнее использовать не обычную замену, а замену имён. Эта функция вызывается другой кнопкой и другим сочетанием клавиш. Например в моей LiteIDE эта замена вызывается, когда курсор стоит на имени элемента (функции/переменной и т.д.) и нажимаешь сочетание клавиш (по-умолчанию) Ctrl+Shift+R:

Режим замены имени
Режим замены имени

Так мы предсказуемо дорабатываем код.

1.3. Форматирование кода

У каждой компании свой стиль форматирования кода. У крупных компаний есть целые стандарты (гайдлайны) по форматированию - чтобы все сотрудники придерживались единого стиля.

Сейчас важно знать, что форматирование кода по-умолчанию, можно настроить при каждом сохранении, либо же командой в терминале: go fmt имя_файла, - см. иллюстрацию ниже:

Ввод в терминал команды форматирования кода
Ввод в терминал команды форматирования кода

На иллюстрации мы видим, что 9 строка имеет некорректный отступ, а в 18 строке визуально различим лишний пробел перед переменной col и знаком "меньше". Нужно отформатировать код.

Команда fmt пересохраняет файл с кодом, в данном случае имя файла с кодом time.go. Поэтому вышло сообщение о разрешении пересохранить файл.

Удобнее настроить такое форматирование при каждом сохранении, а не отдельной командой в терминале.

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

2. Указатели на массивы

Как мы помним, функция работает с копиями аргументов , а не с самими аргументами.

Код с указателем на массив
Код с указателем на массив

Код принимает десять элементов с типом данных int и выводит их в терминал в обратном порядке. Код можно прочитать так:

  1. Строка 15: Из функции main передаём в функцию revers адрес хранения массива ar: revers(&ar);
  2. Строка 19: В функции revers мы принимаем переменную, в которой хранится адрес переменной-массива размером 10 и типом данных int: func revers(array *[10]int);
  3. Строка 20: В цикле мы проходим по всем элементам переменной-массива, на который указывает переменная array: range *array;
  4. Строка 23: Возвращаем из функции revers значение переменной, адрес которой хранится в переменной array: *array;
  5. Строка 16: Печатаем переменную ar с новым значением, которое было сформировано в функции reverse.

Астериск в возвращаемом значении можно поставить не перед переменной, а перед типом данных возвращаемой переменной (не в 23 строке, а в 19й строке:

Изменение расположения указателя для возвращаемого аргумента
Изменение расположения указателя для возвращаемого аргумента

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

Также можно добиться того же результата, без использования указателей. Но тогда нужно доработать строку 15:

Код без указателя
Код без указателя

В этом коде мы присвоили нашему первому массиву значение, возвращаемое функцией в строке 15.

3. Выводы

Мы познакомились с основами рефакторинга: имена переменных, размер функции, форматирование кода. Также познакомились с синтаксисом для возвращения массивов из функций.

Постепенно уровень IT-знаний растёт. Заметил такую штуку: пока изучаю одно, ранее изученное забывается. Доходит до того, что забываю как пользоваться логикой и/или. Поэтому каждый день обязательно прорешиваю несложные задачи, чтобы освежить в памяти пройденный материал. Что рекомендую и вам.

Успехов, бро

--//--//--

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

Hunter Bryant https://unsplash.com/photos/dvb9r2_C-sU
Hunter Bryant https://unsplash.com/photos/dvb9r2_C-sU

Бро, ты уже здесь? 👉 Подпишись на канал для новичков «Войти в IT» в Telegram, будем изучать IT вместе 👨‍💻👩‍💻👨‍💻