Зачем и кому нужен Go?

Так вышло, что последнии 2 года я довольно плотно работаю не только с давно привычными мне C++ и Python, но и Go. Как мне кажется, 2 года довольно приличный срок для того чтобы сформировать свое мнение о каком-либо инструменте, так что, пора им поделиться. Так же, по моим ощущениям, про Go обычно пишут люди из небольших компаний и стартапов, я же буду писать с точки зрения разработчика из матерой корпорации специализирующейся на разработке ПО.

Когда Go не нужен и не полезен

Начнем с самого важного: при каких условиях этот язык скорее вреден.
Continue reading

Командная строка и Windows

Надо признать, что время не стоит на месте и за те 9 лет что я не работал с Windows много что изменилось. Довольно неожиданным для меня открытием оказалось современное состояние командной строки на Windows, которая дошла до некого рабочего состояния. Не совсем, конечно, Vim так же хреново работает как и раньше, но всё же. Итак, как сделать окружение Windows относительно удобным для того, кто привык к *NIX. Continue reading

Информативная обработка ошибок в Go

Концепт обработки ошибок в Go довольно интересен в первую очередь тем, что ошибка в Go это просто произвольный объект поддерживающий интерфейс с функцией Error() string. Подобный подход превращает ошибку в некий гибрид Boolean с текстовым описанием и изрядная часть кодовой базы Go проектов выглядит так:

func foo(val int) error {
    if val == 42 {
        return fmt.Errorf("42 is not allowed")
    }
    // normal workflow
    return nil
}
...
err := foo(1)
if err != nil {
// do some error handling
}
// normal workflow

Continue reading

9 лет с macOS

Внезапно осознал, что приблизительно 9 лет назад, в 2009 году, я перешел с Windows на Mac OS X. Сейчас, не дотянув 1 года до ровных 10 лет, я окончательно ушел с macOS на Linux + Windows. Всё это, само собой, относится к повседневному домашнему использованию и мелким личным проектам, на работе как были все 3 платформы с macOS в качестве основной рабочей среды, так и остались.

В 2009 году решения от Apple действительно впечатляли как своими дизайнерскими и инженерными решениями, так и тем что “всё просто работает”. Да и в профессиональном плане эта миграция 9-ти летней давности была очень удачным решением для меня. Именно благодаря этому я в своё время оказался в Лаборатории Касперского и получил невероятно интересный и полезный опыт. Но время шло, конкуренты развивались, Apple деградировал и в последнии годы я был вынужден сначала уйти с iOS на Android, который внезапно стал предлагать на много более адекватное сочетание цены/качества, а потом и на PC индивидуальной сборки.

В принципе, для человека занимающегося графическим дизайном или просто использующего компьютер для набора текстов, интернета и просмотра фильмов, но практически не играющий в ресурсоемкие игры решения Apple (iMac, все виды MacBook) до сих пор на высоте как минимум с точки зрения железа. К сожалению с точки зрения софта ситуация не столько радужная до боли стала напоминать древние Windows, когда до выхода SP1 о переходе на новую версию ОС и думать было нечего, так как с большой вероятностью что-то отваливалось. Так что на macOS всё до сих пор вроде “просто работает”, но только после Нового Года. Каждую осень выходит нечто непотребное, это нечто усиленно латают 2-3 месяца и после НГ уже можно обновляться на новую ОС.

Хотя дальнейшая пригодность macOS для дизайнеров мне кажется тоже под большим вопросом после новости о том, что OpenCL объявлен устаревшим, так как миграция всех продуктов со сложными расчетами на Metal Performance Shaders, который поддерживается исключительно Apple, мне кажется довольно невероятным развитием событий. Собственно, отношение к GPGPU со стороны Apple для меня и стало последней каплей. Мало того, что на всех компьютерах устанавливаются GPU от AMD, так еще и никакое кросс-платформенное API типа Vulkan, а теперь еще и OpenCL, не поддерживается. Хотя и до последнего анонса максимально поддерживаемая версия OpenCL была всего лишь 1.2.

В процессе миграции на Windows + Linux я с удивлением осознал что за прошедшие 9 лет Windows так и не стал дружественной к разработчику платформой. Всё те же пляски вокруг установки разных SDK, Студий, никакенная консоль, нет менеджера пакетов даже для продуктов Майкрософт… Ту же CUDA я так и не смог нормально запустить на Windows за где-то 8 часов чистого времени (то не та версия студии, то компонент уже установлен, но часть dll почему-то не установилась вообще, то еще 1001 невнятная проблема) но сделал это за 15 минут на Ubuntu, что мне кажется довольно показательно, с Ubuntu я ведь те же 9 лет не имел дела.

