Программист ру – 19

Содержание

Чему я научился у ведущего программиста / Mail.ru Group corporate blog / Habr


Год назад я начал работать на полную ставку в Bloomberg. И тогда же задумал написать эту статью. Я думал, что буду полон идей, которые смогу выплеснуть на бумагу, когда придёт время. Но уже через месяц понял, что всё будет не так просто: я уже начал забывать то, чему научился. Либо знания настолько хорошо усвоились, что мой разум заставил меня поверить, будто я всегда это знал, либо они просто вылетели у меня из головы.1

Это одна из причин, по которой я начал вести дневник. Каждый день, попадая в интересные ситуации, я описывал их. И всё благодаря тому, что я сидел рядом с ведущим программистом. Я мог вблизи наблюдать за его работой, и видел, насколько она отличается от того, что сделал бы я. Мы много программировали вместе, что ещё больше облегчало мои наблюдения. Более того, в нашей команде не осуждается «подглядывание» за людьми, пишущими код. Когда мне казалось, что происходит что-то интересное, я поворачивался и смотрел. Благодаря постоянным вставаниям я всегда был в курсе происходящего.

Я год просидел рядом с ведущим программистом. Вот чему я научился.



Написание кода


Как называть вещи в коде

Одной из моих первых задач была работа над React UI. У нас был основной компонент, содержавший все остальные компоненты. Мне нравится добавлять в код немножко юмора, и я хотел назвать основной компонент GodComponent. Наступил момент ревью кода, и я понял, почему так трудно давать наименования.

There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors.

— Leon Bambrick (@secretGeek) January 1, 2010

Каждый кусок кода, который я окрестил, обрёл неявное предназначение.
GodComponent
? Это компонент, в который попадает вся дрянь, которую я не хочу помещать в нужное место. Он содержит всё. Назови я его LayoutComponent, и будущий я решил бы, что этот компонент присваивает макет. Что он не содержит состояния.

Ещё одним важным усвоенным мной уроком стало то, что если что-то выглядит слишком большим, вроде LayoutComponent с кучей бизнес-логики, то пора его рефакторить, потому что бизнес-логики здесь быть не должно. А в случае с названием GodComponent присутствие бизнес-логики не будет иметь значения.

Нужно назвать кластеры? Называть их в честь сервисов, которые на них работают, будет прекрасной идеей до тех пор, пока вы не запустите на этих кластерах что-то ещё. Мы дали им название в честь нашей команды.

То же самое относится и к функциям. doEverything() — ужасное название с многочисленными последствиями. Если функция делает всё, то будет чертовски сложно тестировать отдельные её части. Какой бы большой ни стала такая функция, вам это никогда не покажется слишком странным, ведь она же должна делать всё. Так что поменяйте название. Отрефакторьте.

У осмысленного наименования есть и обратная сторона. Вдруг название будет слишком осмысленным и скроет какой-то нюанс? Например, закрытие сессий не закрывает подключение к базе данных при вызове session.close() в SQLAlchemy. Мне следовало прочесть документацию и предотвратить этот баг, подробнее об этом рассказано в разделе Байка.

С этой точки зрения именование функций как x, y, z вместо count(), close(), insertIntoDB() не позволяет вкладывать в них определённый смысл и заставляет меня внимательно следить, что же делают эти функции.2

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

Унаследованный код и следующий разработчик

Бывало ли, что вы смотрите на код и он вам кажется странным? Почему так написали? Это же не имеет смысла.

Мне довелось поработать с унаследованной кодовой базой. Такой, знаете, с комментариями вроде «Раскомментировать код, когда Мухаммед разберётся в ситуации». Что вы тут делаете? Кто такой Мухаммед?

Я могу поменяться ролями и подумать о человеке, которому потом передадут мой код, покажется ли он ему странным? Отчасти решить эту проблему помогает ревью твоего кода коллегами. Это навело меня на мысль о контексте: нужно помнить о контексте, в котором работает моя команда.

Если я забуду этот код, вернусь к нему позднее и не смогу восстановить контекст, то скажу: «Какого хрена они так сделали? Это же глупость… А, погодите, это я так сделал».

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

Документация и комментарии в коде

Они помогают сохранить контекст и передать знания. Как сказал Ли в How to Build Good Software: 
Главная ценность ПО не в созданном коде, а в знании, накопленном людьми, которые создали это ПО

