Найти в Дзене
Я, Golang-инженер

#74. Makefile как способ автоматизировать работу с ПО, избежать досадных ошибок и задокументировать код

Это статья об основах программирования на Go. На канале я рассказываю об опыте перехода в IT с нуля, структурирую информацию и делюсь мнением. Хой, джедаи и амазонки! Участвовал в командной разработке проекта в Мастерской Практикума и познакомился с утилитой make для работы с Makefile. Расскажу о пользе такого подхода для разработчика, которая проявляются при работе над командным более-менее крупным проектом, для которого предполагается поддержка: тестирование, расширение кода и введение в разработку новых людей. Мастерская Практикума в моём понимании - это проект Яндекс Практикума, где его выпускники могут получить опыт командной работы по ТЗ над реальным проектом, ревью кода и рекомендациями практикующего разработчика с видео-встречами, обсуждением задач в ТГ, PR, работой с гитом уровнем выше, чем git push. Задачи мы выбирали по канбан-доске в GitHub. Ментором выставлялись задачи, а желающие из команды выбирали приглянувшиеся поручения, назначали себя ответственными и выполняли их.
Оглавление

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

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

Участвовал в командной разработке проекта в Мастерской Практикума и познакомился с утилитой make для работы с Makefile.

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

1. Введение

Мастерская Практикума в моём понимании - это проект Яндекс Практикума, где его выпускники могут получить опыт командной работы по ТЗ над реальным проектом, ревью кода и рекомендациями практикующего разработчика с видео-встречами, обсуждением задач в ТГ, PR, работой с гитом уровнем выше, чем git push.

Задачи мы выбирали по канбан-доске в GitHub. Ментором выставлялись задачи, а желающие из команды выбирали приглянувшиеся поручения, назначали себя ответственными и выполняли их.

Одной из таких задач был запуск миграций через Makefile. Позднее появилась задача по запуску приложения и инфраструктуры в Docker Compose и управление процессом через Makefile.

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

Make - это консольная программа для управления работы с приложением.

Вот что написано в официальной документации, прочтите без переводчика:

Фрагмент официальной документации
Фрагмент официальной документации

Утилита make как я понял, установлена на всех Linux по-умолчанию. На Windows есть аналог - nmake.

Справка:

  • За выходные в апреле 1976 г. написана первая версия утилиты Make Стюартом Фельдманом в компании Bell Labs.
  • В 1980-х Ричард Столман и Роналд Макграф в рамках проекта GNU расширили функционал утилиты Make. Это ПО стало стандартом для ОС на основе UNIX, в т.ч. Linux.
  • В 2003 г. Стюарт Фельдман получил премию Ассоциации вычислительной техники Software System Award за создание Make. Это ежегодная награда за выдающиеся долгосрочные достижения в области разработки программных систем.

Вот частичный список премии Software System Award:

Скриншот с английской Википедии
Скриншот с английской Википедии
Скриншот с английской Википедии
Скриншот с английской Википедии

Make была написана, чтобы упростить трудоёмкий процесс сборки приложений на ОС Unix. Позднее появились и другие реализации Make, но все они базируются на использовании одного и того же понятного текстового формата инструкций без закодированных двоичных файлов - Makefile.

2. Makefile

Makefile - это текстовый файл с инструкциями для утилиты make.

Создаётся он без расширений, просто называется Makefile:

Терминал
Терминал

Можно конечно разные имена придумать этому файлу, но придётся его запускать с различными флагами.

Makefile хранится в репозитории с проектом - обычно в корневом каталоге, но не всегда.

Инструкции в Makefile позволяют выполнять одну или серию команд в заданной последовательности одной простой командой.

Рассмотрим Makefile:

Makefile
Makefile

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

О миграциях схемы БД можно почитать здесь: *клик*. Конкретно в этом проекте использовалась библиотека goose для PostgreSQL.

Теперь, создав такой Makefile, разработчик для взаимодействия с ПО, вместо набора команд может ввести в терминал название требуемой цели после указания утилиты make:

make migrate-up

и будет выполнена серия команд, определённая под данной инструкцией.

Единожды созданные и проверенные команды позволяют IT-специалисту пользоваться ими по простой схеме без необходимости прописывать каждый символ каждой команды: сокращается риск опечатки или просто неверного синтаксиса. Это особенно полезно при командной разработке, когда один человек разобрался как и что должно работать, а другому придётся либо потратить время на понимание и поиск команд, либо работать с приложением простыми командами из Makefile.

По поводу целей-миграций. По-логике, если переменные окружения определены, например, в ~./bashrc-файле или аналоге, или в самом мейкфайле как у меня в шапке, то нет нужды вручную прописывать их под целями, как я это сделал с миграциями:

GOOSE_DRIVER=$(GOOSE_DRIVER) \
GOOSE_DBSTRING=$(GOOSE_DBSTRING) \

Но без такого подхода миграции не работали. Так что прописывал под каждой целью отдельно.

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

Makefile
Makefile

Запустив команду в терминале

make all

выполнится сперва цель build, затем - run-local. Т.е. сперва будут собраны образы из Docker Compose, а затем запустятся контейнеры.

Такой подход удобен, когда есть несколько целей со множеством команд. И важно соблюдать их последовательность. Причём не хотелось бы прописывать под одной целью серию слабосвязанных команд, а нужно разделить блоки команд на разные цели. Это как при написании кода: одна функция отвечает за что-то одно. Но это уже к лайфхакам работы относится.

Комментарии в Makefile позволяют IT-специалисту ознакомиться с кратким описанием назначения целей - документирование кода.

Рассмотрим пример работы с Makefile в известном приложении - Kubernetes, написанном, кстати, на Go. Вот два фрагмента Makefile:

https://github.com/kubernetes/kubernetes/blob/master/build/root/Makefile
https://github.com/kubernetes/kubernetes/blob/master/build/root/Makefile
https://github.com/kubernetes/kubernetes/blob/master/build/root/Makefile
https://github.com/kubernetes/kubernetes/blob/master/build/root/Makefile

Как видите, довольно сложная структура: много комментариев, примеры, ветвления с else и другие интересные вещи типа директивы .PHONY, позволяющим понять с чем работаем: каталогом в репозитории или целью, прописанной в Makefile.

В общем, стартануть можно с простого, а когда подключитесь к реальному проекту и увидите там Makefile уже будете немного знать об этом инструменте разработчика.

3. Выводы

Познакомились с популярным инструментом разработчиков и историей его возникновения. Я показал два примера Makefile - простой и сложный. Простой - чтобы понять принцип и как можно начать работать, а сложный - понять, как выглядит Makefile сложного приложения.

Спасибо, что дочитали публикацию до конца. Успехов, и будем на связи.

https://ru.freepik.com/free-photo/man-forest-with-tea-by-fire_2527737.htm
https://ru.freepik.com/free-photo/man-forest-with-tea-by-fire_2527737.htm

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