Привет, %username%! Какое-то время назад я делал опрос на тему “Должен ли Ops уметь программировать?” – большинство сошлось во мнении, что “ДА, Ops должен уметь кодить”. И вот теперь коротко о том, какой путь выбрал я.

Суть проблемы

Примерно 2-3 недели назад я себе признался в том, что я хреновый программист (тут надо бы вставить гифку/картинку ba-dumm-ts.gif, но мне лень – ты же сможешь ее визуализировать в голове с соответствующим звуком). И поводом такого признания стало то, что мне на работе стали прилетать задачки на программирование в духе “Доработать такой-то сервис на Python, добавить в него функционал, освежить helm-chart и выкатить в K8s”. А одно из свежих предложений “Может переписать сервис с Python на Golang”. И вот программирую я просто отвратительно – был вагон собеседований с live-coding, когда я проваливался потому что не шарю за алгоритмы.

Мой вариант решения проблемы

Собственно я решил исправлять этот собственный косяк и уже больше двух недель (ежедневно, без выходных и пропусков) прохожу курсы на Stepik и решаю задачи на LeetCode и Codewars. На Stepik’e я прохожу только бесплатные курсы и буквально вчера – 18.05.2022 – закончил первый курс по Golang и сразу начал второй. На LeetCode и Codewars я тренирую алгоритмы – я в них не погружался со школы и это просто пипец. Катастрофически не хватает практики программирования и благодаря этим ресурсам я восполняю пробел в знаниях.

Что и почему выбрал

Важно понимать, что то о чем я рассказываю – в первую очередь IMHO, а не silver-bullet. На том же Stepik’e в курсах есть практические задания – “Напишите программу, которая выполняет это и это” – которые позволяют закрепить пройденный материал на каком-то этапе. Некоторые решения на Golang из курса по этому языку я выкладывал в виде gist’ов. Вот пример задачи по работе с данным в формате JSON.

На LeetCode и Codewars я просто тренируюсь в алгоритмы – решаю различные алгоритмические задачи на Python и Golang. Почему сразу два языка? Очень просто – с Python я работаю чуть больше и даже что-то уже писал самостоятельно – например вот такая поделка zbx2jira, которая в 2019 году решала проблему интеграции Zabbix-мониторинга и JIRA ServiceDesk. В то время в Zabbix не было прямой интеграции “из коробки”, поэтому мне пришлось изобретать. Стоит заметить, что работает эта штука до сих пор.

Golang я выбрал просто “потому что” – довольно стабильный, компилируемый, быстрый язык. Да и в целом полезно – когда надо какую-то “быструю” штуку сделать или когда есть потребность в распространении в виде бинарного файла. Python тоже можно в бинарь упаковать, но вот проблема в том, что он будет весить как крыло от самолета. А бинарь на Golang будет совсем мало весить.

Как решаю

Собственно говоря к решению задачек на LeetCode я подхожу довольно своеобразно. Я сначала решаю задачу на Python – на нем мне проще решать т.к. я его знаю чуть лучше чем Golang, а после переписываю свое решение с Python на Golang и повторно отправляю решение на другом языке. Начал я с данного листа задачек Easy Collection – Top Interview Questions. Некоторые решения на Python я выкладываю в репозиторий interview-task, который изначально заводил для задачек с собеседований. Когда разберусь поглубже в Golang и смогу внятно писать тесты, то и на Golang такой репозиторий сделаю, а пока только на Python – на нем через pytest очень просто писать примитивные тесты.

Если пройтись по репозиторию interview-task, то можно увидеть одинаковую структуру всех файлов с задачами и тестами. Описание задачи с LeetCode я просто копирую как есть и вставляю в файл с реализацией tasks/task0000.py в виде docstring модуля – в самом начале. Не самый удачный вариант, но поскольку это независимые задачи – вполне себе удобоваримо. В каждой задаче есть пара примеров, которыми объясняется вид входных данных и выходных данных. Собственно примеры и берутся за основу для тестов, которые кладутся в tests/test_task0000.py. В тесте все просто и максимально наглядно:

import pytest

from tasks.task0020 import solution


@pytest.mark.parametrize(
    "s, result",
    [("leetcode", 0), ("loveleetcode", 2), ("aabb", -1)],
)
def test_task0020_solution(s, result):
    assert solution(s) == result

Импортируется модуль pytest и конкретная задача – все функции, которые являются решением я называю solution. Это позволяет мне писать тесты очень просто – строка from tasks.task0020 import solution одинаковая во всех тестах, меняется только порядковый номер задачи. После чего я описываю кейсы из примеров задачи: входные и выходные данные, и просто прогоняю один тест с разными данными.

После написания тестов я перехожу к реализации самого решения. Такой подход в целом называется TDD – Test-driven Development или разработка через тестирование. TDD предполагает написание тестовых кейсов до написания кода функционала. Ты сначала пишешь тесты, которые “горят красным” и потом начинаешь реализовывать функционал, который сделает эти тесты “зелеными”. Может показаться, что я “подгоняю свое решение под конкретные ответы”, но это не совсем так. На том же LeetCode очень большой набор тестов прогоняется на твоем решении уже после того, как ты отправил его. Если что-то пойдет не так в твоем решении и с твоими тестами, то LeetCode тебе любезно сообщит об этом и даже покажет на каких входных данных у тебя все зафейлилось и что ожидалось на выходе.

Как я уже упоминал выше, после решения задачи на Python, я переписываю это решение на Golang – тут все просто с тем отличием, что я не пишу тесты. Пока не разобрался в этом вопросе достаточно хорошо, но когда-нибудь и это начну делать.

Что дальше

Дальше все просто – хочу решить больше сотни задач на LeetCode – своего рода моя внутренняя ачивка. Надеюсь у меня получится “затащить все 100 дней кода” – если не очень понятно, то просто загугли “100 days of code” и можешь добавить название своего языка программирования.

Итоги

Итоги подводить пока рано, потому что каких-либо внятных (по моим меркам внятных) достижений еще нет. По моим меркам “внятное достижение” – это “написать свой сервис”. Не “микросервис”, а полноценную взрослую штуку. Например сервис отложенных постов для своего Telegram-канала, или еще что-то подобное.


Если у тебя есть вопросы, комментарии и/или замечания – заходи в чат, а так же подписывайся на канал.