В итоге у меня теперь Windows для C1 и Photoshop, к сожалению на Linux нет и не будет ничего сопоставимого, и Ubuntu для всего остального

Coursera, Глубокое обучение

Обычно я довольно скептично отношусь к около-IT онлайн-курсам. То слишком много воды, то слишком мало нового, то слишком медленный прогресс. Выходит проще взять документацию по интересующей тематике, найти подходящие заметки в блогах или книги и разобраться самостоятельно. До того как я наткнулся на специализацию по Глубокому обучению от Эндрю Ына, единственным исключением для меня был разве что курс на той же Coursera по алгоритмам Тима Рафгардена. А вот с курсом Глубоким обучением я сильно увлекся тематикой.

Курс Глубокое обучение прекрасен по большому счету вообще во всем: хорошо структурированная и продуманная теоретическая часть, интересная практическая часть на Python с использованием NumPy и переходом к TensorFlow в конце второй ступени, адекватные домашние задания. До того как начать этот курс я попробовал начать курс на fast.ai, но был довольно сильно разочарован сильнейшим перекосом в сторону практики, где всё демонстрируется на основе собственной надстройки толи над TensorFlow, толи над PyTourch. В принципе название курса на fast.ai – “Практическое машинное обучение для кодера” верное, делай что сказали без понимания базы и будет тебе счастье. Ну, возможно, кого-то такой подход и устраивает, я через пару недель сдался и пошел искать нечто более глубокое, так как имея ответ на вопрос “почему”, дойти до “как” в разы проще.

Если говорить про уровень начальной подготовки для специализации Глубокое обучение, то нужно помнить кое-какие моменты из старших классов школы, такие как производные, умножение матриц и простейшие элементы из математической нотации (такие как ∑, ℝ). Кроме того, нужно иметь хотя бы поверхностное представление о Python и Jupiter (бывший IPython). В зависимости от начальной теоретической базы, в неделю на курс будет уходить где-то от 4 и до 8 часов если исходить из стандартного темпа прохождения курса.

Все домашние задания в рамках курса выполняются в “тетрадях” Jupiter на серверах Coursera. Хотя если захочется копнуть поглубже и развить тему самостоятельно, то возникает необходимость либо в аренде мощностей в облаке (AWS, PaperSpace, и т.п.) либо сборке собственного компьютера под свои задачи, так как требуется довольно производительно GPU с поддержкой CUDA. После многочисленных таймаутов и отвалившихся сессий у облачных провайдеров я просто собрал себе подходящий компьютер дома. Но, еще раз подчеркну, это НЕ нужно если идти исключительно в рамках курса.

На данный момент я прошел 2 курса из 5 в рамках специализации и надо признать, понимание того “что такое DL” появилось и начинает обретать какие-то форму. Возможно, я изменю свое мнение о специализации когда дойду до конца, но пока что всё просто великолепно

С++ и надежный, безопасный код

Довольно часто можно встретить высказывания о том, что C++ и надежный, безопасный и легко поддерживаемых код несовместимы. Особенно часто такими высказываниями грешат адепты управляемых языков и довольно долгое время это было в общем-то небезосновательно. Сам я остро почувствовал данную проблему с C++ после того как основательно погрузился в Go, где благодаря большому количеству утилит для автоматического анализа кода, удается добиться приличного уровня кодовой базы проекта с относительно не высокими временными затратами. К счастью, в мире C++ в последние годы ситуация сильно изменилась и получить сопоставимый по качеству уровень стало возможно с приблизительно сопоставимыми усилиями.

Единый стиль форматирования

Казалось бы, единый стиль форматирования проекта – это мелочь, но ведь не просто так почти каждая уважающая себя компания имеет увесистый документ “BestCompanyInTheWorld Coding Standard”, который как минимум на половину состоит из того, как код должен быть отформатирован. При этом, код в BestCompanyInTheWorld почти наверняка отформатирован вразнобой, так как применение стандарта контролируется в лучшем случае в процессе ревью, но кто же помнит все эти хитросплетения пробелов и скобок? Работая с Go я впервые оценил прелесть того, что весь код включая сторонние библиотеки действительно написан в едином стиле, так как существует единое правило форматирования для всего языка. Эта казалось бы мелочь очень сильно упрощает работу над чужой кодовой базой и в случае с Go легко достигается автоматически при помощи доступных по умолчанию форматтеров.
Continue reading

