Когда пора комментировать

September 27, 2016

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

int some() {
  // ... много кода 

  // av: fix of #342987. Иногда внешний сервис возвращает 1, но при этом ...
  if (...) {
    // ...
  }

  // ... еще много кода
}

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

С Синатрой мне не по пути

September 26, 2016

Так получилось, что с Синатрой у меня так и не сложилось. Я раз пять пробовал запускать на нем различные легкие приложения, а потом понимал, что что-то как-то неютно (привет, ActiveSupport). Ой, и в базу нужно сходить (добавим ActiveRecord). Еще недурно было бы пару писем отправить (ура, есть же ActionMailer). В этот момент появляется первое подозрение, что что-то здесь не так. И потом нужно добавить пару форм, авторизацию, а сессии из коробки не работают, и csrf нет и вообще пора приложение переводить на рейлс и ловить кайф. Возвращаться в рейлс с других технологий - всегда в кайф, там все как-то просто берет и работает.

У нас сейчас минимум два таких приложения крутится, которые побывали синатрой и превратились в рейлс. Я общался - у многих так. Говорят, что где-то там, у кого-то синатра приложения работают и все довольны, но в живой природе пока не встречал.

Емейл-маркетинг в жизни простого инженера

September 23, 2016

Большинство инструментов маркетинга требуют добавления в домен SPF-записи. И через некоторое время получается примерно такая конструкция:

dig +short -t txt mailchimp.com
# v=spf1 include:servers.mcsv.net include:mail.zendesk.com
# include:_spf.google.com include:_lp.mailchimp.com ip4:50.22.164.201
# ip4:205.201.140.14 ip4:205.201.132.14 ~all

Однако важно помнить одну деталь - при проверки этой записи сервер по спецификации должен сделать не больше 10 DNS запросов (информацию легко найти в интернете по ключевым словам spf: too many DNS lookups), иначе репутация письма будет сильно испорчена. Мы один раз случайно _spf.google.com поставили на последнее место для одного из доменов, эта запись вылетела из лимита и письма, отправленные просто из gmail-интерфейса, стали часто попадать в спам.

Необходимое количество запросов легко посчитать вручную, раскрыв spf-запись каждого перечисленного адреса, или с помощью какого-нибудь скрипта. Однако самый лучшим способом проверить качество не только SPF-записей, а всех настроек в принципе, это отправить письмо из каждого используемого сервиса на специальный адрес, например который предложит www.mail-tester.com. Именно с помощью него мы быстро вычислили свою проблему с гмейлом.

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

Хорошего дня вам, высокой конверсии и нулевого баунс рейта!

Устои шатал

September 22, 2016

В книге Закон малинового варенья и еще 103 секрета консалтинга, которую мне подарил замечательный друг Андрей Рынкевич, есть глава о важности развития способности мыслить парадоксально. Найти в старом, что-то новое, увидеть нестандартное решение, придумать что-то свежее можно только попав в условия парадокса. Для меня парадокс граничит с провокацией, которая также помогает выйти за границы сложившегося, расшатать устои. Я люблю подвергать сомнению привычные схемы, проверяя их прочность с помощью юмора и, да что уж тут скрывать, легкого троллинга.

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

Из литературы можно узнать (читал давно, со ссылками беда :disappointed:), что самый лучший фильтр качества, который отлавливает больше всего ошибок - это формальная инспекция кода. Но если мы хотим чтобы в продакшен проходило скажем 1 из 100 ошибок, нам придется ставить несколько фильтров: ревью, ручное тестирование, юнит-тесты, интеграционное тестирование, альфы, беты и так далее, прилично удорожая производство. Саппорт, мониторинг это тоже фильтры, но уже в продакшене. Но нигде нет правила, что нужны именно автотесты, который встроены в рейлс и другие веб фреймворки. Их вполне в некоторых условиям можно заменить чем нибудь другим (подозреваю, что выгонят даже с привокзальных вечеринок).

На докладе я не врал, первые версии Учи.ру действительно были без тестов. Мы сделали не меньше пяти разных вариантов, ходили в школы, постоянно все переделывали, тестировали вручную и снова в школы. И я рад, что мы прорвались. Компания растет, задачи все интереснее и если бы не срезали углы, не факт, что получилось бы.

Для меня важность наличия тестов в привычном понимании находится месте на третьем в приоритетах, а полный ковередж месте на десятом. Однако считаю, что CI обязательно, стопроцентно должен быть подключен в каждом продакшене с первых же комитов, чтобы если кто-то хочет написать тесты, мог это безболезненно сделать. На первых двух местах конечно же общая организация процессов и структура проекта. Если главный мотив реализации совпадает с бизнесом, кода не очень много, он прост и прямолинеен, то это прекрасный задел. Вот, что например говорит DHH, наш дорогой:

Таким образом я и Дэвид. Или Дэвид и я, как будет менее провокационно? :smile: Мы вообщем с Дэвидом считаем, что хороший дизайн приложения важнее покрытия тестами. А что такое хороший дизайн? Хм. Кто знает.

