Пятнадцать тысяч триста девяносто долларов в год разделяли две медианные зарплаты в посте, который аналитик данных Stack Overflow Дэвид Робинсон опубликовал в середине июня 2017 года. Если бы так различались сеньоры и джуны или Калифорния и Индия, пост прошел бы незамеченным, потому что такими графиками интернет завален доверху. Шум поднялся из-за признака, по которому разработчиков разложили на две кучки: чем они делают отступы в коде, пробелами или табуляцией.

Новость разлетелась от The Register до BBC, комментаторы привычно разбились на два лагеря, а несколько человек с Pandas наперевес попробовали этот результат развалить. Дальше пойдет речь как раз о той части истории, где его разваливали, и о том, почему ни у кого толком не вышло.

Откуда взялись цифры

Stack Overflow каждый год проводит большой опрос разработчиков, и в 2017-м в нем поучаствовали больше 64 тысяч человек. Вместе с отчетом компания выложила сырые ответы, и Робинсон отобрал из них тех, кто считает себя профессиональным разработчиком (студентов и бывших программистов он отсеял) и ответил на вопрос про отступы. Таких набралось 28 657, из них 40,7% выбрали табы, 41,8% пробелы, а оставшиеся 17,5% используют и то и другое; зарплату указали 12 426 человек.

Картинка получилась такая: медиана у пробельщиков вышла 59 140 долларов, у табуляторов 43 750. Если поделить одно на другое, выходит примерно 1,35, то есть сырой разрыв около 35%. Тех, кто ответил «и то и другое», Робинсон из большей части анализа убрал, потому что по зарплатам они практически не отличались от любителей табов.

Ищите переменную

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

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

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

Тогда в ход пошла линейная регрессия, куда загрузили все, что по идее влияет на зарплату, включая участие в опенсорсе. Модель оценила, что пробелы вместо табов связаны с зарплатой выше на 8,6%, доверительный интервал от 6 до 10,4%, p-value меньше 10⁻¹⁰. Предсказывали при этом логарифм зарплаты, чтобы получить вклад каждого фактора в процентах, и в пересчете на стаж пробелы оказались эквивалентны прибавке в 2,4 года опыта.

Тут полезно прикинуть порядок. Сырой разрыв в 35% после всех поправок съежился до 8,6%, то есть примерно три четверти разницы объяснили страна, стаж и прочие скучные вещи (сравнение грубое, проценты из логарифмической модели и проценты от отношения медиан сопоставимы с натяжкой, но для порядка годится). Остаток при этом никуда не делся, и с ним уже приходится разбираться всерьез. Если приложить 8,6% к медиане табуляторов, получится около 3 760 долларов в год, а при 250 рабочих днях примерно пятнадцать долларов в день, то есть пробелы ежедневно оплачивают своему владельцу бизнес-ланч.

Самое неприятное для скептиков Робинсон написал сам: он пытался учесть еще много факторов из опроса сверх перечисленных, но эффект почти не уменьшался, а исчезать отказывался совсем.

Табуляция и ее враги

Спор этот старше большинства его участников, и данные к нему подтаскивали и до Робинсона. Опрос Stack Overflow 2015 года показывал перевес в другую сторону: табы тогда предпочитали 45% ответивших, пробелы 33,6%. За два года табы уступили лидерство, что само по себе любопытно, потому что привычки целой профессии так быстро обычно не меняются, зато быстро меняется состав тех, кто заполняет анкеты.

В 2016-м Фелипе Хоффа из Google прогнал через BigQuery миллиард файлов из 400 тысяч топовых репозиториев GitHub, около 14 терабайт кода, и пробелы там встречались куда чаще табов во всех языках, кроме C и Go. С Go все понятно: gofmt форматирует код табами, и обсуждать там нечего, решение один раз приняли за всех. У C тоже есть объяснение, стиль кодирования ядра Linux предпочитает табы, причем шириной в восемь символов, а за ядром тянется изрядная часть сишной экосистемы. Записать мейнтейнеров ядра в низкооплачиваемые как-то язык не поворачивается, так что табы явно не приговор.

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

Второе мнение

Робинсон в конце поста предложил статистикам и аналитикам скачать сырые данные и покопаться в них самостоятельно, и желающие нашлись.

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

Автор блога Data Skeptic подошел к делу еще осторожнее. Он напомнил, что опрос никто не проектировал под проверку такого заголовка, сам поискал конфаундер и не нашел в анкете ничего похожего на разумное объяснение, а вывод сделал такой: в опросе просто не хватило вопроса, который объяснил бы разрыв лучше. С этим трудно спорить, остается лишь угадать, какой вопрос стоило задать.

Что спрашивали и что услышали

Вопрос в анкете был коротким: табы или пробелы. Между тем в большинстве современных редакторов клавиша Tab давно вставляет четыре пробела (или два, смотря по настройкам), и человек может годами жать Tab, так ни разу и не создав в файле символ табуляции. Что такой человек ответит в анкете, зависит от того, знает ли он, что лежит у него в файлах. Мой редактор так настроен с незапамятных времен, и на этот вопрос я бы ответила «пробелы», хотя пробел ради отступа не нажимала, кажется, ни разу в жизни.

Отсюда первая гипотеза: ответ «пробелы» отчасти измеряет, насколько человек в курсе устройства собственных инструментов. Тот, кто пишет «табы», нажимая Tab, мог попросту перепутать клавишу с символом, и такая неосведомленность вполне может коррелировать с уровнем, который годы стажа не ловят. Тут и всплывают те самые «и то и другое», которые по зарплатам слились с табуляторами. В гипотезу они укладываются аккуратно, ведь смесь табов и пробелов в файлах обычно заводится там, где за форматированием никто не следит.

Вторая гипотеза мне кажется сильнее, и касается она того, кто вообще принимает решение. Во многих проектах его давно принимает конфиг. PEP 8 велит отступать четырьмя пробелами, black форматирует пробелами без вариантов, Prettier по умолчанию тоже ставит пробелы, а Python 3 падает с TabError, если табы и пробелы перемешаны неоднозначно; с другой стороны баррикады gofmt и стиль ядра выбирают табы. Получается, что для огромной части разработчиков ответ на вопрос задан проектом, линтером и CI, который завернет пулл-реквест с неправильным отступом. Такая инфраструктура (форматтер, обязательное ревью) чаще встречается в компаниях с выстроенным инженерным процессом, а они и платят обычно больше. Размер компании Робинсон учитывал, но размер и зрелость процессов совпадают плохо: стартап из сорока человек с жестким CI и корпорация на пять тысяч сотрудников с двадцатилетним легаси попадут в разные корзины по размеру и в перепутанные корзины по культуре.

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

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

Отступать некуда

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

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