Минутка просвещения

Читать в телеге. Когда-то там были посты не только от меня.

Старейшая тудушка в коде

Ну уж в этом-то году точно все легаси уберем, да?

Чтобы найти старые TODO в репозитории (и, скорее всего, ужаснуться), можно использовать вот эту колбасу

git grep -i -nE 'TODO|FIXME|FIMXE' | while IFS=: read -r file lineno line; do commit_date=$(git blame -L "$lineno,$lineno" --porcelain "$file" | awk '/^author-time/ {print $2}' | { read epoch; date -u -d @$epoch "+%Y-%m-%d %H:%M:%S" 2>/dev/null || date -u -r $epoch "+%Y-%m-%d %H:%M:%S"; }); echo "$commit_date $file:$lineno: $line"; done | tee >(sort > todos.txt)

(результат будет в todos.txt)

P.S. Особым мазохизмом было получение кроссплатформенного варианта этой команды и выдрать нормальную дату из гита, потому что по умолчанию blame выдавал не очень машиночитаемый формат.

СсылкаКомментировать

"Кроссплатформенность" bash

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

Но как только надо написать какой-нибудь не очень тривиальный однострочник, чтобы добавить его в документацию и/или репозиторий, чтобы “работало” везде, сразу возникают проблемы. Например, у какого-нибудь sed есть как минимум две версии: BSD (во фряхе и маках) и GNU (в большинстве линуксов), и они серьезно отличаются.

Казалось бы, есть POSIX-команды, можно врубить какой-нибудь режим совместимости и все будет пусть и безобразно, но единообразно, да? *падме.жпг* Реальность, разумеется, полна разочарований: так с большинством команд сделать не получится.

Например, GNU date -Is -ud @249499969321 — это BSD date -Iseconds -ur 249499969321, и если seconds тоже можно использовать в первом случае, то остальное уже не поменять.

Другой пример: в BSD sed “на месте” должен быть явным, -i "", а в GNU должно быть именно -i, без явной пустой строки. Обо всяких \b тоже можно забыть.

Наконец, некоторые вещи можно обнаружить только методом проб и ошибок, например, strftime в awk.

Вишенка на торте: по умолчанию на маках стоит баш версии 3.2 аж от 2007 года (пусть даже ее постоянно патчат, функционально она застыла во времени).

В качестве обходного решения на маке можно… тупо поставить GNU-версии через brew. В среднем по больнице они все равно лучше. Но если это невозможно, то очевидный вариант — обмазать скрипт if/else с проверками на систему или переписать на питон. Еще один обходной путь: вызывать два варианта команды через || с учетом того, что неподходящий вариант отвалится с ошибкой.

СсылкаКомментировать

Дублирование ссылки в Markdown

Понадобилось в во внутренней доке вынести часть ссылок в начало документа, чтобы не искать их в тексте. Оказывается, у Markdown есть механизм для ссылки на ссылку! В любом месте документа (например в конце) добавляем название

[link_name]: https://ov7a.narod.ru/index-1.html

И потом используем в квадратных скобках сколько угодно:

Это [ссылка][link_name]. И [это][link_name] та же самая ссылка.
СсылкаКомментировать

Версионирование

Де-факто стандарт для версионирования всяких библиотек и продуктов — семантическое версионирование. Идеи довольно простые, хотя и полный документ содержит немного душноты.

Браузеры со своими версиями за 300 и внутренние релизы некоторых компаний а-ля 0.192, годами крутящиеся на проде, передают пламенный привет:)

Оказывается, у этого подхода есть куча критиков: 1, 2, 3. Недостатки сводятся к следующему:

  • Демагогия по поводу того, “а что такое ломающее изменение”, “а если это влияет только на 1% пользователей”, “а мелкое ли это изменение?”, “это не баг, а фича” и т.п.
  • Не все следуют SemVer (sic!) (например, у них 0.x в проде).
  • О ужас, SemVer не всем подходит!
  • Одно число не может передать всей глубины изменений. На него нельзя полагаться при обновлениях, все равно надо читать список изменений.
  • Если ваш продукт последний в цепочке (например, фронтенд-морда) — о боже мой, всем насрать какой он там версии. Это все очень сложно, простоиспользуйте одно число, как например браузеры.
  • Частые обновления библиотек могут отпугнуть пользователей.
  • Настоящим инженерам вообще версии не нужны — посмотрите на ранние UNIX-программы, они совершенны! Версионирование — это отмазка, чтобы ломать API.
  • В большом дереве зависимостей изменение одной версии может привести к каскадному резонансу изменению заметного числа зависимостей.
  • Инженеры боятся обновлять мажорную версию своей библиотеки, и откладывают внедрение фич. Иногда во имя маркетинга.
  • Ради обратной совместимости приходится делать костыли.

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

В java-мире сейчас обсуждают подход Tip & Tail, который может сгладить некоторые моменты (при этом не противореча идее SemVer). По сути предлагается иметь два релиза: tip, с новейшими фичами и всем таким, и tail, в котором все будет максимально стабильно и меняться очень редко и только когда прям совсем надо (по сути, LTS).