У вас есть открытый для клиентов эндпойнт API, которым, похоже, никто ни разу не пользовался. Нужно ли его просто удалить? Вообще говоря, это технический долг. А если я скажу вам, что в одной из стран 10 журналистов раз в год отправляют свои отчёты на этот эндпойнт? Как это проверить? Если в документации об этом не упомянуто (так и было), то никак не проверить. Мы и не проверили. Удалили, а через несколько месяцев наступил тот самый ежегодный момент. Десять журналистов не смогли отправить свои важные отчёты, потому что эндпойнта больше не существовало. А люди, обладавшие знаниями о продукте, уже покинули команду. Конечно же, теперь в коде есть комментарии, объясняющие, для чего это нужно.

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

Мы ещё не придумали идеального решения. Лично мне нравится, как Антирез разделил комментарии в коде по разным типам ценности.

Атомарные коммиты

Если вам нужно откатиться (а вам это понадобится. См. главу Тестирование), то будет ли этот коммит иметь смысл как единый модуль?
Как уверенно удалять паршивый код

Мне было очень неприятно удалять паршивый или устаревший код. Мне казалось, что всё написанное века назад является священным. Я думал: «Они же что-то имели в виду, когда так писали». Это противостояние между традицией и культурой с одной стороны, и мышлением в стиле «первичного принципа» с другой стороны. Это то же самое, что и в случае с удалением ежегодной-конечной-точки. Я усвоил особенный урок.
3

Я постарался бы обойти код, а ведущие разработчики постарались бы пройти сквозь него. Сотрите его. Выражение if, к которому невозможно обратиться? Ага, стираем. А что сделал я? Я просто написал поверх него свою функцию. Я не уменьшил технический долг. Во всяком случае, я только что увеличил сложность кода и переадресацию. Следующему человеку будет ещё сложнее собрать кусочки картины воедино.

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

Ревью кода

Ревью кода — прекрасный инструмент для самообразования. Это цикл внешней обратной связи, показывающий, как они написали бы код и как его написал ты. В чём разница? Один способ лучшего другого? Я спрашивал себя об этом при каждом ревью: «Почему они написали именно так?» И если не мог найти подходящий ответ, то шёл и спрашивал.

Спустя первый месяц я начал находить ошибки в коде моих коллег (как они находили в моём). Это было какое-то безумие. Ревью стало для меня гораздо интереснее, оно превратилось в игру, которой мне не хватало, игру, которая улучшала моё «чувство кода».

По моему опыту, не надо одобрять код, пока я не пойму, как он работает.


Моя GitHub-статистика.

Тестирование


Я так полюбил тестирование, что мне неприятно писать код в кодовой базе без тестов. 

Если ваше приложение делает лишь что-то одно (как все мои школьные проекты), тогда всё ещё можно тестировать вручную.4 Именно так я и делал. Но что происходит, если приложение выполняет 100 разных задач? Я не хочу тратить полчаса на тестирование, и иногда что-то упускаю из виду. Кошмар.

Здесь помогают тесты и автоматизация тестирования.

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

Сегодня, когда я пишу тесты, я стараюсь:

  1. Показать, как использовать тестируемый класс, функцию или систему.
  2. Показать, что, по моему мнению, может пойти не так.

Как следствие, чаще всего я тестирую поведение, а не реализацию (вот пример, который я выбрал на перерывах в Google).

В пункте 2 я не упомянул об источниках багов.

Когда я замечаю баг, то убеждаюсь, что у исправления есть соответствующий тест (это называется регрессионным тестированием) для документирования информации. Это ещё одна из причин, почему что-то может пойти не так.5

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

Так выглядит общая ситуация с тестированием.

Но это не единственная разновидность тестирования, которую я применяю. Я говорю о средах развёртывания. У вас могут быть идеальные модульные тесты, но если у вас нет тестов системных, то может произойти нечто подобное:

Это относится и к хорошо протестированному коду: если у вас на компьютере нет необходимых библиотек, то всё обрушится.

  • Есть машины, на которых вы разрабатываете (источник всех мемов вроде «На моём компьютере работало!»).
  • Есть машины, на которых вы тестируете (могут совпадать с предыдущими).
  • Наконец, есть машины, на которых вы развёртываете (они не должны совпадать с машинами, на которых вы разрабатывали).

Если на машинах тестирования и развёртывания среды не совпадают, у вас будут проблемы. А избежать этого помогут среды развёртывания.

Мы ведём локальную разработку в Docker на своем компьютере.

У нас есть среда разработки, эти компьютеры оснащены набором библиотек (и инструментов разработки), и сюда мы устанавливаем написанный код. Здесь его можно протестировать со всеми необходимыми системами. Также у нас есть бета/стейджинговая среда, которая полностью повторяет эксплуатационную среду. Наконец, у нас есть эксплуатационная среда — машины, на которых исполняется код для наших клиентов.