PS: Чтобы пост был не совсем бесполезным поделюсь, что мы используем CirleCI - хороший, стабильный CI, есть бесплатный план с одним контейнером. Вообще я эпизодично пользовался и семафором, и трависом, и вексором, и дженкинсом, они сейчас все хорошие. Но для нас CircleCI - проверенно хорош.

Шоты

September 21, 2016

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

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

Теперь откуда корни. Саму идею я взял из стартапа компании Evrone, к сожалению не могу его нагуглить, а название "шот" с митапа Баду, на котором как-то был. Очень приятное и звучное.

Шоты у нас все любят и знают, что они значат. Что на них можно можно безопасно менять что хочется, но также к ним нужно относится со всей ответвенностью, так как одобренный шот напрямую попадает на продакшен. Поэтому когда Хероку, по-моему в этом году, написала как здорово создавать тестовые версии продакшенов из девелоперских веток (по-моему у них это называется Heroku Pipelines, но точно не скажу, не пользовался), я только ухмыльнулся - конечно здорово, мы так уже четыре года делаем :smile:.

Два принципа

September 20, 2016

В жизни я стараюсь следовать двум принципам:

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

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

Как заходить на сайт

September 19, 2016

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

  • curl -v https://yandex.ru - даст много полезной информации о сертификате, заголовках, редиректах и так далее.
  • ab -c10 -n100 https://yandex.ru/ - зайти громко, полезно если вы хотите увидеть факт запроса в логах (научил меня этому приему Иван Евтухович).
  • openssl s_client -connect yandex.ru:443 - выводит цепочку сертификатов, пригодится если есть подозрение, что установлен неправильный сертификат (из копилки непревзойденного Юрия Игнатова из Express42, вообще Юра умеет писать из головы такие хитрые openssl-команды, что я даже не пытаюсь повторить).

Таким образом отладку любого ендпойнта обычно начинаю с одной из этих команд. Конечно еще помогает curl во всех его других проявлениях, но нужные опции, кроме пожалуй -H, -X я читаю в мане или гуглю.

Поиск по логам для бедных

September 16, 2016

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

В самом простом случае логи сохраняются прямо на диске и регулярно ротируются. И если поиск по логам осуществляется редко, то вполне можно справится стандартными линукс утилитами.

Для начала очень рекомендую добавить в production.rb:

  config.log_tags = [
    :uuid,
    :remote_ip,
    lambda { |req| "user-#{req.cookie_jar.signed[:uid]}" || "anon" }
  ]

Тогда логи будут выглядет примерно так:

[4ba12972-bf3a-4dc5-9f9e-66908966e534] [50.141.127.26] [user-21] Processing by SomeController#some as HTML
[4ba12972-bf3a-4dc5-9f9e-66908966e534] [50.141.127.26] [user-21] Completed 200 OK in 16ms

и будут прекрасно грепаться.

fgrep '[user-21]' *.log
zfgrep '[user-21]' *.gz
zfgrep 'Completed 302' *.gz

У грепа есть разновидности: fgrep - ищет точные вхождения подстроки, не пытаясь использовать регекспы, zfgrep - делает тоже самое, но уже по сжатым файлам.

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

grep '10a15a85-1216-47b2-b2c0-8ddb38c97ae2\|2424e9f8-c0cb-411a-8057-6c6308e5f7f6' production.log

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

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

Что мне не нравится в рейлс

September 15, 2016

В рейлс мне не нравятся, пожалуй, две вещи: минимальный проект в любом случае состоит из большого количества файлов. В этом плане Node.js и Go симпатичней, можно выращивать полезный сервис, начав с одного файла. А иногда одного файла и хватает. Например у нас есть бот, который скидывает по запросу статус заббикса в слек. Он состоит всего из 130 строчек джаваскрипта.

И вторая вещь связана с динамической природой самого руби, которая с одной стороны помогла сделать выразительный, компактный и очень мощной фреймворк, с другой стороны код плохо грепается, гораздо хуже чем на Go или C++ например. Так как нет никакой гарантии, что кто-то не вызвал какой-нибудь метод с помощью send "some" + "_another". Конечно, обычно так не делают, но в общем случае гарантии нет. Например когда используются гемы со слишком пересахаренным интерфейсом, или попробуйте найти в легаси проекте все варианты построения раута (включая form_for [:admin, @user]).

Slim & Coffee

September 14, 2016

Я очень люблю Coffeescript и Slim по очень простой причине: Coffeescript выучил из ролика Рьяна Бейтса - railscasts #267 (кофескрипт сейчас сильно сдает позиции на фоне ES6, но это другая история), а Slim - читая главную страницу сайта. Все, больше никогда не учил, изредка только что-то подгугливал.

Конечно не все технологии можно так подать, но мне кажется к этому нужно стремится в современном разогнаном мире.