Для чего нужны ограничения
Локдаун ни при чем. Зачем нужны ограничения и QR-коды, если они не имеют отношения к победе над очередной волной ковида
Данное сообщение (материал) создано и (или) распространено иностранным средством массовой информации, выполняющим функции иностранного агента, и (или) российским юридическим лицом, выполняющим функции иностранного агента
ГКБ-24 в Москве. Фото: Komsomolskaya Pravda / Global Look Press
Четвёртая волна эпидемии коронавируса — пока не пришел омикрон — идет на спад, больницы освобождаются, заболеваемость снижается, местами регионы даже ослабляют ограничения. А принятие закона о QR-кодах на федеральном уровне, ещё недавно выглядевшее неизбежным, вдруг забуксовало — на фоне улучшения эпидемиологической ситуации жёсткие меры начинают казаться избыточными. Выглядит так, будто нерабочие дни, объявленные в начале ноября, спасли безнадёжную ситуацию и преломили тренд.
По крайней мере, нам так говорят.
О том, что нерабочие дни помогли сбить заболеваемость, заявляли и федеральные, и региональные чиновники. Об этом говорили премьер-министр Михаил Мишустин, министр здравоохранения Михаил Мурашко, глава Роспотребнадзора Анна Попова, вице-премьер Татьяна Голикова. Об этом говорили и главы регионов: нерабочие дни сбили волну в Москве, в Петербурге, в Самарской области, в Курской области, в Башкирии и далее по списку. Ситуация после локдауна (который нельзя называть локдауном, как заявила Попова) улучшилась в большинстве регионов.
Всё сложилось чрезвычайно удобно. Чиновники изначально заверяли, что нерабочие дни окажутся короткими — так и вышло. Они обещали, что нерабочие дни помогут разорвать цепочки заболеваемости — и это произошло. Говорили, что это происходит «моментально» — и не обманули.
И везде звучит единым лейтмотивом: как мы вовремя приняли меры, как мы правильно отреагировали — именно это помогло нам сбить волну.
Однако вовремя ли? И это ли именно помогло?
Все эти заявления работают, если не всматриваться в официальную статистику выявленных случаев, которую публикует оперштаб, и не задумываться над её противоречиями. Стоит всмотреться — сразу возникают вопросы, неудобные, много.
Например, сразу становится ясно, что в реальном мире течение эпидемии как будто не зависит от действий чиновников и подчиняется своим законам.
Иначе как объяснить, что в Чувашии нерабочие дни как будто сбили волну (удачно вышедшую на пик 31 октября и начавшую спадать 10 ноября), а в соседнем Татарстане только за ноябрьский локдаун случаи выросли на треть и продолжили расти и бить рекорды вплоть до 17 ноября? Притом что и там, и там заболеваемость одинаково пошла в рост уже в конце сентября.
Почему нерабочие дни сработали в Красноярском крае и сдержали заболеваемость, а в соседней Иркутской области словно никак не повлияли на ситуацию?
Как так выходит, что в Москве инкубационный период «дельты», по версии оперштаба, составляет 5 дней, а в Челябинской области — 2 недели (в реальности медиана — 4,3 дня)? Безусловно, такая разница прекрасно объясняет, почему Москве хватило 11 нерабочих дней, чтобы сбить волну, а Челябинской области, которая продлевала локдаун, не хватило и 16 дней — заболеваемость здесь продолжает непрерывно расти уже два месяца. Но всё же?
Желание чиновников, федеральных и региональных, приписать себе успехи более чем понятно. Однако на самом деле ноябрьский локдаун к спаду заболеваемости, который мы наблюдаем, отношения не имеет.
В действительности естественный пик волны пришёлся на октябрь, а локдаун стал лишь запоздалой реакцией на этот пик. Практически ни в одном регионе не было мер, принятых вовремя. И даже в их отсутствие вспышка продолжила бы отступать.
Увидеть это помогают независимые показатели: ковид-специфичные запросы в Яндексе и госпитализации (по которым ни Минздрав, ни оперштаб не публикуют сводных данных — изучение госпитализаций требует самостоятельного поиска и сбора).
Госпитализации важны: это объективная метрика, которая показывает реальную нагрузку на здравоохранение и при этом не так подвержена манипуляциям, как выявленные случаи. Госпитализации — промежуточный этап между инфицированием и смертью. И зачастую именно перегрузка больниц и нехватка резервных коек — единственное, что вынуждает чиновников действовать и вводить строгие ограничения. Так это произошло и сейчас.
«Никакого локдауна»: как упустить волну
Пик госпитализированных по стране пришёлся на конец октября — аккурат перед началом нерабочих дней. Если учесть, что средний лаг между заболеванием и госпитализацией — 5–7 дней, а между инфицированием и первыми симптомами — ещё 4–5 дней, то получается, что фактический пик заражений пришёлся на 17–24 октября — то есть на ту неделю, когда было принято решение о нерабочих днях.
В последнюю неделю октября по стране было занято рекордное количество коек. В больницах лежало почти 270 тыс. человек, и это абсолютный рекорд с начала эпидемии: на 21% больше, чем на пике второй волны, осенью 2020 года. А уже с начала ноября число занятых коек начало снижаться — для вклада нерабочих дней ещё слишком рано:
Вместе с тем, масштабы грядущего бедствия были очевидны уже в сентябре. В четвёртую волну эпидемии Россия вступила с куда худшими вводными, чем год назад — во вторую. На середину сентября в стране было 140–150 тыс. занятых коек — это на 50–70% больше, чем в прошлом сентябре. Дальше начался стремительный рост: за вторую половину сентября число пациентов выросло на 25%, за первую неделю октября — ещё на 15%.
Уже в начале октября в больницах лежало почти столько же людей, сколько на пике второй волны, в середине ноября 2020-го.
Однако серьёзных ограничений на тот момент не было никаких — а незадолго до этого Анна Попова заявила, что оснований для локдауна в России нет.
Ограничения по большей части были несущественны. Где-то, как в Тюменской области, ограничили посещаемость мероприятий тысячей человек. Где-то, как в Новгородской области, детям и подросткам было запрещено посещать кинотеатры и торговые центры без родителей. Где-то, как в Калининградской области, закрыли детские развлекательные центры и игровые комнаты и ввели QR-коды для общепита.
Крупные чиновники — то Татьяна Голикова, то Валентина Матвиенко — на тот момент заявляли, что никакого локдауна не будет и что мер, которые принимают регионы, достаточно. Регионы тоже обещали не вводить локдаун — якобы он «неактуален».
Результаты такого промедления неутешительны. Уже к середине октября стало очевидно, что меры необходимы — в больницах уже 250 тыс. человек. Вскоре по всей стране объявили нерабочие дни. Правда, об этом сообщили почти за две недели до их наступления. Это сразу привело к резкому всплеску бронирований билетов и жилья на туристических направлениях.
К началу федерального локдауна, в начале ноября, в больницах было уже 30 тыс. тяжёлых пациентов — это на треть больше, чем на пике год назад. На ИВЛ лежало 7 тыс. человек — это на 40% больше, чем на прошлогоднем пике. Потребление кислорода также вышло на исторический максимум: почти 3 тыс. тонн в сутки.
С такими вводными Россия ушла на локдаун. Данные оперштаба тем временем показывали рост выявленных случаев вплоть до 6 ноября — а уже на следующий день, под занавес нерабочих дней, заболеваемость начала снижаться, знаменуя тем самым победу над четвёртой волной.
Что ищут люди: динамика поисковых запросов
Второй независимый показатель — это специфические поисковые запросы. Важна совокупная статистика по тем запросам, которые люди станут искать в Яндексе или Google, когда заболели они сами или их близкие. Поисковые запросы, как было неоднократно показано (например, здесь и здесь), сильно коррелируют с фактической заболеваемостью, госпитализациями и избыточной смертностью.
Я работаю с пулом из 400+ ковид-специфичных поисковых запросов, разбитых на 13 семантических групп. Среди них есть группы, связанные с начальным периодом болезни (это запросы «симптомные», запросы с аносмией и с течением болезни), есть группы, связанные с лечением, с обеспечением медицинской помощи, запросы с выдержками из КТ-заключений, практические запросы вида «сатурация 89 что делать», запросы диагностические. Наконец, несколько групп — это запросы, связанные с периодом после болезни, реабилитацией и постковидными осложнениями.
И поисковые запросы показывают ровно то же, что и госпитализации: пик заболеваемости в эту волну пришёлся на 17−24 октября — как по стране в целом, так и по большинству регионов. Далее заболеваемость начала снижаться — и к началу нерабочих дней заболеваемость стала падать независимо от ограничений.
Иными словами, запоздал не только локдаун, но и само решение о локдауне. 19 октября, когда только зашла речь о нерабочих днях в ноябре, страна уже проходила пик этой волны — и готовилась к снижению.
Реальные хроники четвёртой волны
Если восстанавливать хронологию четвёртой волны на основе поисковых запросов и госпитализаций, получится такая картина.
С июля заболеваемость (а с ней и нагрузка на больницы) медленно снижалась в большинстве регионов: одной из особенностей третьей, летней, волны был синхронный подъём, и спад также оказался синхронным. Заболеваемость достигает минимума в первую неделю сентября. А уже 9–10 сентября вновь начинается рост, заметный в масштабах страны.
Первой начинает расти Москва — и это мгновенно отражается на статистике оперштаба. В остальных регионах рост искусственно сдерживается: так, выявленные случаи по стране отстают от фактической заболеваемости минимум на неделю, и оперштаб показывает рост только накануне выборов.
Очень показательный пример, как региональные оперштабы сдерживают заболеваемость — это Башкирия. Поисковые запросы достигают минимума в первую неделю сентября, а в больницах тем временем лежит 4000 человек. Уже 10 сентября начинается резкий рост запросов. Выявленные случаи при этом почти не растут — их интенсивный рост происходит на две недели позже, только после выборов. Заболеваемость, отпущенная, словно пружина, резко расправляется в статистике: за последнюю неделю сентября выявленные случаи резко увеличились на 32% —так же они росли на протяжении двух предшествующих месяцев. На начало октября в Башкирии занято уже 6000 коек, на середину месяца — 7200, в полтора раза больше, чем на пике второй волны.
Госпитализации по стране достигают дна в середине сентября, а затем тоже пускаются в рост, с задержкой в 5–6 дней относительно поисковых запросов. Рост стремительный: ситуация ухудшается быстрее, чем в предшествующие волны.
Вскоре десятки регионов сталкивается с острым дефицитом кислорода, и со всей страны несется вал новостей одна другой тревожней. В Перми детям не хватает мест в больницах — их размещают в коридорах. В Самарской области не хватает мест на кладбищах — хоронят уже в проходах. В Орловской области людей в больницы кладут, только когда кто-то из госпитализированных умирает. В Нижнем Новгороде резко растёт спрос на похороны. В Москве и Подмосковье — рекордное число пациентов на ИВЛ. В Воронежской области за месяц скончалось почти 2 тыс. человек от пневмонии — это в 7,6 раз больше, чем за весь 2019 год.
А спустя месяц рост прекращается. К 20 октября сотни ковид-специфичных поисковых запросов достигают пика — и начинают идти на спад.
А официальная заболеваемость ещё 2,5 недели растёт: либо из-за особенностей сбора данных оперштабом и задержки в ПЦР-тестах, либо для оправдания уже введённых ограничений.
В чём причина такой асинхронности, остаётся только гадать. Однако в связи с этим есть два очень показательных примера.
Рекорды заболеваемости там, где их на самом деле не было
Пример первый — Краснодарский край. Крупный, с 5,6 млн населения, регион с начала эпидемии показывал подозрительно низкую заболеваемость: не более 200 случаев до июля 2021, и не более 300 случаев — до нерабочих дней; та ровная полочка, которую можно видеть на графике заболеваемости, статистически недостоверна. А с завершением нерабочих дней происходит неожиданное — и заболеваемость начинает резко расти.
11 ноября местный оперштаб сообщил про подготовку законопроектов об обязательных QR-кодах, которые будут действовать практически повсеместно. Правда, на тот момент на протяжении недели число выявленных случаев колебалось в пределах от 300 до 350. И уже на следующий день после этого заявления выявленные случаи взлетают — и за какие-то 8 дней вырастают втрое, с 350 до 990. Такого роста на Кубани ещё никогда не было.
Это же позволяет делать чиновникам заявления об ухудшении обстановки и о стремительном росте заболеваемости. Власти «вынуждены» идти на строгие меры, и уже с 22 ноября на Кубани начинает действовать повсеместная система пропусков по QR-кодам. Коды нужны везде: в торговых центрах, в общепите, в большинстве магазинов, во всех организациях из сферы развлечений и отдыха.
Удивительным образом это мгновенно сбивает заболеваемость: уже со следующего дня выявленные случаи резко снижаются.
Вместе с тем, все независимые индикаторы указывают на то, что на самом деле никакого взлёта заболеваемости после локдауна на Кубани не происходит. Напротив: по поисковым запросам пик приходится на первую неделю ноября, а далее запросы быстро снижаются. Аналогичную динамику показывают и госпитализации: здесь пик занятых коек пришёлся на начало ноября. К тому моменту, когда официальная заболеваемость в регионе резко взлетает, даже госпитализации начинают снижаться. И за те дни, что выявленные случаи взлетают втрое, занятые койки снижаются на 13%: с 6,4 тыс. до 5,6 тыс.
Похожая история и в Татарстане, только здесь всё ещё удивительней. По запросам, пик заболеваемости пришёлся на 11−14 октября (тогда официальная статистика только начала расти). Пик госпитализаций — на последнюю декаду октября. А официальная заболеваемость за октябрь-ноябрь взлетает, и за месяц с небольшим Татарстан 22 раза бьёт рекорды. Согласно оперштабу, пик пришёлся на 17 ноября.
Между тем, именно в Татарстане введены одни из самых жёстких мер в эту волну — но введены совсем поздно. Татарстан стал пилотным регионом с проверкой QR-кодов на общественном транспорте. И, по странному совпадению, на следующий день после того, как местный кабмин утвердил QR-коды, заболеваемость прошла пик и начала снижаться.
Зачем это нужно? Почему есть регионы, где при фактическом спаде заболеваемости официальные цифры резко растут? Вопрос открытый.
Можно только предполагать, что это значит. Стремление к открытости и большей честности? Пересмотр учёта выявленных случаев? Реакция на призыв Владимира Путина не занижать заболеваемость и не приукрашивать картину (впрочем, почти дословно такой же призыв звучал и годом ранее)?
Попытка легитимизировать строгие ограничения? Это кажется наиболее правдоподобным объяснением: так, тяжело объяснить повсеместное введение QR-кодов, когда на 5,6 млн населения заболевает всего по 300 человек в сутки. Или объяснить введение QR-кодов на общественном транспорте при официальной заболеваемости в 160 случаев сутки на четырехмиллионный регион.
Резкий рост заболеваемости позволяет мотивировать жёсткие ограничения и переводит их из тоталитарной плоскости (как это воспринимают люди) в плоскость эпидемиологическую.
Проблема в том, что эта недостоверность подливает масла в огонь ковид-диссидентам, убеждённым, что вся эпидемия политически мотивирована. А ещё это попросту дезориентирует людей, которые начинают неизбежно задаваться вопросом: почему локдаун не сработал? Почему у нас в регионе прививают по 20 тыс. человек в сутки, а заболеваемость только растёт?
Но, пожалуй, самое важное: вместо реальной борьбы с эпидемией всё превращается в фикцию, в дурной фарс.
Вместо того, чтобы принимать реальные меры на подъёме волны, мы будем бесконечно разворачивать койки — до тех пор, пока их будет хватать. Потом можно подумать и об ограничениях.
Вместо того, чтобы вводить некомфортные для людей, но необходимые меры — будем пытаться дотянуть до естественного пика волны. А то, что это повлечёт за собой чудовищную перегрузку больниц и колоссальную избыточную смертность — это не столь важно. И то, что койки сами по себе не лечат и не спасают, тоже не имеет значения. Главное — постараться всех обеспечить; для этого можно и ужесточить критерии госпитализации.
Вместо того, чтобы стимулировать вакцинацию между волнами, будем вводить QR-коды в разгар вспышки — и гнать толпы людей прививаться в поликлиники и торговые центры.
Вместо того, чтобы контролировать эпидемию, будем качаться на её волнах. А когда волна сойдёт (а это неизбежно случится — попросту в силу эпидпроцесса), можно приписать эту очередную победу себе. И два месяца в локдауне сидеть не пришлось, как в какой-то Европе. И при этом вовремя отреагировали и приняли правильные меры.
При этом было бы ошибкой считать, что это уникальная для России история. На самом деле, запоздалая реакция и нежелание до последнего вводить серьёзные меры — это общее место и для других стран, в основном постсоветских. Например, тот же паттерн показывает и Украина, и соседняя с ней Молдова. Проспать начало волны, опоздать с вакцинацией, оттягивать до последнего строгие меры, подчёркивать, что всё под контролем — и всеми силами стараться дотянуть до естественного спада волны. А меры если и принимать, то только на пике заболеваемости.
И это поднимает уже другие вопросы: а что общего между нами? И почему борьба с эпидемией не только в России, но и в ближайших к нам странах нередко оборачивается фарсом? Почему так низко ценится человеческая жизнь и здоровье? Но это все тема уже другого разговора.
А прямо сейчас главный вопрос в другом: какие рекорды нас ждут в следующую волну? Как станут реагировать власти, когда в страну придёт омикрон и если окажется, что он и правда настолько заразен и настолько хорош в ускользании от иммунитета, как предполагается? Будут ли приняты меры, когда пойдёт новая вспышка — или вновь будем тянуть до естественного пика волны?
Это вопросы тем более актуальны, что за последнюю неделю сразу ряд регионов вновь пошёл в рост. Среди них — Москва и Санкт-Петербург. Поначалу стали расти ковидные поисковые запросы, теперь, по сообщениям частных лабораторий, начался рост и доли положительных ПЦР-тестов после нескольких недель спада. Госпитализации в Москве также перестали падать и готовятся к развороту.
Что будет дальше — новое высокое плато или уже пятая волна — мы не знаем. Но готовиться к этому нужно уже здесь и сейчас.
Почему программистам нужны ограничения
Мы родились в культуре с девизом «Никаких границ» или «Раздвигай границы», но на самом деле границы нам нужны. С ними мы становимся лучше, но это должны быть правильные границы.
Цензура ради качественной музыки
Когда перед нами встают внешние ограничения того, что можно сказать в песне, книге или фильме, то для передачи нужного смысла авторы должны использовать метафоры.
Возьмём для примера классическую песню Коула Портера 1928 года Let’s Do It (Let’s Fall in Love). Все мы понимаем, что подразумевается под «It» и это определённо не «давай влюбимся». Подозреваю, что автору пришлось добавить часть в скобках, чтобы избежать цензуры.
Перенесёмся в 2011 год и посмотрим на Slob on my Knob группы Three 6 Mafia. За исключением первого метафорического куплета всё остальное до отвращения очевидно.
Если отвлечься на минуту от художественности исполнения (или его отсутствия), то можно сказать, что в песне Коула Портера намёками говорится о том, что Three 6 Mafia вываливает на нас с невыносимыми подробностями, не оставляющими ничего для работы воображения.
Проблема заключается в том, что если не разделяете взглядов на занятия сексом, описываемых в текстах Three 6 Mafia, то посчитаете песню в лучшем случае вульгарной и совершенно не раскрывающей тему. А включив песню Коула Портера, слушатель может вызвать в воображении собственную фантазию.
То есть ограничения могут делать предмет более притягательным.
Акула сломалась
Изначально Стивен Спилберг планировал рассказать сюжет «Челюстей» через сцены с акулой. Но она постоянно ломалась. Бо́льшую часть времени съёмочная группа не могла показывать акулу — звезду этого фильма.
Лента, ставшая блокбастером, не существовала бы в своём нынешнем виде, если бы сложности с механикой не наложили ограничения на возможности Спилберга.
Почему этот фильм намного лучше того, в котором показывают акулу? Потому что каждый зритель самостоятельно заполняет пробелы с помощью своего воображения. Он вспоминает собственные фобии и проецирует их на экран. Поэтому страх ПЕРСОНАЛЕН для каждого зрителя.
Аниматорам этот принцип был известен уже давно. Включите звук падения за экраном, а затем покажите его последствия. В этом есть два преимущества. Во-первых, не нужно анимировать падение, во-вторых, падение происходит в сознании зрителя.
Почти все люди считают, что они видели то, как застрелили маму Бэмби. Но мы не только не видим, как в неё стреляют — мы даже никогда не видели её ПОСЛЕ выстрела. Но люди могут поклясться, что они видели обе сцены. Но этого НИКОГДА не показывали.
Итак, ограничения делают всё лучше. Гораздо лучше.
Возможности выбора повсюду
Представьте, что вы художник, и я прошу вас написать картину. Единственное, чего я прошу: «Нарисуйте мне что-нибудь красивое. То, что мне понравится».
Вы приходите в свою студию и сидите там, глядя на пустой холст. Вы бесконечно смотрите на него, и никак не можете начать писать. Почему?
Потому что вариантов слишком много. Вы можете нарисовать буквально что угодно. Я не поставил перед вами НИКАКИХ ограничений. Это явление называется парадоксом выбора.
Однако если бы я попросил нарисовать пейзаж, который мне понравится, я по крайней мере устранил бы половину бесконечных вариантов. Даже несмотря на то, что по-прежнему остаётся бесконечное количество вариантов, любые мысли о портрете будут быстро отметаться.
Если бы я пошёл дальше и сказал, что мне нравятся морские пейзажи и волны, разбивающиеся о берег во время золотого заката, то всё равно бы осталось бесконечное количество возможных картин, но эти ограничения на самом деле помогли бы вам думать о том, что нарисовать.
И пока неосознанно вы смогли бы начать писать морской пейзаж.
Итак, ограничения делают творчество проще.
Аппаратное обеспечение проще, чем программное
В «железе» никогда не бывает так, что транзистор или конденсатор использовался несколькими компонентами компьютера. Резисторы в схеме клавиатуры не могут использоваться графической картой.
Графическая карта обладает собственными резисторами, которыми управляет только она. Инженеры аппаратного обеспечения делают так не потому, что они хотят продать больше резисторов. Они делают так, потому что у них нет выбора.
Законы Вселенной гласят, что такую систему невозможно создать, не учинив хаоса. Вселенная задаёт правила разработчикам «железа», то есть ограничивает пределы возможного.
Такие ограничения делают работу с аппаратным обеспечением проще, чем работа с ПО.
В программах нет ничего невозможного
Теперь перейдём к ПО, в котором возможно почти всё. Ничто не мешает разработчику программного обеспечения использовать переменную в любой части программы. Такие переменные называются глобальными.
В языке ассемблера мы можем просто перейти к любой точке в коде и начать её выполнение. И это можно сделать в любой момент. Можно даже выполнять запись в данные, заставляя программу запускать непредусмотренный код. Такой метод используют хакеры, эксплуатирующие уязвимости типа «переполнение буфера».
Обычно операционная система ограничивает действия, которые программа может выполнить за своими пределами. Но никакие ограничения не накладываются на то, что она может делать с принадлежащими ей кодом и данными.
Именно отсутствие ограничений делает написание и поддержку ПО таким сложным делом.
Как правильно ставить ограничения в разработке ПО
Мы знаем, что при разработке ПО нужны ограничения, и по опыту знаем, что ограничения в других творческих профессиях могут пойти нам во благо.
Также мы знаем, что не можем позволять обществу случайным образом цензурировать наш код или ставить механические преграды, ограничивающие наши парадигмы. И мы не можем ждать от пользователей такого уровня квалификации, чтобы они ставили соответствующие ограничения в дизайне ПО.
Мы должны ограничивать себя сами. Но мы должны гарантировать, что эти ограничения пойдут всем во благо. Так какие же границы мы должны выбрать и как нам вообще принимать такие решения?
Чтобы ответить на этот вопрос, мы можем положиться на наш опыт и годы практики. Но самым полезным инструментом являются наши прошлые ошибки.
Боль от наших предыдущих действий, например, когда мы коснулись горячей плиты, говорит нам, какие ограничения мы должны наложить на себя, чтобы избавиться от таких мучений в будущем.
Let my People Go
Давным-давно люди писали программы, код которых прыгал из одного места в другое. Это называлось спагетти-кодом, потому что отслеживание подобного кода походило на наблюдение за одной макарониной в кастрюле.
Индустрия поняла, что такая практика контрпродуктивна и сначала запретила использование в коде конструкции GOTO тех языков, в которых она разрешалась.
Со временем, новые языки программирования полностью отказались от поддержки GOTO. Они стали называться языками структурного программирования. И сегодня все популярные высокоуровневые языки не содержат GOTO.
Когда это произошло, некоторые стали жаловаться, что новые языки слишком строги и что при использовании GOTO писать код проще.
Но победили более прогрессивно мыслящие, и мы должны быть благодарны им за отказ от такого разрушительного инструмента.
Прогрессивно мыслящие люди поняли, что код гораздо чаще читается, чем пишется или изменяется. То есть это может быть менее удобно для консерваторов, но в длительной перспективе жизнь с этим ограничением будет намного лучше.
Компьютеры по-прежнему могут выполнять GOTO. На самом деле, им это даже необходимо. Просто мы, как индустрия в целом, решила ограничить непосредственное использование их программистами. Все компьютерные языки компилируются в код, использующий GOTO. Но разработчики языков создали конструкции, использующие более упорядоченное ветвление, например, с помощью конструкции break, выполняющей выход из цикла for.
Индустрия программного обеспечения значительно выиграла от ограничений, поставленных разработчиками языков.
Надеваем кандалы
Так что же является GOTO сегодня и что разработчики языков готовят для нас, ничего не подозревающих программистов?
Чтобы ответить на этот вопрос, нам нужно рассмотреть те проблемы, с которыми мы сталкиваемся ежедневно.
Сложность
Сложность растёт со временем. То, что изначально является простой системой, со временем эволюционирует в сложную. То, что начинается как сложная система, со временем эволюционирует в хаос.
Так как же нам ограничить программистов, чтобы помочь им снизить сложность?
Во-первых, мы можем заставить программистов писать код, полностью разбитый на небольшие части. Хотя это сложно, а может и невозможно полностью, мы можем создать языки, поощряющие такое поведение и вознаграждающие за него.
Многие функциональные языки программирования, особенно самые чистые, реализуют оба эти эффекта.
Написание функции, которое является вычислением, принуждает писать очень сильно разбитый на части код. Также это заставляет продумывать ментальную модель задачи.
Также мы можем наложить ограничения на то, что программисты могут делать в функциях, например, сделать все функции чистыми. Чистые функции — это те, у которых нет побочных эффектов, например, функции не могут получать доступ к данным, находящимся за их пределами.
Чистые функции работают только с переданными им данными, вычисляют свои результаты и передают их. Каждый раз, когда вы вызываете чистую функцию с одинаковыми входными данными, она ВСЕГДА будет выдавать одинаковые выходные данные.
Это делает работу с чистыми функциями гораздо логичнее, потому что все выполняемые ими задачи находятся целиком внутри самой функции. Также для них проще проводить юнит-тестирование, потому что они являются самодостаточными единицами. Если вычисления таких функций получаются затратными, то их результаты можно кэшировать. Если у вас будут одинаковые входные данные, то можно быть уверенным, что выходные тоже всегда одинаковы — идеальный сценарий для использования кэша.
Ограничивая программистов исключительно чистыми функциями, мы значительно ограничиваем сложность, потому что функции могут иметь только локальное влияние; кроме того, это помогает разработчикам естественным образом разбивать на части их программы.
Многократное использование
Индустрия программного обеспечения борется с этой проблемой почти с самого момента появления программирования. Сначала у нас были библиотеки, потом структурное программирование, а потом — объектно-ориентированное наследование.
Все эти подходы имеют ограниченную привлекательность и успех. Но есть один способ, который всегда работает и применялся почти каждым программистом — Copy/Paste, или «копипаста».
Если вы копируете и вставляете свой код, то делаете что-то не так.
Мы не можем запретить программистам копипастить, потому что они всё-таки пишут программы в виде текста, однако мы можем дать им кое-что получше.
В функциональном программировании есть стандартные практики, которые намного лучше копипасты, а именно функции высшего порядка, каррирование (карринг) и композиция.
Функции высшего порядка позволяют программистам передавать параметры, которые являются данными и функциями. В языках, не поддерживающих эту особенность, единственным решением является копирование и вставка функции с последующим редактированием логики. Благодаря функциям высшего порядка логику можно передавать как параметр в виде функции.
Каррирование (карринг) позволяет применять к функции по одному параметру за раз. Это позволяет программистам писать генерализированные версии функций и «запекать» некоторые из параметров для создания более специализированных версий.
Композиция позволяет программистам собирать функции как кубики Lego, позволяя им повторно использовать функционал, который они или другие встроили в конвейер, в котором данные переходят от одной функции к другой. Упрощённой формой этого являются конвейеры Unix.
Итак, хотя мы не можем избавиться от копипасты, мы можем сделать её необязательной благодаря поддержке языка и с помощью анализа кода, запрещающего её присутствие в кодовых базах.
Глобальное изменяемое состояние
Вероятно, это величайшая проблема в программировании, хотя многие и не осознают её как проблему.
Задавались ли вы когда-нибудь вопросом, почему чаще всего программные «баги» исправляются перезагрузкой компьютера или перезапуском проблемного приложения? Так происходит из-за состояния. Программа повреждает своё состояние.
Где-то в программе недопустимым образом изменяется состояние. Такие «баги» обычно одни из самым сложных в исправлении. Почему? Потому что их очень сложно воспроизвести.
Если вам не удаётся стабильно воспроизвести такой «баг», то вы не сможете найти способ его устранения. Вы можете проверить своё исправление и ничего не произойдёт. Но получилось ли так, потому что проблема устранена, или потому, что она пока не возникла?
Правильное управление состоянием — наиболее важный принцип, который нужно реализовать для обеспечения надёжности программы.
Функциональное программирование решает эту проблему, устанавливая ограничения для программистов на уровне языка. Программисты не могут создавать изменяемые переменные.
Поначалу кажется, что разработчики зашли слишком далеко, и пора бы поднять их на вилы. Но когда вы действительно работаете с такими системами, вы можете увидеть, что можно управлять состоянием, в то же время сделав все структуры данных неизменяемыми, то есть после того, как переменная получает значение, оно никогда не может измениться.
Это не значит, что состояние не может меняться. Это просто значит, что для этого необходимо передать текущее состояние в функцию, создающую новое состояние. Пока вы, любители хакинга, снова не начали точить свои вилы, могу уверить вас, что существуют механизмы оптимизации таких операций «за кулисами» с помощью Structural Sharing.
Учтите, что такие изменения происходят «под капотом». Как и в былые времена уничтожения GOTO, компилятор и выполняемая программа по-прежнему применяют GOTO. Они просто недоступны программистам.
Там, где должны возникнуть побочные эффекты, функциональное программирование имеет способы ограничения потенциально опасных частей программы. В хороших реализациях эти части кода явно помечены как опасные и отделены от чистого кода.
И когда в 98% кода отсутствуют побочные эффекты, портящие состояние баги могут оставаться только в оставшихся 2%. Это даёт программисту хороший шанс найти ошибки такого типа, потому что опасные части загнаны в загон.
То есть ограничивая программистов исключительно (или по большей мере) чистыми функциями, мы создаём более безопасные и надёжные программы.
Динамическая типизация
Есть ещё одна долгий и старый спор о статической типизации и динамической типизации. Статическая типизация — это когда тип переменной проверяется на этапе компиляции. После того, как вы зададите тип, компилятор помогает определить, используете ли вы его правильно.
Возражения против статической типизации заключаются в том, что она навешивает на программиста ненужную ношу и загрязняет код подробной информацией о типизации. И эта информация о типизации синтаксически «шумная», потому что находится рядом с определением функций.
При динамической типизации тип переменной никогда не задаётся и не проверяется на этапе компиляции. На самом деле, большинство языков с динамической типизации являются некомпилируемыми.
Возражения против динамической типизации заключаются в том, что несмотря на значительную очистку кода, программист не может отследить все случаи неправильного использования переменной. Их невозможно обнаружить, пока программа не будет запущена. Это означает, что несмотря на все усилия, ошибки типов добираются до этапа продакшена.
Так что же лучше? Поскольку здесь мы рассматриваем ограничение программистов, вы наверно ожидаете, что я буду выступать за статическую типизацию, несмотря на её недостатки. Вообще да, но почему бы нам не взять лучшее из обоих миров?
Оказывается, не все системы со статической типизацией созданы равными. Многие функциональные языки программирования поддерживают вывод типов, при котором компилятор может определить типы создаваемых вами функции на основании того, как вы их используете.
Это значит, что мы можем пользоваться статичной типизацией без излишнего задания типов. Рекомендации говорят нам, что типизация должна задаваться, а не определяться компилятором, но в таких языках, как Haskell и Elm, синтаксис типизации на самом деле не разрушает структуру и довольно полезен.
Нефункциональные, т.е. императивные языки со статической типизацией отягощают программиста заданием типов, не давая почти ничего взамен.
По сравнению с ними, системы типов Haskell и Elm на самом деле помогают программистам кодировать лучше и уведомляют их на этапе компиляции, если программа не будет работать правильно.
Итак, ограничивая программистов хорошей статической типизацией, компилятор может помочь в распознавании ошибок, определять типы и помогать в кодировании, а не отягощать разработчика многословной, навязчивой информацией о типах.
Тестирование
Написание кода тестов отравляет жизнь современного программиста. Очень часто разработчики тратят больше времени на написание кода тестов, чем на сам тестируемый код.
Написание кода тестов для функций, взаимодействующих с базами данных или веб-серверами сложно (если не невозможно) автоматизировать. Обычно существует два варианта.
Но если мы ограничим код исключительно чистыми функциями, то они не смогут непосредственно взаимодействовать с базой данных, потому что это может привести к побочным эффектам или мутациям. Нам по-прежнему нужно получать доступ к базе данных, но теперь наш слой опасного кода будет очень тонким интерфейсным слоем, в то время как бо́льшая часть модуля остаётся чистой.
Тестирование чистых функций намного проще. Но нам всё равно нужно писать код тестов, отравляющий нам жизнь. Или всё же нет?
Оказывается, что существуют программы для автоматического тестирования функциональных программ. Единственное, что должен предоставить программист — свойства, которых должны придерживаться функции, например, обратные функции. Автоматизированный тестер Haskell называется QuickCheck.
Итак, ограничивая большинство функций так, чтобы они были чистыми, мы делаем тестирование намного проще, а в некоторых случаях просто тривиальным.
Крах Закона Мура
Закон Мура — это на самом деле не закон, а практическое наблюдение, заключается в том, что вычислительная мощность компьютеров удваивается каждые два года.
Этот закон был справедлив более 50 лет. Но, к сожалению, мы достигли пределов современной технологии. И на разработку технологии создания компьютеров не на основе кремния могут потребоваться десятилетия.
А до этого момента наилучшим способом удвоения скорости компьютера является удвоение количества ядер, т.е. количества вычислительных «двигателей» центрального процессора. Но проблема не в том, что изготовители «железа» не могут дать нам больше ядер. Проблема заключается в аккумуляторах и ПО.
Удвоение вычислительной мощности означает удвоение потребляемого процессором питания. Это приведёт к ещё большему расходу батарей, чем сегодня. Аккумуляторные технологии сильно отстают от неутолимых аппетитов пользователей.
Поэтому вместо того, чтобы добавлять новые ядра, разряжающие аккумуляторы, нам, возможно, стоит оптимизировать использование уже имеющихся ядер. Именно здесь в дело вступает ПО. В современных императивных языках программирования очень сложно заставить программы выполняться параллельно.
Сегодня реализация параллелизма — тяжкая ноша для программиста. Программу необходимо разрезать вдоль и поперёк на параллельные части. Это непростая задача. И на практике, в таких языках, как JavaScript, программисты не могут управлять этим, потому что код не может выполняться параллельно, он однопоточный.
Но при использовании чистых функций не важно, в каком порядке они выполняются. Самое важное в них — доступность входных данных. Это означает, что компилятор или система выполнения может определять, когда и какие функции нужно выполнять.
Ограничиваясь только чистыми функциями, программист избавляется от заботы о параллелизме.
Функциональные программы смогут оптимальнее использовать преимущества многоядерных машин, не увеличивая сложность для разработчика.
Делать больше благодаря меньшим возможностям
Как мы видим, при установке правильных ограничений мы можем значительно улучшить наши художественные работы, дизайн и саму жизнь.
Разработчики аппаратного обеспечения сильно выиграли от естественных ограничений своих инструментов, которые упростили их работу и позволили за прошедшие десятилетия добиться потрясающего прогресса.
Мне кажется, что и для нас, разработчиков программного обеспечения, настало время ограничивать себя, чтобы достичь большего.











