-
Механическая работа
Любую работу я условно делю на осмысленную и механическую. Первая — когда нужно думать, вторая — когда не нужно. Если проще, то в первом случае работает голова — нужно соображать, искать варианты. Во втором случае — задница: нужно сесть и сделать монотонную работу.
Каждый вид хорош по-своему, и секрет в том, как их чередовать.
Механическую работу нельзя делать, пока остался потенциал для осмысленной. Лучше сделать осмысленную, а механическую оставить на потом. Обратное тоже верно: нельзя браться за осмысленную, если уже устал — лучше заняться рутиной.
Например, мы исследуем узкое место в программе. Это осмысленная работа, потому что нужно строить гипотезы и проверять их. Предположим, мы нашли причину, и теперь нужно исправить двадцать файлов. Это механическая работа, и будет глупо браться за нее сразу — наверняка остался потенциал для чего-то полезного. Лучше исправить пару файлов и поскорее прогнать замеры. Нафигачить костылей, выкатить приложение на препрод и посмотреть метрики. И только если гипотеза подтвердилась, прижать зад и исправить остальные 18 файлов.
Я не чураюсь механической работы. Просто отмечаю про себя, что это место в целом понятно, просто нужно взять его терпением. И возвращаюсь, когда мозги уже выжаты, а работают только пальцы. Я не особо люблю автоматизирующие скрипты — писать и отлаживать их дольше, чем сделать работу. Включаю что-нибудь из раннего Пинк Флойд и колбашу руками.
Осмысленность и механика — две стороны одной медали. На самом деле одно и то же, но и разные. Дают гибкость и маневр, скрашивают капризы нашего тела.
-
Крайний
К слову “крайний” в значении “последний” я отношусь с улыбкой. Это дремучее просторечие, и дергать людей из-за него — то же самое, что поправлять “одеть” и “надеть”. Пусть человек говорит, такая у него особенность.
Но я никогда не думал, что прочту “крайний” в значении “последний” в книге. И не в прямой речи простолюдина, скажем, “братан, предупреждаю, это крайний раз”. Слово “крайний” использует рассказчик книги, по сюжету — развитый, интеллектуальный персонаж.
Как же случилось, что такое просторечение пропустили переводчик, корректор и редактор? Это уму не постижимо — разве что все трое приехали из одной рязанской деревни. Другой версии у меня нет.
Книга — “Звездный десант”, крайний перевод.
UPD: в Телеграме объяснили, что “крайний” пришло из военных и прочих профессий, связанных с риском. Там не говорят “последний раз”, опасаясь, что он станет таковым буквально. Можно понять: у военных, моряков и летчиков целый букет прибабахов. Но зачем перенимать это в обычную жизнь – загадка.
-
Задача с датами
Прочитал, что в одной фирме дают задание: не используя библиотеки и Гугл, написать функцию, которая для заданной даты вернет название дня. Скажем, для 2021-03-25 — вторник, для 2015-09-11 — среду (беру с потолка). Я бы эту задачу не решил, и вот почему.
Во-первых, я не помню все критерии високосного года. Каждый четвертый — это понятно, но есть еще два критерия, которые встречаются реже. Нужно смотреть их в википедии.
Во-вторых, я не помню, сколько дней в каком месяце за исключением февраля. В детском саду и школе нас учили считать по костяшкам, но на мой взгляд, это бред. Костяшек восемь, месяцев двенадцать. Если брать одну руку, то костяшек четыре, а промежутков три, в сумме семь. Как ни крути, эта сова не натягивается.
В-третьих, нужна точка отсчета. Даже если я переведу дату в число дней и возьму остаток от деления на семь, нужно знать, какой день был первым. Считается, что Иисус родился в понедельник? В любом случае это нужно сверять с википедией.
Еще был переход с юлианского календаря на григорианский, отсюда “старый стиль”, “старый новый год” и прочее.
Наконец, текущая система дат и времени — это костыль на костыле, которые достались нам от древних греков. Самое худшее, что можно вообразить — это работать с датами без библиотеки.
“Что ж, свою кандидатуру я снимаю сам.” ©
А вы бы решили?
-
Еще про Silent Hill 2
Еще одна заметка про Silent Hill. Понимаю, что всем пофиг, но это для себя. В этот раз — еще одна партия наблюдений, незамеченных в детстве.
Как вы знаете, герой ищет пропавшую жену Мэри. Город знакомит его с Марией — женщиной, которая выглядит как жена, но противоположна ей по характеру: общительна, сексуально раскрепощена. Часть локаций Джеймс проходит с Марией, у нее есть ключи от закрытых дверей.
Во второй половине игры происходят странные вещи: Марию начинают убивать, причем каждый раз с большей жестокостью. В первый раз ее пронзает ножом Пирамида, во второй раз Джеймс находит ее истерзанной в тюрьме, в третий раз ее казнят кольями. Каждый случай Джеймс переживает все тяжелее, и это расшатывает его рассудок. Примечательно, что после смерти Мария ничего не помнит и ведет разговор о посторонних вещах.
Не монстры, не ужасы города, а именно Мария становится главным мучением Джеймса. В каждой ее смерти он винит себя. Это напоминает наказание в аду, когда преступник переживает преступление снова и снова. Вот в чем заключается наказание Джеймса: город дает ему идеальную женщину и постоянно убивает ее, сводя с ума.
Только в последней сцене, увидев Марию живой в четвертый раз, Джеймс отвергает ее. Этим он разрывает порочный круг, и начинается финал.
Другой сложный символ, который сопровождает игру — это кровать, и появляется он в двух значениях. Первый — медленный уход из жизни, когда человек проводит дни в страданиях. Кровать становится его тюрьмой, превращаясь в могилу. Пустая кровать появляется, когда речь идет об умершей жене. Пустые кровати часто встречаются в игре как немой упрек: раньше здесь был человек, а теперь его нет.
Второе значение кровати — страсть, секс. Кровать встречается в сценах с Марией, альтер-эго умершей жены. Иногда Мария ложится якобы отдохнуть, взглядом и жестом приглашая Джеймса занять место рядом. После первого убийства Джеймс находит Марию в тюрьме в комнате длительных свиданий — проще говоря, месте, отведенном для секса. Мария сидит на кровати за решеткой, и нужно найти к ней другой путь. Когда Джеймс отправляется на поиски хода, она откидывается назад, намекая, какой будет встреча.
Когда Джеймс приходит к ней подземным ходом, Мария оказывается убитой. Шокирует резкая смена контекста: еще недавно она лежала на кровати соблазняя, а теперь лежит, будучи жертвой. Такой быстрый переход от любви к смерти подействовал на меня сильно. В детстве я не оценил мощь этой перемены, видимо, я просто не мог. С возрастом появились какие-то струнки, которые теперь задеты.
Интересный факт насчет трех лет. Джеймс утверждает, что жена умерла три года назад. Он продолжает это делать даже когда вылазят зловещие нестыковки. Ближе к концу мы узнаем, откуда взялись эти три года. В лодочной станции есть магнитофон с записями диспетчеров. Если послушать их, послышится диалог Джеймса с доктором в госпитале. Джеймс пытается выжать из доктора, сколько осталось жене. Доктор дает крайне широкую оценку: возможно, три года, возможно, несколько месяцев. И хотя все произошло за неделю, ум Джеймса ухватился за эти три года, стараясь задвинуть трагедию как можно дальше в прошлое.
Сексуализация монстров, которые выглядят как женские фигуры, связана с подавленным желанием Джеймса. В игре не обсуждается его сексуальная жизнь, но судя по долгому угасанию жены, в ней значительный пробел. Навещая жену в госпитале, Джеймс смотрел на ноги и грудь медсестер — в основном из этих частей состоят монстры. В середине игры есть сцена, где обыграно изнасилование одного из существ. Очевидно, это фантазии Джеймса.
Каждый персонаж живет в своем мире, и только изредка они пересекаются. Каждому предназначено свое мучение. Об этом не сказано явно, нужно догадаться из диалогов. Когда Джеймс видит Анжелу в последний раз, он замечает, что все в огне (намек на то, что Анжела сожгла дом вместе с насильником). На это Анжела отвечает, что “для нее всегда так”. Неудачника Эдди преследуют выдуманные им же люди, которые насмехаются над ним. Джеймс не видит этих людей, потому что они в мире Эдди. Пересекаясь с ним, он видит только трупы убитых насмешников. В мире Лоры нет ни монстров, ни опасностей, только кошки. Догадаться об этом можно по диалогу, когда Джеймс находит Лору в подвале госпиталя и спрашивает, как есть удалось не получить ни царапины. Лора искренне не понимает, что ей может угрожать.
Много всего я надумал, ненадолго вернувшись к этой игре. Ощущение, что перечитываешь Достоевского или Булгакова — нет-нет да найдешь то, что раньше не замечал. Может быть, через пятнадцать лет еще что-то найду — и разумеется, дам вам знать.
-
Саундтрек из Silent Hill 2
Один знакомый, зная, что я неравнодушен к серии Silent Hill, прислал ссылку на саундтрек ремастера. Оказалось, это не полноценный саундтрек, а нарезка по 20 секунд из каждого трека. Но поскольку там 90 треков длительностью три часа, сумма огрызков набегает на час. Послушайте и вы по ссылке.
Вдохновившись музыкой, пересмотрел ключевые сцены из оригинальной второй части. Лишний раз убедился, что Silent Hill 2 — уникальная в своем роде игра. Другой такой нет, да и не нужно — пусть она останется неповторимой.
Дело в том, что в основе игры лежит глубокая личная драма заурядного человека. Главный герой Джеймс не спасает мир от монстров и не ищет волшебные артефакты. Его проблема — медленный уход из жизни близкого человека. Боль, борьба желания и долга, терзания, что сказать и сделать в ситуации, когда и то, и другое бесполезно.
Пересматривая кат-сцены, не переставал удивляться глубокому символизму игры. Каждый кадр, каждая сцена выстроена так, чтобы сообщать что-то между строк. Это и окружающие предметы, и антураж, и одежда героев.
Красной нитью сквозь игру идет тема суда — подавленное желание наказать себя за преступление. Это преступление тщательно забыто, но прорывается наружу флешбеками и уликами. Темы суда и казни особенно сильны в конце, когда герой поднимается на крышу по железному коридору. Формально железные ограждения нужны, чтобы человек не упал с лестницы, но на самом деле это отсылка к тюремному коридору, по которому заключенный идет к месту казни. Когда Джеймс ступает на крышу, коридор падает — обратно он не вернется.
Другой назойливый символ игры — нож. В меню игры его форму имеет курсор. Нож передает Джеймсу Анжела. Оружие Пирамиды есть увеличенный в размерах нож — тот самый, что носит Джеймс. Его гротескный размер, вероятно, имеет отсылку к картинам Сальвадора Дали, где гигантизм означает дутую немощь.
Ближе к концу игры Анжела просит отдать нож: она хочет покончить с собой, чтобы избежать мучений. Джеймс отказывается, на что Анжела замечает: бережешь для себя? И хотя Джеймс несколько раз за игру произносит, что не убил бы себя, именно это случается в главной концовке. Я в курсе, что есть и другие, в том числе когда он уходит из города с новой женщиной, а в лучшем случае — даже с ребенком. Но получить хорошую концовку при первом прохождении, скажем мягко, затруднительно. Поэтому суицидальный конец истории я считаю каноничным.
Завершение самоубийством по-своему хорошо тем, что вписывается в концепцию игры. Она становится абсолютно, полностью завершенной. Дело в том, что игра начинается на парковке возле пристани. Оттуда Джеймс начинает путешествие в город. На парковке стоит его машина. При попытке открыть багажник Джеймс говорит, что почему-то хочет этого делать — в то время как взять вещи из машины, казалось бы, самое логичное дело.
Здесь и таится главная недосказанность игры: в багажнике машины лежит тело его жены. Повидав ужасы города, лишенный всех надежд Джеймс, пережив смерть жены дважды, возвращается на парковку. Там он заводит автомобиль и топит себя с телом жены. Не все из этого показано в игре, но концепция не оставляет других толкований.
На мой взгляд, второй Silent Hill — это “Преступление и наказание” нашего времени. В нем заложен такой плотный концепт, что можно разбирать очень долго. Это самообман, оправдание преступления, различные приемы, чтобы убедить совесть в обратном, подавленная сексуальность, ненависть к зависимому человеку и целый короб подобных штучек. И это только Джеймс, не считая второстепенных персонажей вроде Анжелы, Эдди и Лоры. Подобно Раскольникову или Соне, каждого персонажа можно брать и рассматривать часами.
Пишу это, чтобы напомнить: второй Silent Hill — важный культурный продукт нашего времени. Понимаю, это несколько странно: применять к игре формулировки, которые больше подходят книге. Да, из-за формата не все могут ознакомиться с ней. Но будь у вас лишние несколько часиков — не знаю, правда, откуда они в сорок лет — ознакомиться не помешает.
-
Микросервисы
Беда микросервисов в том, что их разработчики не понимают одну вещь. Хотя формально микросервисы отделены друг от друга, на самом деле они связаны, потому что подчиняются общим требованиям.
Обычно об этом не думают и колбасят пачки сервисов. Доходит до того, что один сервис пишут на Питоне, второй на Ноде, а в третьей команде экстремисты протащили Хаскель. И все такие — а что такого, у нас микросервисы, общение по HTTP JSON, какая разница, что крутится в кубернетисе?
Не все равно хотя бы по следующим причинам.
По нажатию кнопки микросервис должен сгенерировать HTML-документацию со всеми апишками и схемами. Все это генерится из кода, а не руками. Документашка пишется в докстрингах, схемы хранятся в файлах. Далеко не каждый фреймворк обладает столь мощной интроспекцией, чтобы перебрать свои кишки и понять, на какой эндпоинт что навешено.
На практике я наблюдаю, что документацию завозят только если продают апишку внешним потребителям. Для своих отношение другое — посмотришь исходник, не рассыпешься.
Далее трассировка. Каждый сервис трекает в общей базе request-id, с которым его вызвали. Записывается начало запроса, конец и статус. Должна быть админка, где вводишь request-id и система рисует граф вызовов с метриками. Опять же, где вы такое видели?
Лимиты. У каждого сервиса должен быть механизм рейт-лимита, чтобы его не ддосили. Как бывает обычно? Ты вызвал сервис 1000 раз, и начинаются крики “кто нас дидосит!!11”. Так ведь нигде не написано, сколько раз можно вызывать! Должна быть прокладка, которая считает число запросов в разрезе потребителей и внятно отвечает, сколько ждать до обнуления. Такое хоть где-то бывает?
Длины массивов. Сервис принимает список айдишников. Передаю 10 тысяч и получаю статус 500. Начинается восточный базар: передавай по сто. Нет, это мало, давай по тысяче? Нет, давай по пятьсот. Ну ок.
Разумеется, этого не должно быть. У каждого массива или строки должен быть верхний лимит — чего я не наблюдаю.
Из этого следует правило: микросервисы должны клепаться не как попало, а из общей болванки. В ней встроено все, описанное выше: генерилка документации, трекинг запросов, рейт-лимиты и так далее. В идеале сначала пишут болванку, а потом множат из нее микросервисы. Но разве так бывает? Все наоборот: сперва колбасят никак не связанные сервисы, а потом думают, как заставить их идти в одной упряжке.
Здесь и кроется предубеждение: хотя формально микросервисы не связаны друг с другом, на практике это клоны одного проекта. Изменения в клоне отражаются в его копиях, поэтому ни о какой самобытности не может быть и речи. Правильные микросервисы — это унификация, полный отказ от самостоятельности.
-
Нейролица
В интернете все больше лиц, нарисованных нейросетью. На картинке выше — какой-то медицинский стартап. Предполагается, что все эти улыбчивые люди — довольные клиенты сервиса.
Мне неприятно смотреть на эти лица, потому что они выглядят как натертые воском яблоки. Каждый раз смотрю и не понимаю: откуда эти блики? Они что, собрались на oiled-вечеринку? Ясно, что иллюстраторы любят градиенты и блики, но почему нельзя обучить алгоритм на каких-то реальных фото?
Моральных аспект: искусственные лица подаются как клиенты бизнеса, которых на самом деле нет. Тут включается внутренний голос и говорит: будь на фотках люди с фотостоков, тебе было бы легче? Это же модели, актеры, которые сегодня врачи, завтра домохозяйки, а послезавтра у них съемки белья для Вайлдберриз. Прям так сильно тебе нужны настоящие люди?
И отвечаю — да, лично мне нужны. Я не хочу покупать то, что рекламирует откровенно сгенерированный человек. Хотят моего внимания — пусть напрягутся и раздобудут настоящего.
-
Разрешения
В мобильных операционках мне нравится далеко не все. Но есть одна вещь, которую я горячо поддерживаю, и которая перешла в десктопы — это система разрешений. Например, доступ к камере, микрофону, контактам, календарю. Все это дает контроль за программами, которые лезут, куда не просят.
Может быть, не все помнят ранний Андроид, а я помню. В версиях до какой-то там у Андроида не было разрешений по требованию. Это значит, ты ставишь какой-нибудь Фонарик Про, а он говорит: нужен доступ к фоткам, контактам, акселерометру и еще десяти пунктам. А если не согласен, иди лесом. У Эпла разрешения были по запросу с возможностью позже отозвать их. Модель Гугла была ужасна, ее обузили так сильно, что пришлось сделать как у Эпла.
Так вот, возвращаясь к десктопу. Хотя в нем есть система разрешений, ее возможностей не хватает. Например, я бы хотел регулировать, какой программе можно в интернет, а какой нет. Чтобы снять в настройках чекбокс у программы — и все, шабаш. Не увидишь модалки, что вышло обновление. Не появится прогресс-бар с загрузкой. Не будет сбора метрик и кликов. Сейчас, чтобы победить эту хрень, приходится возиться фаерволом.
Вряд ли такое произойдет, но помечтать не вредно.
-
Last in Clojure
Chat GPT: No, the
last
function is not particularly expensive for vectors in Clojure. It runs in O(1) time because vectors in Clojure support efficient access to their last element.Meanwhile, Clojure:
-
Подробней о last
Поскольку в заметке про last отметились только профильные специалисты (в Телеграме), считаю, нужна его подробная версия. Я и сам понимаю, что для таких огрызков служит Твиттер, но чего нет — того нет.
Итак, дело вот в чем. Коллега спрашивает у Chat GPT, насколько дорого получить последний элемент вектора функцией last в Кложе. На это чат говорит — все тип-топ, у вектора доступ к последнему элементу работает за O(1).
Все бы ничего, но в ответе напутаны правда и ложь, и в целом он не верный. Чтобы в этом убедиться, откроем исходный код функции last:
(dеf ^{:doc "Return the last item in coll, in linear time"} last (fn ^:static last [s] (if (next s) (recur (next s)) (first s))))
Полагаю, даже человек, едва знакомый с Лиспом, увидит паттерн. Функция принимает коллекцию, и если в ней больше одного элемента (есть хвост), то она вызывает себя с хвостом. Когда длина хвоста равна одному, возвращается этот элемент.
В коде нет проверок на тип коллекции, например, отдельно для вектора или списка. Все очень просто и линейно.
Наконец, докстринг функции как бы говорит нам: вернуть последний элемент коллекции за линейное время. Линейное, Карл, то есть такое, что растет с числом элементов, то есть O(N).
Поэтому буквальный ответ на вопрос таков: нет, функция last вернет последний элемент вектора за O(N) шагов. Что не подходит для больших векторов.
Спрашивается, откуда у чата уверенность в правоте? Дело в том, что вектор действительно хранит ссылку на последний элемент. Для доступа к нему служит функция с забавным названием peek (заглянуть). Она работает только для вектора и для всего остального кинет ошибку.
Можно предъявить Ричу Хикки: надо было сделать интерфейс
Lastable
с методомgetLast
. Обычные коллекции бегут с головы, а вектор берет с конца. Все это упаковано вlast
, который переключает на нужную логику. Все довольны и смеются. Но имеем то, что имеем, тем более что я согласен с текущим положением дел. Из всех коллекций только вектор может вернуть последний элемент. Остальным коллекциям это не положено по идеологическим причинам.Скорее всего, чат прочитал вопросы на StackOverflow и слепил некую компиляцию. Вроде бы да, но вроде бы нет. В этом и состоит вред: чат выдает что-то, очень похожее на истину. Выглядит настолько правдоподобно, что принимаешь за чистую монету. Но если проверить, то окажется, что не в карты, а в нарды, и не корову, а машину, и не выиграл, и проиграл.
Поэтому я не пользуюсь чатом и аналогами, я в них даже не зарегистрирован. И вам советую прибегать к ним реже.