Идея заключается в том, чтобы выловить ошибки, которые не всплыли в ходе модульного и системного тестирования. Например, разницу API у запрашивающей и отвечающей системы. Думаю, в случае с личным проектом или маленькой компанией ситуация может быть совсем иной. Не у всех есть возможность создать собственную инфраструктуру. Однако можно прибегнуть к услугам облачных сервисов, например, AWS и Azure.

Вы можете настроить отдельные кластеры для разработки и эксплуатации. AWS ECS использует для развёртывания Docker-образы, так что процессы в разных средах будут относительно согласованы. Есть нюансы с точки зрения интеграции между разными AWS-сервисами. Вы вызываете правильную конечную точку из правильной среды?

Можно пойти ещё дальше: скачать альтернативные контейнерные образы для других AWS-сервисов и настроить локальную полнофункциональную среду на основе Docker-Compose. Это ускоряет цикл обратной связи.6 Возможно, я наберусь больше опыта, когда создам и запущу свой побочный проект.

Снижение рисков


Какие шаги вы можете предпринять, чтобы снизить риск катастрофы? Если речь идёт о новом радикальном изменении, то как можно удостовериться в минимальной длительности простоя, если что-то пойдёт не так? «Нам не нужно полностью развёртывать систему из-за всех этих новых изменений». Что, правда? И почему я об этом не подумал!

Архитектура


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

Нужно очень многое продумать при создании архитектуры.
  • Как будут использоваться числа?
  • Сколько будет пользователей? Насколько может увеличиться их количество (от этого зависит количество строк в базе данных)?
  • Какие подводные камни могут встретиться?

Мне нужно превратить это в чеклист под названием «Сбор требований». Сейчас у меня пока недостаточно опыта, постараюсь сделать это в следующем году в Bloomberg. Этот процесс во многом противоречит Agile: сколько можно проектировать архитектуру, прежде чем переходить к реализации? Всё дело в балансе, нужно выбирать, когда и что вы будете делать. Когда имеет смысл ринуться вперёд, а когда — отступить назад? Конечно, сбор требований не равносилен обдумыванию всех вопросов. Думаю, это окупается, если включить в проектирование ещё и процессы разработки. Например:
  • Как будет протекать локальная разработка?
  • Как мы будем упаковывать и развёртывать?
  • Как мы будем проводить сквозное тестирование?
  • Как мы будем проводить стресс-тестирование нового сервиса?
  • Как мы будем хранить секреты?
  • CI/CD-интеграция?

Недавно мы разработали новый поисковый движок для BNEF. Работать над ним было чудесно, я организовал локальную разработку и узнал о DPG (пакетах и их деплое), поборов деплой секретов. 

Кто бы мог подумать что деплоить секреты в прод может быть таким нетривиальным:

  1. Их нельзя поместить в код, ведь кто-то может их заметить
  2. Хранить их как переменную окружения как предлагает спека 12 факторов приложения? Неплохая идея, но как их туда положить? (Заходить на прод чтобы заполнить переменные окружения каждый раз, когда стартует машина — боль)
  3. Деплоить их как файлы? Но откуда они возьмутся и как их заполнять?

Мы не хотим всё делать вручную.

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

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

Создаём архитектуру, не забывая о сопровождении

Проектирование систем вдохновляет. А сопровождение? Не слишком. Моё путешествие по миру сопровождения привело меня к вопросу: почему и как деградируют системы? Первая часть ответа связана не с выводом из эксплуатации всего устаревшего, а только с добавлением нового. Склонность добавлять, а не удалять (ничего не напоминает?). Вторая часть — это проектирование с мыслью о конечной цели. Система, которая со временем начинает делать то, для чего не предназначалась, не обязательно будет работать так же хорошо, как система, изначально спроектированная для тех же задач. Это подход в стиле «отступить на шаг назад», а не хитрости и уловки.

Я знаю не меньше трёх способов снижения скорости деградации.

  1. Разделяйте бизнес-логику и инфраструктуру: обычно деградирует инфраструктура — растёт нагрузка, устаревают фреймворки, проявляются уязвимости нулевого дня и т.д.
  2. Создавайте процессы с учётом будущего сопровождения. Применяйте одинаковые обновления для старых и новых битов. Это предотвратит появление различий между старым и новым и сохранит весь код в «современном» состоянии.
  3. Убедитесь в том, что выбрасываете всё ненужное и старое.

Развёртывание


Буду ли я упаковывать фичи вместе или развёртывать их по одной? В зависимости от текущего процесса, если вы будете упаковывать их вместе, то жди беды. Спросите себя, почему вы хотите упаковывать фичи вместе?
  • Развёртывание занимает много времени?
  • Ревью кода проходит не слишком весело?

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

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