Rust и Я

У меня, как наверное и у многих других C++ разработчиков какие-то сложные отношения с Rust. Этот язык вроде как и очень сильно нравится и в то же время всё сложно. На сей раз моя попытка заняться Rust в серьез зашла куда дальше чем обычно (обычно я после нескольких небольших тестиков удовлетворенно забрасывал изучение) – я нашел компанию которой нужны Rust разработчики, связался с ними и взял тестовое задание. Тестовое задание просто восхитительное, не сложное, но помогает понять главное – хочешь ли ты связываться с языком или нет?

На тестовое задание я честно потратил часов 8 и за это время успел заглянуть в tokio, которая, как я понимаю, является образцово-показательной библиотекой для написания асинхронных сетевых приложений. Честно говоря, я до сих пор в состоянии смятении, но точно знаю одно – видеть такое и не дай бог поддерживать на постоянной основе я точно не хочу. К примеру, вот кусок кода, который читает данные из канала и шлет их по TCP:

Box::new(tcp.map(move |stream| {
    let (sink, stream) = stream.framed(Bytes).split();
    pool.execute(stdin.forward(sink).then(|result| {
        if let Err(e) = result {
            panic!("failed to write to socket: {}", e)
        }
        Ok(())
    })).unwrap();
    stream
}).flatten_stream())

Несколькими месяцами раньше я баловался с биндингами к libClang, где было всё читабельно и очевидно, что наводит на мысли, что написать на Rust можно писать как в адекватном и легко поддерживаемом стиле, так и городить write-only код в духе приведенного выше. И надо отметить что в примере выше чувствуется и стиль и задумка. Если в него какое-то время повтыкать (желательно в IDE с навигацией, очень рекомендую IntelliJ Rust), то становится понятно что хотел сказать автор и почему. Только вот “НУ ЗАЧЕМ?!?!” не покидает.

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

Наверное, меня всё равно не отпустит и баловаться с Rust я не перестану. Но вот подаваться на позицию “Rust разработчик” я довольно долгое время точно не буду, сообщество должно наиграться в “zero cost abstractions” для начала

IDE и C++

Я довольно давний поклонник IDE от Jetbrains. Тем же IntelliJ IDEA и PyCharm просто нет сопоставимых альтернатив с точки зрения скорости работы и удобства. Собственно говоря у меня у меня даже подписка на них оформлена из соображений “нравится проект – поддержи финансово”, но вот с CLion что-то пошло не так…

На мой взгляд основная проблема в том, что разработчики и менеджеры продукта пришедшие с платформ .NET и JVM просто не понимают что такое разработка на C/C++. В итоге идёт попытка переложить модель разработки с той же Java на C++. В крайне случае у меня сложилось именно такое ощущение как после личного общения с JetBrain-овцами на CppCon, так и после вчерашнего диалога в Twitter.

Собственно, проблема и непонимание состоит в том, что команда CLion упорно хочет видеть “проектную модель”. Я не знаю чем это вызвано, толи наличием libClang под капотом, толи архитектурными проблемами собственного парсера, но без реальной проектной модели CLion превращается в тыкву. Хотя, он даже и с реальной проектной моделью иногда превращается в тыкву, например спотыкаясь на сгенерированном через Protobuf коде.

К сожалению, такой подход не может работать в мире C++ на многих проектах сложнее Hello World. За исключением счастливчиков, которым доступно писать всё в Visual Studio, у разработчиков огромный зоопарк используемых редакторов и причина у этого довольно грустная, в теории CLion и должен был исправить эту ситуацию. Так вот, мои коллеги пишут в Sublime, Emacs, Vim, Eclipce CDT, Studio Code и многих других редакторах по большому счету потому, что все они практически одинаково плохи в роли C++ IDE. Ну может за исключением Emacs/Vim, за счёт его интеграции с Globals/CTags и Eclipse, за счёт наличия грамотно реализованного парсера C++. Но в Emacs/Vim ещё нужно уметь писать – это свой отдельный мир, а Eclipse даже на Xeon-ах с горой памяти на борту умудряется тормозить.