СсылкаКомментировать

Валидация HTML в консоли

На одной из страничек в легаси проекте всплыл косяк, что есть лишний закрывающий div. Вроде очевидное решение — его надо убрать, но может можно как-то найти и предотвратить это в будущем? Конечно, для этого можно использовать какой-нибудь JS-фреймворк (какой там сейчас популярный?), но у меня же тупо страничка с шаблоном (или SSR, как сейчас (или уже раньше) было модно говорить). Нашел консольную утилиту — HTML tidy, вы только зацените кислотность сайта! Привлекло, что можно ее можно использовать в формате curl url | tidy.

P.S. думал еще какой-нибудь плагин/расширение для браузера найти, но это тяжело в пайплайн встроить, и быстро ничего приличного не нашел (если кто шарит, поделитесь опытом).

СсылкаКомментировать

Применимость AI в разработке

Годная статья про текущий уровень, где автор неплохо и довольно трезво оценил, как лучше сейчас использовать всяких “ассистентов” (демки/MVP, автодополнение, генерация черновых вариантов), какие есть проблемы (код надо проверять, уметь дебажить и думать о крайних случаях оказывается, ну и архитектура с безопасностью в помойке) и попытался посмотреть в будущее (автоматизация рутины, помощь в поиске идей, проактивные предложения ну, и, разумеется, “вкалывают роботы, а не человек!”).

Описанное в статье в целом соответствует моим впечатлениями (см. 1 и 2)

СсылкаКомментировать

Работа с ошибками в Roc

Очередной доклад про работу с эффектами (на самом деле с обработкой ошибок). Не могу сказать что он супер или что в нем какая-то невероятно новая идея, но тут хорошо поставлена и разжевана проблема: почему напряжно обрабатывать ошибки разных видов.

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

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

Впрочем, автор и сам признает некоторые недостатки и часть идей на момент доклада не была реализована. Однако, если ни с одной идеей не знакомы, доклад довольно простой и доступный, и его можно посмотреть. Видос от создателя Roc и соавтора Elm, и прошлое автора чувствуется — торчат уши языков из этого семейства и сопутствующих идей. Но он неплохой докладчик — у меня в бложеке нашлась еще пара ссылок на его видео (1, 2).

СсылкаКомментировать

Пик сложности

Давным-давно, когда я глотал фантастические книжки стопками, в одной из них была такая идея об уровнях развития цивилизации:

  1. Простые технологии/механизмы для решения простых задач (палка стукать).
  2. Сложные технологии/механизмы для решения сложных задач (двигатель внутреннего сгорания, атомная станция).
  3. Простые технологии/механизмы для решения сложных задач (это у более развитых цивилизаций, чем наша).

Было это в контексте того, что кто-то посмотрел на двигатель высокотехнологичного транспорта, а там внутри все просто и понятно, и элементарно починить.

Увы, я уже совсем не помню никаких метаданных о книге, и ни поиск, ни чатгпт не помогли (если вы вдруг знаете, откуда это — напишите, пожалуйста). Но сама идея намертво застряла и я ее постоянно кому-то рассказываю, потому что она очень хорошо подходит для разработки.

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

В тему эволюции подходов к решению задач есть неплохой доклад от архитекторов языка Java, основная идея которого заключается в том, что когда вы наконец рассмотрели задачу со всех сторон и учли все нюансы, надо потратить еще время, чтобы упростить решение. Автор предостерегает от того, чтобы развертывать первое решение, приводя в пример сериализацию в Java (которая очень сложная и имеет кучу проблем). Тут есть нюанс контекста: он рассуждает в контексте платформенного решения, на основе которого строятся другие, а свое уэб-приложение можно и перезалить. Но еще важный момент — отношение: “раз работает, то все, задача выполнена, да и бизнес давит” — так и рождается техдолг и/или переусложенное решение.

СсылкаКомментировать

Недостатки закона Постела

Сам принцип звучит примерно так:

Будьте либеральны в том, что вы принимаете, и консервативны в том, что вы отправляете.

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

Если вкратце обобщить источники выше:

  • Если что-то “почти правильное” принималось без проблем, то оно может стать де-факто стандартом. Потом будут сюрпризы при использовании альтернативных реализаций, особенно если у них разный уровень толерантности к вводу. Похожая фигня случилась с URI/URL. Из-за этого возможно придется делать совместимость на уровне багов.
  • Нечеткая интерпретация спецификации может привести к уязвимостям и другим проблемам безопасности.
  • Толератность приводит к усложнению реализации: будут разные модели для ввода и вывода, ну и в целом надо будет поддерживать дополнительный код для исправления неточностей, количество которого потенциально может расти со временем для обеспечения взаимодействия с новыми реализациями.
  • Многие упускают аспект, что этот принцип нужен для исправления недостатков спецификации, но часто есть возможность улучшить саму спецификацию.
  • Если не глотать ошибки/недочеты, то их будет проще обнаружить, и будет обратная связь для протокола/спецификации.
  • Работать обычно проще с меньшей вариативностью, KISS и все такое.
СсылкаКомментировать