Когда что-то идёт не так


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

То же самое применимо и к «испорченной» машине в вашем кластере: выключите её, пометьте как недоступную, прежде чем выяснять, что с ней произошло. Я нахожу странным, насколько моё естественное желание и инстинкты противоречат оптимальному решению.

Думаю, этот инстинкт также приводил к тому, что я дольше исправлял баги. Иногда я понимал, что что-то не работает, потому что написанный мной код какой-то неправильный, и я залезал в дебри, просматривая каждую строку. Что-то вроде поиска «сначала в глубину». И когда оказывалось, что проблема возникла из-за изменения конфигурации, то есть я не проверил это в первую очередь, меня эта ситуация выбивала из колеи. Я очень нерационально тратил время на поиск бага.

С тех пор я научился искать «сначала в ширину», а потому уже «сначала в глубину», чтобы исключить верхнеуровневые причины. Что именно я могу подтвердить, имея текущие ресурсы?

  • Машина работает?
  • Код установлен верно?
  • Конфигурация присутствует?
  • <Характерная для кода конфигурация>, вроде того, корректно ли прописана маршрутизация?
  • Правильная ли версия схемы?
  • А потом уже погружаюсь в код.

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

Конечно, мне не нужно делать это каждый раз. Иногда достаточно лишь сообщения об ошибке, чтобы сразу заняться разбором кода. Когда я не могу определить причину, я стараюсь свести к минимуму количество изменений-в-коде-ради-того-чтобы-найти-причину. Чем меньше изменений, тем быстрее я смогу найти настоящий корень проблемы. Кроме того, теперь у меня есть памятка для багов, которая сэкономила мне больше часа на размышления «что я упустил?» Иногда я забываю о простейших проверках, вроде настройки маршрутизации, соответствия версий схемы и сервиса, и т.д. Это ещё один шаг по освоению стека технологий, который я использую, и то, что обретаешь лишь с опытом — интуицию в определении, что же именно не работает.
Байка

Эта статья не может быть полной без байки. Мне нравится их читать, и хочу одной из них поделиться с вами. Это история о поиске и SQLAlchemy. В BNEF работает много аналитиков, которые пишут отчёты об исследованиях. При публикации отчёта мы получаем сообщение. При получении сообщения мы обращаемся к базе данных через SQLAlchemy, получаем необходимые данные, преобразуем и отправляем на индексирование в экземпляр Solr. И как-то возник странный баг.

Каждое утро подключение к базе приводило к сбою с ошибкой «MYSQL server has gone away.» Иногда это случалось и днём. Машины включаются в течение дня, так что это было первое, что я проверил. Нет, при включении компьютера ошибка не возникала. Мы делали тысячи запросов к базе в течение дня, всё было в порядке. Так в чём же дело, что приводило к сбою?

Может быть, мы не закрывали сессии после транзакций? А если сессия та же, и спустя длительное время приходит запрос, то мы пропускаем таймаут и сервер исчезает. Быстро просмотрели код и убедились, что мы используем диспетчер контекста для каждой операции чтения, в ходе которой применительно к __exit__() вызывается session.close().

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

Session.close() в MySQL-диалекте SQLAlchemy не закрывает подключение к базе данных, если не используется NullPool. Это решило проблему. Забавно, что этот баг возник лишь потому, что мы не публиковали отчёты об исследованиях вечером или в обед. И отсюда проистекает ещё один урок: в большинстве ответов на StackOverflow (конечно, я там искал!) советовали настроить длительность таймаута сессии, или настроить параметр, управляющий объёмом пересылаемых в SQL-выражении данных. Всё это не имело для меня смысла, поскольку не было связано с истинной причиной. Я проверил, что размер запроса у нас не превышает ограничения, а сессии мы закрывали (хаха), так что таймаут просто отсутствовал. 

Мы могли бы «исправить» этот баг, увеличив длительность таймаута сессии с 1 часа до 8. Нам казалось бы, что проблема решена, до первого выходного в течение недели — и тогда первый отчёт на следующее утро завершился бы сбоем.

Это балансирование между настройкой параметров, игрой со статистикой и исправлением причины.

Мониторинг


Это то, о чём раньше я никогда не думал. Честно говоря, пока я не начал работать программистом на полную ставку, я никогда не занимался поддержкой систем. Я лишь создавал их, использовал с неделю и шёл дальше. 