Если же говорить о проектной модели и почему привязка к ней делает редактор не пригодным к промышленному использованию – то её часто просто нет. К примеру на данный момент я периодически переключаюсь между несколькими проектами: один на базе CMake, второй на некой дикой смеси Make, CMake и SCons обвешанной sh/bat скриптами сверху. Так же я иногда заглядываю в проекты которые представляют из себя кучу файлов просто “для консультации”. Таким образом, в теории, я мог бы писать 1 проект из всех над которыми работаю в CLion, но есть ли в этом хоть какой-то смысл если мне нужно писать и другие проекты и иметь пусть приблизительную, но быструю навигацию по коду и хоть какую-то автоподстановку? По мне так никакого, так как привыкать к особенностям 2-х редакторов куда как менее удобно нежели всегда работать в одном. Жаль только надежда на то, что на менеджеров продукта CLion сойдет понимание проблемы угасла.

Go и контроль качества проекта

А начну я с громкого заявления: Go – это один из самых лучших языков программирования для командной разработки на данный момент. И дело тут ни в простоте языка, ни в простоте инфраструктуры, хотя и эти пункты очень важны. Основная же причина для такого заявления кроется в инструментах для статического анализа кода. При этом я не знаю ни одного другого языка, который позволял бы провести такой дотошный статический анализ по всем направлениям, начиная от стилистики кода, заканчивая потенциально опасными конструкциями и обработкой ошибок.

Основная проблема в командной разработке – разнородность уровня и, как следствие, разное качество производимого командой кода. Ревью, безусловно, позволяют в той или иной степени сгладить последствия разнородности и даже подтянуть уровень разработчиков, но работают они не так хорошо как хотелось бы. Кому-то может быть лень, кто-то устал, кто-то не заметил и в репозитории оказывается нечто, которому там не место. Можно ли это хоть как-то исправить в C++? Нет, нельзя. Можно ли эту проблему минимизировать в Go? Довольно легко, что я вчера и сделал.

В Git есть замечательный механизм хуков, которые отрабатывают в зависимости от внутренних событий. Меня интересовал pre-commit хук, позволяющий заблокировать коммит по результату выполнения скрипта. Использование этого хука купе с Go Meta Linter, агрегатором линтеров для Go, позволяет автоматически заблокировать коммит до исправления ошибок.

#!/bin/sh

if ! [ -x "$(command -v gometalinter)" ]; then
echo 'Error: gometalinter is not installed. Please install it first and execute `gometalinter -i`'
exit 1
fi

lint_errors=$(gometalinter ./... --vendor -j 5)
if [[ $? != 0 ]]; then
echo 'Error: gometalinter checks had failed. Please execute `gometalinter ./... --vendor` first and fix ALL issues'
exit 1
fi

Дело остается за малым – поместить файл с хуком в директорию .git/hooks проекта, что я сделал при помощи нашего сборочного скрипта. Да, нам пришлось написать такой скрипт поверх стандартных Go команд типа go build так как есть пре- и пост- шаги которые необходимо предпринять в процессе сборки, а никакого CMake-подобного механизма в Go нет. Хотя, что уж тут, поверх CMake писать аналогичный скрипт тоже приходится.

CppCon 2017

oznor

Дни на CppCon 2017 пролетели очень быстро и незаметно. Конференция действительно потрясающая и на неё однозначно стоит ехать, если есть такая возможность, любому кто любит C++ и хочет писать качественный код. Желающих выступить на конференции так много, что практически всё время параллельно идут около 5 сессий. К сожалению, это приводит к тому, что иногда приходится жертвовать интересным выступлением в пользу еще более интересного. Именно так я пропустил выступление Гора Нишанова, посвященное корутинам, которое теперь придется смотреть на Ютубе. Вообще, казалось бы, можно все то же самое посмотреть на Ютубе или 9-ом канале… но это не то, не создается того ощущения погружения в тему, как от личного присутствия, живого общения и разбора материалов в течении 5 дней. Теперь еще несколько месяцев ковыряться, думать и систематизировать услышанное.

Очень порадовал и удивил тот факт, что со всех сторон на конференции была слышна русская речь. Встретил много бывших коллег из Лаборатории Касперского, познакомился с народом из JetBrains. На конференции была великолепная подборка книг по C++, парой из которых я обзавелся: Advanced Metaprogramming in Classic C++ и C++ Templates the Complete Guide. Со второй книгой вообще вышло занятно: после того, как её порекомендовал Саттер на своем выступлении, за ней выстроилась довольно большая очередь, брали по несколько экземпляров

Назвать одно самое-самое выступление в этот раз я не могу, так как на мой взгляд их два:

