Нет в программистском фольклоре более короткой дороги к репутации наивного человека, чем фраза "у меня на компе всё работает". Тестировщики слышат её с вежливой гримасой, технички поддержки молча начинают седеть, а продвинутые коллеги проводят достопамятный жест: дарят разработчику наклейку или кружку с этим крылатым изречением. Шутка древняя и одновременно вечно юная, потому что фундаментальная причина её бессмертна: Windows, за плечами которой стоит самое разношёрстное железо и софт в истории человечества, существует не в одной комбинации, а в миллиардах частных вселенных. Обещать свою программу "всем" в таком мире можно только с долей самонадеянности, и история индустрии - это, по большей части, история медленного, болезненного насыщения этого парохода тормозами и предохранителями.

Почему два одинаковых компьютера не одинаковы уже на второй день

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

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

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

Как индустрия болела эту болезнь и что придумала

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

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

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

Фраза-мем и её культурная роль в коллективе разработки

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

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

Хорошие коллективы поддерживают при этом редкостную привычку - инфраструктуру воспроизводимости. Инструкции по сборке, фиксированные версии зависимостей, контейнерные образы и скрипты развёртывания переводят фразу из плоскости шуток в плоскость технической начинки: "у меня работает" может стать "у вас тоже заработает", если окружение перенести вместе с кодом.

Практические решения для тех, кто не хочет сорваться на мель

Полезные выходы из этой общей проблемы можно собрать в деловой свод:

  1. Фиксируйте зависимости рукой администратора: версии библиотек, настройки, конфигурации должны быть описаны и версионируемы вместе с кодом;
  2. Пусть установка будет самодостаточной: программа несёт с собой мир, в котором запускается, а не клянчит его у чужих библиотек;
  3. Тестируйте не только на своей машине: виртуальные стенды, облачные фермы и минимальный набор опорных конфигураций значительно уменьшают поле сюрпризов;
  4. Учите программу рассказывать о себе: журналы, диагностика и диагностические дампы ценнее ста предположений;
  5. Прощайтесь с гордыней быстро: если у пользователя не работает, над программой не стоит светиться надпись "у меня работает".

Пункт пятый стоит выделить как самое глубокое правило. Уверенность в непогрешимости кода вредна не потому, что она неуместна, а потому, что она закрывает тебе глаза на главный урок программирования: программа не существует вне мира, в котором запускается.

Эпоха всеобщего разнообразия и как её измеряли

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

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

Урок для любого, кто делится своей программой

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

Небольшая мемориальная доска для крылатой фразы

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

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

Где маячит хороший конец этой истории.

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

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

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