Поработав с двумя системами, одна из которых обладала замечательным мониторингом, а другая не могла этим похвастаться, я начал очень высоко ценить мониторинг. Я не могу исправить баги, если не знаю об их существовании. Хуже всего, когда узнаёшь о багах от клиентов. «Чем я занимаюсь?! Я даже не знаю о проблемах в системе, которой владею?».

Я считаю, что мониторинг складывается из трёх компонентов: журналирования, метрик и оповещений. Журналирование в коде, как и дневник, процесс эволюционный. Вы прикидываете, что вам нужно будет мониторить, начинаете журналировать и запускаете систему. Со временем находите несколько багов, для исправления которых у вас мало информации. Пришло время расширить журналирование — чего не хватает вашему коду? Думаю, вы интуитивно понимаете, что важно журналировать. Я и тот ведущий программист журналировали очень разные наборы данных. Я считал, что достаточно будет логов запросов-ответов, а он фиксировал кучу метрик, вроде длительности исполнения запроса, некоторые внутренние вызовы, сделанные кодом, и т.д. А при ротации логов ещё и сортировал статистику.

Практически невозможно заниматься отладкой без логов. Если вы не знаете, в каком состоянии была система, как вы можете её воссоздать? Метрики можно извлекать из логов или выделять в коде (например, отправку событий в AWS CloudWatch и Grafana). Вы сами определяете набор метрик и отправляете информацию по мере исполнения кода.

Оповещения соединяют все элементы в замечательную систему мониторинга. Если одной из метрик является количество серверов, работающих в данный момент в эксплуатации, то когда её значение падает до 50 %, это должно быть поднимать настоящую тревогу — возникла серьёзная проблема. Количество сбоев превысило порог? Ещё одно оповещение. Я крепко сплю по ночам, потому что знаю — в случае чего меня разбудят (погоди, что?).

Это приводит к ещё одной привычке в разработке. Когда исправляешь баги, то думаешь не только о том, как исправить, но и о том, почему ты не определил их раньше? Было ли оповещение? Как можно улучшить мониторинг, чтобы предотвращать такие проблемы?

Я ещё не придумал, как мониторить интерфейс. Тестировать наличие компонентов мало для того, чтобы определять возникновение проблем. Обычно клиенты приходят и говорят — у вас тут что-то выглядит криво.

Заключение


Я многому научился за последний год. Я рад, что решил написать эту статью, с её помощью мне удалось полнее оценить, насколько я вырос как специалист. И я надеюсь, что вы узнали для себя что-то полезное!

Сейчас я сижу рядом с двумя ведущими разработчиками. Посмотрим, к чему это приведёт!

Хорошие инженеры самостоятельно проектируют системы, которые получаются более надёжными и лёгкими для понимания. Это приводит к мультипликативному эффекту, позволяя их коллегам опираться на их работу и решать свои задачи гораздо быстрее и надёжнее — How to Build Good Software.

В чём я не уверен


Я ещё не познал всех тайн программного инжиниринга. Так что эта глава служит мне напоминанием: я ещё многого не знаю! Если я всё делаю правильно, то в следующем году этот список должен стать длиннее.
  1. Мыслить абстракциями или реализациями?
  2. Должен ли я иметь твёрдое мнение относительно способов решения задач? Например, как следствие набитых шишек? Достаточно ли я сделал, чтобы иметь мнение?
  3. Продумывание рабочих процессов. Если нужно срочно или ситуативно поменять подход, то можно ли считать процесс нарушенным? Нужно ли его исправлять?
  4. Являются ли вспомогательные классы (utils) (папка, в которую ты складываешь то, что не знаешь, куда деть) признаком того, что код «с душком»?
  5. Как работать с документацией по коду и рабочим процессам?
  6. Как мониторить интерфейс так, чтобы замечать, когда что-то выглядит неправильно?
  7. Что лучше — потратить время на проектирование идеального API или контракта в коде, или хакинг и многократное итерирование в поисках лучшего решения?
  8. Легкий способ или правильный? Не уверен, что правильный способ всегда лучше.
  9. Делать самостоятельно или показывать тем, кто не знает, как сделать. Первое быстрее, а второе означает, что вам редко придётся делать это самостоятельно.
  10. Когда рефакторишь и избегаешь больших PR: «Если бы я сначала изменил все тесты, то я бы увидел, что у меня изменилось 52 файла, и это, очевидно, слишком много, но я сначала занялся кодом, а не тестами». Стоит ли оно того?
  11. Дальнейшее исследование снижения рисков. Какие существуют стратегии для уменьшения рисков в проектах?
  12. Эффективные способы сбора требований?
  13. Как снизить скорость деградации системы?