Еще 5 докладов, уже без вау-эффекта, но невероятно интересные и полезные:

  • Faster Delivery of Large C/C++ Projects with Conan Package Manager and Efficient Continuous Integration. Если вы работаете не в продуктовой команде, а в SDK, то это то, что нужно обязательно смотреть! Если ничего нового для себя не открыли, то у вас просто невероятно продвинутая команда.
  • C++17 ParallelSTL: A Standardization Experience Report for CPU and GPU on SYCL. Тут вроде всё из названия понятно, презентация обзорная, скорее конспект для дальнейшего самостоятельного изучения.
  • C++ as a “Live at Head” Language. Презентация наделала много шуму, в принципе, оправданно… но только если вы работаете в компании размера Гугл. Я даже для Автодеска полезность Abseil с трудом могу оценить как положительную, но сама идея интересная, стоит послушать как минимум для того, чтобы осознать масштаб проблем, с которыми приходится сталкиваться другим.
  • A Tour of Deep Learning With C++. Для того, кто занимается машинным обучением, эта презентация, скорее всего, покажется банальностью уровня “давайте я вам расскажу зачем нужны умные указатели”. А вот мне, далекому от этой области человеку, было невероятно интересно. Новая, интересная предметная область вкупе с любимым языком – что может быть лучше?!
  • Postmodern immutable data structures. Сюда я даже думал не идти изначально, но был сильно-сильно неправ. Невероятно интересная презентация про иммутабельные структуры данных в мире C++.

Довольно хорошие доклады, не пожалел что сходил:

  • Boost Your Program’s Health by Adding Fibers to Your Coroutine. Так как я имею довольно поверхностное представление о fiber-ах и сoroutine-ах, мне было интересно и полезно.
  • Tools and Techniques To Stay Up-to-date With Modern C++. Мысли о том, как стоит учиться программировать на C++, полезные источники с информацией и т.п. Внезапно оказалось интересно.
  • Curiously Recurring Bug Patterns in C++ at Facebook. Самые злобные грабли C++ по версии Facebook. Сделать конспект и раздавать новичкам
  • Unbolting the Compiler’s Lid: What Has My Compiler Done for Me Lately? Доклад от автора широкоизвестного в узких кругах Compiler Explorer. Немного про чудеса оптимизации компилятора, в особенности Clang, и немного про архитектуру самого сайта.

Посмотрел на Ютуб, понравилось:

  • A modern formatting library for C++. Библиотеки форматирования текста, надо признать, довольно больная тема для C++. Рассказ о fmt из первых рук.
  • Deconstructing the OS: The devil’s In the side effects. А тут уже автор bootOS, рассказывает о том, что лежит в основе разработки.
  • Using Modern CMake Patterns to Enforce a Good Modular Design. Многие разработчики не любят или боятся CMake. Да, синтаксис CMake-скриптов ужасен, но плюсы несомненны, и если его “правильно готовить”, то инструмент начинает восприниматься сильно иначе.
  • Fuzz or lose…. Стыдно сказать, но до этого выступления я не задумывался о фаззинге как таковом. Тем кто в таком же положении, очень рекомендую глянуть.
  • 10 Core Guidelines You Need to Start Using Now. Название тут говорит само за себя. Человек, который хотя бы краем глаза заглядывал в C++ Core Guidelines, из этого выступление много нового не подчерпнет, но в целом полезно.
  • Undefined Behavior in 2017 и вторая часть выступления посвящены проделкам оптимизатора на -O2. Интересно и познавательно, хотя докладчик несколько тараторит.

Внезапно не понравились доклады от Бьёрна Страуструпа и Энтони Уильямса: очень тягомотно и, как мне кажется, довольно бесполезно. При том, какие у них отличные книги, я ожидал большего. Если уж говорить про разочарования от конференции, я бы добавил еще два: ни Майерс, ни Александреску на конференции снова не появились, а так хотелось послушать их вживую.

А еще меня разочаровало то, что на конференции не было ни одного доклада или стенда про статический анализ кода, хотя на мой взгляд, в современном C++ это одна из самых серьезных проблем. Гора отладчиков, множество приложений для разбора крэш-дампов, доклады про отладку и борьбу с багами… и чуть-чуть санитарайзеров времени исполнения, а так же практически полное отсутствие доступных средств для статического анализа кода и поиска уязвимостей. И при этом, по моим наблюдениям, эта ситуация вообще мало кого заботит

P.S. Линки на доклады добавлю по мере их появления.