Обсуждая с друзьями и коллегами языки программирования, я осознал, как приблизительно должны выглядеть такие разговоры. В этой статье я расскажу об этом, надеюсь, это окажется для вас полезным.
▍ Что мы на самом деле сравниваем, сравнивая языки программирования?
Придя в гости к другу, я увидел, что на нём надета футболка Golang. Он сказал, что любит Golang, я ответил, что мне нравится футболка, а сам язык чуть меньше. Ему понравилась мысль «обсудить это позже», и после ужина мы уселись на диванах и приступили к разговору. Я хотел поговорить о сборщике мусора (1, 2), о том, что горутины/каналы — это удобная абстракция, но я предпочитаю абстракции BEAM, потому что они позволяют использовать супервайзоры, обсудить очень свободное отношение Golang к корректности, но… он не горел желанием говорить обо всём этом. Мой друг с восторгом рассказывал о том, что ему нравится, что «разработчики на Go знают, что достаточно одного цикла for
. Кто-то притащил в мою компанию Scala, и мне очень не нравится смена образа мышления».
Разговор был бесплодным, и мы оба ощущали, что собеседник не ценит то, что было важно другому. Когда люди говорят о языках, которые им нравятся или не нравятся, я группирую аспекты обсуждения на три большие категории, которые назову почва, поверхность и атмосфера:
Почва — это свойства выполняемого кода на этом языке. Большинство этих свойств связано с самим процессом выполнения кода (основные характеристики производительности, «двоичный ли код или интерпретируется VM», планировщик и/или взаимоотношения с многоядерностью/параллелизмом, сборщик мусора), но в более широком смысле это «всё, что не связано с редактированием кода и не касается напрямую „сообщества“». Сюда я включаю время сборки и свойства инструментария. То есть в обсуждении Golang я говорил о «почве»; также к ней относится и следующее:
- То, что код на Python часто в сотни или тысячи раз медленнее, чем на других языках.
- Сравнение языков с долгим (Scala, Kotlin) и коротким (Golang) временем компиляции.
- Наличие в языке дженериков, способ их реализации: type erasure,
мономорфизация или что-то другое? - У Erlang есть предварительный планировщик, а внутренний способ работы iolists + конкатенации строк позволяют создать шаблон рока.
Поверхность — это то, о чём обычно думают люди при сравнении языков: их фичи! Исходный код! Наличие вашей любимой конструкции цикла (или его отсутствие по принципу «нужен только цикл for
»). Синтаксис, FFI, поддерживаемые регулярные выражения, семантика конкретной системы объектов. Другие примеры:
- Less/Sass и CoffeeScript были чисто «поверхностными» разработками: они не про базовые возможности; похоже, их расширяют чистыми «исправлениями» неоптимальных поверхностей.
- «Ruby гораздо лучше Java! Сравни, как открывается файл кодом на Java (показывает тридцать строк) и на Ruby! (две строки)»
- Привлекательность стеков MERN и MEAN в основном вызвана тем, что «всё это JavaScript/JSON», то есть можно уменьшить объём изучаемой «поверхности».
- Сильные реакции с обеих сторон на CSS-in-JS и Tailwind кажутся мне «поверхностными», хотя и могут иметь влияние на «почву».
И, наконец, атмосфера: это всё, что связано не с языком или кодом, а с сообществом. Вакансии, ответы на Stack Overflow, количество звёзд в популярных проектах на GitHub, количество пакетов в их репозиториях. Я зайду немного дальше и включу сюда влияние этого сообщества, например, параметр «есть ли у языка плагин для VSCode и языковой сервер» кажется мне более близким к атмосфере, чем к чему-то другому:
- Большинство разговоров о том, что «можно с лёгкостью нанять разработчиков на React», совершенно отделено от технических обсуждений React как фреймворка. То же относится к Java, Python, Ruby, JS…
- Основная часть культуры языка: в Elm и Clojure существует примерно такое отношение: «если Эван/Рич решил, что вам это не нужно, то, возможно, вы ошибаетесь?». Golang говорил вам, что вы глупы и ошибаетесь о необходимости дженериков, а спустя десяток лет реализовал их. У Scala есть весь этот глупый драматизм.
Небольшое примечание об исключениях: как сказал Хиллел, «все таксономии поломаны, точка». Здесь «инструментарий» соответствует всем трём категориям: обычно существование инструментария (например, языкового сервера) — это дело сообщества, однако свойства инструментария сильно связаны с «почвой», зависят от решений главных разработчиков и существенно влияют на повседневную работу с языком (например, время компиляции) или даже после развёртывания.
Среди прочего есть «статические типы»… Мне кажется, что это поверхность, но кто-то может сказать, что это почва.
Учитывая всё вышесказанное, у меня возникли некоторые наблюдения.
Эти 18 логотипов — компоненты «начального проекта» из «It's time to Just Ship» «эпичного стека». Но вы, конечно же, можете продолжать утверждать, что это проще, чем «просто использовать TypeScript».
▍ Обсуждения становятся менее конкретными, когда движутся вверх
Мне кажется, при обсуждении свойств языков «почва» часто достаточно конкретна
(например, общая производительность, сравнение безопасности по памяти программ на Rust и C++), «поверхность» больше завязана на ощущения, но имеет обоснования в реальности (BEAM-языки могут иметь супервайзоры благодаря OTP и неизменяемости, у программ на Go их быть не может; но значение этого для безопасности конкретной программы и влияние на бизнес сложно измерить). Вопросы «атмосферы» же крайне завязаны на чувствах: «невозможно нанять разработчиков на функциональных языках!» (А вы пробовали? Почти у каждой известной мне фирмы, занимающейся функциональным программированием, нет проблем с поиском его любителей, а благодаря парадоксу Python они часто довольно неплохи…) «Нет поддержки библиотек!» (В большинстве репозиториев есть потрясающая коллекция репозиториев, что конкретно вам нужно?)
Я не говорю, что вопросы из области атмосферы не важны, просто влияние этих аспектов замерить сложнее всего. Можно сказать, например, что в npm есть n пакетов, а в Cargo их m, но что же конкретно значат эти числа в рамках задач долговременной и эффективной для бизнеса кодовой базы? По таким источникам, как HackerRank, Leetcode, Greenhouse или GitHub Jobs можно сравнить, сколько есть разработчиков на Java и на Scala, но как эти числа соотносятся с поиском отличных специалистов для вашей конкретной компании? Вы наймёте в этом году тридцать тысяч человек? Если это не проблема исключительно с поиском «гребцов» (а для большинства компаний сложнее всего найти нужных гребцов), то почему это так важно?
И это напрягает меня, потому что мне кажется, что…
▍ Сегодня большинство думает, что нужно «любой ценой обеспечить атмосферу!»
Моя карьера в разработке полностью установилась в нулевых. Это время было совсем другим: люди гораздо больше экспериментировали с выбором технологий! Twitter страдал с Ruby on Rails, поэтому решил попробовать новый многообещающий язык: Scala. Heroku вложилась в Erlang, также поступил и небольшой мессенджер под названием WhatsApp. В 2006 году ITA Software получила $100 миллионов финансирования, несмотря на то, что работала уже десять лет и писала на Common Lisp (она была продана Google в 2010 году за $700 миллионов. В те времена это была впечатляющая сумма; Instagram* был куплен за рекордный $1 миллиард только в 2012 году).
Сегодня мы боимся разрабатывать на всём, кроме JavaScript, Java, Python или Ruby. Такое ощущение, что через десять лет останется один JS. Все мы уже прочитали превосходную статью Маккинли о «жетонах инновации» и решили избегать провалов, вместо того, чтобы ставить рекорды. Руководители разработки стремятся избегать страхов и рисков, а не к оптимизму и вере в свою команду.
Куда делись все хакеры?
Да, на использование экзотической технологии, возможно, придётся потратить жетон инновации, но как и многие вещи в жизни, жетоны инновации — полностью выдуманная концепция; это как говорить о «жетонах любви», которые ты выдаёшь своей супруге за год. Я хотел бы предложить другой взгляд: вероятно, лучший способ уменьшения количества жетонов инновации — иметь плохое воображение. Представьте, что вам дали кошель с жетонами после выбора технологического стека. Выбор отличной подходящей технологии, не относящейся к Большой Четвёрке, требует траты жетона, но заглянув в кошель, вы видите, что там их осталось всего шесть; если ты выберешь скучную технологию, то не тратишь жетон сразу же, но в кошеле их осталось всего три.
Здесь мы видим, как счастливые разработчики тратят жетоны инновации, подаренные доверяющим им CTO.
▍ Сложно ли изучить язык?…
Люди часто говорят о великолепных командах разработчиков (и о командах, которые бы они хотели создать и работать с ними) в достаточно возвышенной форме. Поднимите руку, если разделяете следующие утверждения:
- Я предпочитаю работать с превосходным разработчиком ПО, не привязывающим свою личность к конкретному языку или технологии (то есть я бы предпочёл отличного хакера тому, кто идентифицирует себя как «разработчика на Ruby» или «разработчика на JS»).
- Я предпочитаю иметь коллег, понимающих концепции, лежащие в основе технологий, и не приравнивающие технологии к целым стекам (то есть «базы данных» для этого человека не означают просто «Oracle» или «Mongo», он понимает, что BOM и DOM — это не то же, что и «Svelte»).
- Человек, с которым я хочу быть в команде, познакомился со множеством технологий, может объяснить их плюсы и минусы, способен понимать новые технологии и работать с ними.
Теоретически, каждый опрошенный согласился бы с этими нейтрально изложенными положительными идеалами. Однако когда дело доходит до практикования этих идеалов или голосования за них, результаты не совпадают с теоретическими. Оказывается, многим командам разработчиков вполне нормально нанимать «Java-разработчиков», пугающихся кода на Python, людей, неспособных объяснить различия между разными технологическими стеками, и людей, которые вместо того, чтобы потратить неделю на совершенствование своих навыков, будут жаловаться и возражать, предпочитая продолжать годами использовать неоптимальные решения.
Возникает интересный вопрос: почему у людей есть идеалы, которые забываются, когда приходится выбирать, голосуя действием? Я коснусь этого чуть ниже (на примере технологий). Но на секунду задумайтесь о своей идеальной команде разработчиков, а потом отрефлексируйте ту команду, которую вы создали или собираете; подумайте, почему и в чём они могут отличаться. «Воевать придётся не с той армией, которую хочешь, а с той, которая у тебя есть». Это верно, но почему?! Вы создали и продолжаете создавать эту команду!
Несмотря на весь смысл защищаемого мной в этом посте, могу сказать, что, по моему мнению, для достижения совершенства в языке требуются годы. Дело не только в синтаксисе, но и в почве с атмосферой: распространённых потоках багов и способах их выявления, выстрелах в ногу, инструментарии, экосистеме библиотек, культуре. У меня есть множество советов по изучению новых языков, и в особенности странных; можно заметить, что даже пост с советами начинается с огромной просьбы быть аккуратными при внедрении их в своей компании.
Так почему же я при всём этом призываю экспериментировать и рисковать? Потому что я считаю, что при наличии опытных менторов разработчику требуется несколько дней, возможно, неделя-две, чтобы освоить новый язык до адекватного уровня, особенно если есть обязательный code review. Это заявление может показаться абсурдным, однако, по моим наблюдениям…
▍ …большинство людей мало знает о выбираемых всеми Скучных Стеках. Более того, они не обобщают эти знания!
Дело в том, что большинство Разработчиков на Python™, с которыми мне доводилось работать, даже не знают особо много о Python. Они не могут чётко обосновать, когда нужно использовать abc
вместо того, чтобы просто наследовать от object
, или почему стоит предпочесть namedtuple
вместо dataclasses
. Они не знают, что import x.y.z
импортирует x/__init__.py
и x/y/__init__.py
и x/y/z.py
(или x/y/z/__init__.py
). Они не смогут рассказать, что такое GIL или почему не нужно писать def send_emails(list_of_recipients, bccs=[]):
. В эту игру особенно забавно играть, когда разговариваешь о JavaScript.
В знаниях об используемых разработчиками инструментах есть огромные пробелы. И это нормально. Но в «атмосферном» аргументе типа «проще нанять людей с опытом [X]» проблема заключается в том, что, по моим наблюдениям, этот опыт необязательно так уж глубок, и что люди, считающие, что нанимают опытных пользователей этих языков, врут себе. Многих людей, с которыми я поработал в семи компаниях, лучше всего можно описать как «адекватных».
Обучение не бесплатно, однако стоимость фиксирована на одного разработчика, а при наличии опытных менторов она, вероятно, меньше, чем вы думаете. Мне кажется крайне маловероятным, что фиксированная стоимость 2-4 дней обучения больше, чем затрат на сверхлинейное время сборки + работы с тысячами запросов Sidekiq или Celery, когда можно было просто выбрать Go.
Ещё один аспект: эти технологии на самом деле не стандартизируются. Я поработал в четырёх компаниях, использующих Flask; ни одна из них не имела похожей структуры приложений и не использовала одинаковые плагины (ура, микрофреймворки!). «Просто используйте React», но долгое время означало «с менеджером состояний или без него (Redux)», потом это значило «с хуками или без хуков», затем это было «CSS-in-JS или что-то другое (и/или BEM, а сейчас Tailwind)». Каждая компания, в которой я работал, создавала свою собственную дизайн-систему и/или библиотеку компонентов, имевшую собственный странный формат вызовов. Ни в какой из компаний, в которых я работал с React, тестирование не выполнялось одинаково, а знания о конвейере ресурсов или опциях транспиляции JS нельзя было перенести на проекты других компаний.
Когда умирает компания, писавшая на Python: «стартапы — это сложно». Когда умирает компания, писавшая на Erlang: «Erlang — это сложно».
▍ Почему мы находимся в ситуации «атмосфера любой ценой»?
Вероятно, по этой теме можно написать несколько отдельных постов, так что я просто перечислю в качестве провокации основные причины:
Десятилетие практически нулевых ставок в США и глупые деньги заставили технологический сектор отупеть; развитие «технологической компании с венчурным финансированием» превратилось в работу по методичке. Когда-то стартапы были Диким Западом, а от венчурных капиталов ожидалось идти до нуля, потому что ставки были тупыми и крупными. В то время приветствовались энтузиасты с горящими глазами. В дальнейшем «венчурный капитал» сохранил своё название и попытался сохранить бренд Крупных Ставок, но на практике стал ближе к обычному инвестированию, а технологические компании с поддержкой венчурного капитала разработали методичку, по которой ожидался регулярный доход. Творящих в гаражах гениев заменили скучные профессионалы. Это привело к избеганию рисков и фетишизации Скуки.
Вливание культуры традиционного бизнеса и капитала, которая традиционно рассчитывала на более выхолощенное, скучное и прозаичное
Самым главным становится культура управления и руководства разработкой; люди превращаются в стадо, служащее «Скуке». Последнее десятилетие мы наблюдаем за ростом класса технологического менеджмента и его идейных вдохновителей. Руководители из других областей справляются не очень хорошо, как и разработчики, которых повысили до руководителей. Необходимо было нечто сокрытое, Третий Элемент. Многие влиятельные люди вещают уверенно, хотя нарративы ещё не устоялись; любимой темой для споров в этом сообществе стали Manager README (за, против). Несмотря на множество Уверенных Профессиональных Голосов, по моим наблюдениям, руководство разработкой на практике оказывается непростым путём (вот превосходная статья Брандура по теме). Я думаю, что иногда «Скука» — это неплохая стратегия, но почему-то теперь её считают Единственно Верной, а класс менеджеров покорно двинулся по этому пути.
Самый новый и простой способ Бояться Неизвестности. В утверждении «затраты на атмосферу/преимущества атмосферы — это самое главное» забавнее всего то, что эти аспекты сложнее всего превратить в конкретику: кажется, в конце двухтысячных споры о «поверхности» были столь же безумно неопределёнными. Функциональные программисты без доказательств настаивали, что их программы Более Корректны. Люди, любящие динамическую типизацию, без доказательств настаивали, что их программы не менее корректны. Наверно, мы играли в ту же игру аппелирования к чувствам, но до десятилетия роста популярности обучения в Computer Science, буткэмпов, Stack Overflow, GitHub и прогресса в редактировании текста (языковые серверы, монокультура VSCode) мы не могли говорить об атмосфере, поэтому забирались в спорах настолько высоко, насколько это было возможно.
Я хочу сказать, что всё это способ справиться с ужасом руководства командой разработчиков. Мы находимся в море с результатами множества наших решений, и хотя мы почти уверены, как определять местоположение по звёздам, небо уже вторую неделю затянуто тучами; мы начинаем становиться суеверными. Мы больше склонны верить Уверенному Голосу Спокойного Профессионала. Мы стремимся меньше рисковать в том, что можем контролировать, потому что слишком боимся того, что контролировать не можем.
У меня есть ещё много мыслей на эту тему (существует миллион способов запороть внедрение экзотической технологии и, несмотря на всё вышесказанное, большинству людей не стоит за них браться; кроме того, «скучные технологии» спасли кучу компаний. Но я ведь обещал провокацию!). Выводы:
- Когда вы говорите с кем-то о технологиях, определитесь: это разговор о почве, поверхности или атмосфере? Вместе решите, о чём хотите говорить, и об ограничениях выбранного слоя, потому что иначе может получиться, что вы говорите о разном.
- Пересмотрите своё отношение к тому, что вы считаете «границами» между технологиями. Означает ли использование React, что React просто должен быть повсюду? Если ваша команда, например, использует Retool, разве он тоже не является программируемым интерфейсом с различными прикрученными технологиями для доступа к хранилищам данных в продакшене? Почему добавить Retool проще, чем Java-сервис? Подумайте, не будет ли слишком обременительным время на изучение Retool?
Ещё один любопытный пример для размышлений: считаете ли вы, что очень опасно создавать нативные телефонные приложения вместо использования React Native, Flutter или LiveView Native? Настолько ли велика разница?
- Выбор технологии в конечном итоге не будет отвечать за успех вашей компании.
Да, он определит маршрут вашего пути и было бы ошибочно утверждать, что технологии не важны. После портирования Bleacher Report перешёл с 150 серверов Ruby на 5 серверов Elixir. Языки с правильно реализованной concurrency наподобие JVM, BEAM и Go не требуют запросов Sidekiq или Celery, а также дополнительных воркеров. Благодаря предварительному планировщику BEAM, у вас не будет проблем «шумного соседа», с которыми Lyft столкнулась при работе с Python, или которые будут напрягать вас в цикле событий Node, но на одном ядре. Обучение не бесплатно (подчеркну ещё раз: оно не бесплатно!), однако некоторые технологии намеренно создавались с расчётом на эффективность, а другие ужасно масштабируются. - Пересмотрите своё отношение к «священным коровам» во всех областях технологий. Микросервисов вполне можно избежать (посмотрите на Blue App FB*, Dropbox, YouTube, Instagram*: все они монолиты). PHP был предметом насмешек в течение всего последнего десятка лет, и тем не менее на его основе создали Slack и Lyft, а Hack по-прежнему управляет Facebook*. «Облака лучше», однако у Stack Overflow гораздо больше данных и трафика, чем у вас, и при этом он работает на девяти машинах. WhatsApp купили за $19 миллиардов, хотя его системы развёртываются вручную на bare metal.
И ещё: если условия подходящие и у команды достаточно энтузиазма, можно работать с технологическим стеком, не связанным с JS, Ruby, Python, Java.
Дополнительно:
- Задайтесь вопросом: чего вы не знаете о своих любимых технологиях? Какие возможности бы открылись, если бы вы это знали?
- Какое обучение или упражнения можете вы и/или ваша команда выполнить, чтобы повысить свои знания об используемых технологических стеках?
Автор:
ru_vds