Примечания


  1. Такое происходит со многими знаниями. Вы знаете, как ездить на велосипеде? Можете кого-нибудь научить? Опишете им конкретные этапы, как вы это делали?
  2. Я имею в виду, что нужно не писать код с именами x(), y() и z(), а думать о них как о x(), y() и z(). Не думайте, что это WYSIATI.
  3. Классический барьер Честертона.
  4. Но я больше так не поступил бы. Однажды перейдя на сторону автоматизированных тестов, обратного пути нет?
  5. Есть мнение, что ситуация выходит из-под контроля, если провести миллион тестов на всё, что может пойти не так. Судя по тому, это не верно.
  6. Я давно этого не делал, так что не знаю, насколько легко найти или создать конкретные Docker-образы для AWS.
  7. Здесь в качестве среды может выступать ваш стек технологий.

habr.com

💲 Работа для программистов — вакансии в Москве. 👉 Найти работу программистом на PROFI.RU.

Популярные вопросы

Кто создаёт заказы?

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

Для кого подходит PROFI.RU?

Для частных специалистов и организаций. PROFI.RU — это универсальный канал привлечения клиентов. Мастер, представитель компании или салона на равных условиях могут откликаться на подходящие заказы и находить новых клиентов.

Как PROFI.RU привлекает клиентов?

PROFI.RU привлекает клиентов через рекламу в интернете. Благодаря маркетингу каждую неделю на сайте появляется более 70 тысяч заказов.

За что нужно платить?

Для большинства специальностей — за отклики на заказ, то есть за предложение своих услуг клиенту. Отклики — это ваша реклама, которую видят те, кто потенциально заинтересован в ваших услугах. Если клиент не просмотрит отклик, мы вернём за него деньги.
Репетиторы и спортивные тренеры работают по другой системе — платят комиссию за закрытый заказ.

Как получить отметку «Паспорт проверен» или «Данные проверены»?

Частные специалисты могут пройти проверку паспорта, а компании — проверку юридических данных. Проверенные анкеты чаще привлекают клиентов.

Как искать подходящие заказы?

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

Как получить оплату за услуги?

Об удобном для вас способе оплаты вы договариваетесь напрямую с клиентом и получаете всю сумму от него. Через нас оплата не проходит.

Я получу каждый заказ, на который откликнусь?

Не обязательно. На один заказ могут откликнуться несколько мастеров или компаний. Клиент сам выбирает подходящий вариант. Если клиент не откроет ваш отклик, мы вернём за него деньги. Узнать, просмотрен отклик или нет можно в личном кабинете.

profi.ru

6 причин учиться программированию, если ты не программист

Полина Коковина

1. Это свобода творчества

Многие думают, что для программирования нужны пятёрки по математике. Это заблуждение. Программирование больше про логику и творчество. Например, ты с друзьями в шутку придумал классную игру для смартфона. Можно, конечно, подождать, пока какая-нибудь компания за океаном выпустит её, а можно сделать это самому. Как эта игра будет работать, какие в ней будут правила, интерфейс и функции — решать тебе. С навыками программирования появляется возможность с нуля создать продукт или реализовать идею — приложение, сайт, программу — так, как это нужно именно тебе.

2. Это окупается

Простая истина: чем больше у тебя навыков, тем дороже твои услуги. Например, копирайтеры, которые могут сверстать простые html-страницы, бухгалтеры или менеджеры, которые могут автоматизировать работу Excel или Access с помощью кода, стоят дороже, чем их коллеги только с базовым набором скиллов.

Крупные компании быстро развиваются и ищут при этом новые способы оптимизации. Нанять команду разработчиков и платить каждому по 2 000–3 000 долларов в месяц — дорогое удовольствие. Нанять человека, который будет писать статьи, верстать и ещё придумает, как улучшить мобильную версию сайта, — выгодное решение.

У таких специалистов больше шансов попасть в крупную компанию.

Например, в The New York Times уже более половины журналистов умеют программировать. Когда издание изменило стратегию и сделало акцент на развитие веб- и мобильной версии — обучили программированию сотрудников, которые отвечают за цифровой контент.

3. Это сближает

Просить разработчика написать программу на Ruby, потому что ты вчера прочитал, что это новый и классный язык, плохая идея. Чтобы делать совместные проекты, понимать, как ставить задачи, вносить правки и на каком вообще языке говорить с программистами, нужно самому хотя бы немного понимать код. Даже руководителям компаний и владельцам стартапов полезно научиться программировать. Например, чтобы найти на рынке хорошего специалиста, лично провести собеседование и адекватно оценить уровень кандидата.

4. Это экономит время

Сколько раз ты вздыхал, когда приходилось делать рутинную работу? Например, ты журналист и пишешь для научно-популярного издания. Тебе нужно изучить, в каких странах чаще всего молнии ударяют в землю, и понять, что общего у этих регионов. На это уйдёт не один день. Программирование ускорит этот процесс: ты потратишь 30–40 минут на код, который поможет быстро проанализировать данные и составить отчёт.

5. Это развивает полезные привычки

Программирование — кропотливый процесс. Здесь не получится почитать учебник на досуге, посмотреть видео на YouTube и сходить на пару лекций. Нужно сесть и начать учить язык, копаться в коде и всё время практиковаться. Например, чтобы писать на Python, надо каждый день заниматься по 2–3 часа на протяжении нескольких месяцев.

Это дисциплинирует и помогает мыслить структурно и стратегически.

6. Это полезно для здоровья

В народе ходит слух, что программисты даже в старости лучше соображают. Шутки шутками, но в этом есть доля правды. Например, в 2014 году учёные из Университета Пассау анализировали сканы головного мозга людей во время занятий программированием. Результаты показали, что активны те же части головного мозга, которые работают при изучении иностранных языков. А это уменьшает риск развития болезни Альцгеймера.

Подтверждают пользу кодинга и другие исследования. В Медицинском колледже Альберта Эйнштейна в Нью-Йорке на протяжении нескольких десятилетий изучали почти 500 добровольцев в возрасте от 75 до 85 лет и доказали, что даже один день программирования в неделю может отсрочить развитие деменции на два месяца при регулярной тренировке мозга.

Читайте также

lifehacker.ru

Инструкция для тех, кто хочет стать программистом с нуля

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

С чего начать

Есть несколько вариантов развития событий, в результате которых человек становится программистом. Первый — родители-программисты, которые всему научили своих детей. Таким детям даже не нужно идти в университет. Второй вариант — модная профессия программиста. После школы нужно было выбрать, куда пойти учиться, и выбрали модное направление IT, вроде бы понравилось. И последний вариант — хобби, которое переросло в работу.

Если с вами ничего из вышеперечисленного не произошло, значит, у вас есть выбор из четырёх вариантов:

  • Самообразование. Этот вариант можно использовать как самостоятельно, так и в паре с другими методами. В интернете полно сайтов, книг и приложений, которые помогают изучать различные языки программирования и технологии. Но это самый тяжёлый путь для начинающих.
  • Университет. Если вы оканчиваете школу и хотите быть программистом, тогда идите в университет. Если не за знаниями, тогда за корочкой. Она может послужить бонусом при устройстве на работу. Хотя и какие-то знания вы тоже получите. Но не забывайте заниматься и самообучением. К выбору вуза стоит подойти очень ответственно. Внимательно изучите программы обучения и выбирайте лучшие технические вузы.
  • Ментор. Будет очень неплохо, если вы найдёте человека, который согласится помочь вам и направит вас в правильную сторону. Он подскажет подходящие книги и ресурсы, проверит ваш код, даст полезные советы. Кстати, мы уже писали о полезном ресурсе, где вы сможете найти ментора. Наставника можно искать среди знакомых программистов, на IT-тусовках и конференциях, на онлайн-форумах и так далее.
  • Специализированные практические курсы. Попробуйте поискать в своём городе курсы, где вас обучат какому-нибудь языку программирования или технологии. Я был приятно удивлён количеством таких курсов в Киеве, в том числе бесплатных и с последующим трудоустройством.

Какой язык, технологию и направление выбрать

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

  • Наличие на рынке вакансий. Конечная цель этого пути — найти работу программистом. А это будет трудно сделать, если на рынке вакансий никто не будет искать разработчиков на вашем языке программирования. Проверьте сайты с вакансиями, посмотрите, кого больше ищут, выпишите десяток языков. И переходите к следующему критерию.
  • Низкий уровень вхождения. Если вам придётся потратить длительное время на изучение языка, это может отбить у вас охоту к программированию вообще. Почитайте о тех языках, которые вы выбрали выше. Просмотрите литературу, которую нужно будет прочитать, чтобы изучить эти языки. И выберите те, о которых пишут, что они лёгкие, или которые вам показались лёгкими. Такими языками могут оказаться PHP, Ruby, Python.
  • Кайф от процесса. Если вам не нравится писать код на выбранном языке, вы не будете получать удовольствия от этого процесса, от работы и от жизни. А оно вам надо? Делайте правильный выбор.

Также вам придётся определиться с направлением программирования. Мобильное, десктопное, игры, веб, низкоуровневое программирование и так далее. Самые популярные и относительно лёгкие отрасли — разработка под веб, мобильные и десктопные клиенты. Под каждое направление может подходить один язык и совсем не подходить другой. То есть при выборе языка программирования также стоит отталкиваться и от этого фактора.

В любом случае изучите веб-технологии. Это язык разметки HTML, стили CSS и JavaScript, который позволит сделать вашу страницу динамической. На следующем этапе изучите серверный язык (Python, PHP, Ruby и другие) и подходящие для него веб-фреймворки. Изучите базы данных: практически в каждой вакансии программиста это упоминается.

Как получить начальный опыт

Без опыта вы не получите работу. Без работы вы не получите опыт. Замкнутый круг реальной жизни. Но ничего страшного, мы из него выберемся.

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

Во-вторых, вам нужно найти свои первые проекты. Это, наверное, самый сложный вариант, но рабочий. Вам придётся самому искать заказы, выполнять их, заморачиваться с оплатой. Для новичка это архисложно, но зато затем все остальные варианты покажутся плёвым делом. Выполненные проекты можно будет записать в опыт и показать вашему будущему работодателю. Реальные проекты являются большим плюсом в вашем резюме.

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

Ещё одним неплохим вариантом для получения реального опыта является open source. Таким проектам всегда нужны новые люди, пусть даже и новички. Вы можете поискать в проекте баги или посмотреть в баг-трекере и предложить методы их решения. Найти такие проекты легко на GitHub или других сервисах для хостинга кода. Не стесняйтесь задавать там вопросы.

Четвёртый вариант получения опыта — помощь знакомым программистам. Попросите их передать вам маленькие и несложные задания. Если что-то не будет получаться, у вас всегда будет к кому обратиться. И при этом вы будете участвовать в реальном проекте.

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

Почему стоит выбрать Python

Давайте немного подробнее поговорим о выборе первого языка программирования. Первый язык должен быть простым и популярным на рынке. Таким языком является Python. Я очень советую выбрать именно его в качестве первого языка программирования.

Код программы на Python читабелен. Вам даже не нужно быть программистом, чтобы в общих чертах понять, что происходит в программе. Из-за несложного синтаксиса Python вам понадобится меньше времени для написания программы, чем, например, на Java. Огромная база библиотек, которая сэкономит вам кучу сил, нервов и времени. Python является высокоуровневым языком. А значит, вам не нужно особо думать о ячейках памяти и о том, что там разместить. Python — язык широкого назначения. И он такой простой, что даже дети могут его выучить.

Справедливости ради стоит упомянуть и о других языках программирования. Java может стать неплохим выбором для новичка. Этот язык популярнее, чем Python, но и немного сложнее. Зато инструменты для разработки гораздо лучше проработаны. Стоит только сравнить Eclipse и IDLE. После Java вам будет проще перейти к работе с низкоуровневыми языками программирования.

PHP — ещё один очень популярный язык. И, мне кажется, он даже проще, чем Python. Очень легко найти себе ментора или решение какой-нибудь проблемы на форуме. Всё потому, что в мире существует огромное количество PHP-программистов разного уровня. В PHP нет нормального импорта, есть множество вариантов решения одной и той же задачи. А это усложняет обучение. И PHP заточен исключительно под веб.

Языки C и C# очень сложны для новичка. Ruby — хороший выбор в качестве второго языка, но не первого. JavaScript — очень простой язык, но ничему хорошему он вас не научит. А задача первого языка программирования всё-таки научить вас чему-то правильному, задать какую-то логику.

Важен ли английский язык

Важен! Не знаете? Учите. Знаете? Совершенствуйте. Учитесь читать, писать, слушать и говорить на английском. Делайте упор на техническую литературу. Слушайте англоязычные подкасты. Читайте англоязычные учебники по программированию.

Что нужно знать, кроме языка программирования

Конечно же, кроме языка программирования и английского, нужно знать что-то ещё. А вот что — зависит от направления, которое вы выберете. Веб-программист обязан знать HTML, CSS, JavaScript. Десктоп-программист учит API операционной системы и различные фреймворки. Разработчик мобильных приложений учит фреймворки Android, iOS или Windows Phone.

Всем нужно выучить алгоритмы. Попробуйте пройти курс на Coursera или найти подходящую для себя книгу по алгоритмам. Кроме этого, нужно знать одну из баз данных, паттерны программирования, структуры данных. Стоит также познакомиться с репозиториями кода. Хотя бы с одним. Обязательно знание систем версионного контроля. Выбирайте Git, он самый популярный. Вам нужно знать инструменты, с которыми вы работаете, операционную систему и среду разработки. И главный навык программиста — уметь гуглить. Без этого вы не проживёте.

Последние шаги

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

lifehacker.ru

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *