Категория: Компьютеры

Заметки о программировании и на околокомпьютерные темы

Вложенные категории: Delphi, Игры

О программировании

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

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

Из этого заблуждения возникает архитектурная астронавтика и боязнь хардкода. "Что, если эти обстоятельства изменятся? А если эти? А те?" Такой образ мыслей существует до тех пор, пока человек замечает обстоятельства избирательно; пока он не окинет свой код взглядом и не увидит, что всё в нём – это обстоятельства. Программа это закодированное условие, ограничение на полный произвол. Делая её "универсальнее", вы убираете часть условий, перекладываете их на плечи пользователя.

Например, вы пишете интерфейс доступа к базе данных. Ваша цель конкретна: каталог фильмов, режиссёров, актёров. Что сделает начинающий программист? Запросы "getMovie", "getActor", "getDirector" и так далее.
Но это неуниверсально! Что, если завтра в базе появятся книги? Другой программист предлагает: сделаем "getWork", "getPerson", у work будет параметр type (movie, book), а person будет по отношению к work иметь relation (актёр, режиссёр, автор книги).
Хорошая это идея? Ну, нормальная. Реализовывать её сложнее. Пользоваться ей сложнее! API слегка неочевиднее. Но действительно, очень полезно для расширения.
Третий программист говорит: Кто знает этих заказчиков! Сегодня они хотят одни поля, а завтра другие. Предлагаю сделать ещё универсальнее: getTable(name), getRecord(table, index), getField(record, index). Обратите внимание, какая универсальность! Мы можем хранить внутри таблицы фильмов и актёров, а можем автобусов и маршрутов. Мы можем хранить данные на сервере, а можем кешировать локально. Может прозрачно вводить любые отношения и ограничения!

Но этот универсальный интерфейс по сути не предоставляет никакого интерфейса. Вся сложность, все обстоятельства задачи легли на плечи пользователя. Универсальный интерфейс стал просто интерфейсом доступа к базе данных.
Архитектурным астронавтам это в голову не приходит, но ведь можно пойти ещё дальше. Кто сказал, что нам нужны таблицы и поля? А если завтра это изменится? Можно предоставить интерфейс "readBytes()" или "executeCode()". В таком случае пользователь может сам написать любой код, который будет работать с любыми данными, как ему вздумается!

Колхозная доктрина:
https://eax.me/kolkhoz-doctrine/

Экономика бесконечной разработки

Вот есть какое-нибудь Яндекс.Метро. Простое приложение для расчёта поездки. В последнее время оно показывает много рекламы. Понятно, почему: разработчикам надо платить. Поддержка на Google Play так и пишет: "благодаря рекламе оно продолжает жить и развиваться".

Сколько приложению нужно денег? Начнём с одного разработчика в месяц. Пусть даже он получает 300 тысяч. Или их несколько, но получают меньше, или работают не полную ставку. Неважно. Приложение установлено 150 тысяч раз, будем считать, 100 тысяч им пользуются. С каждого надо в месяц получить три рубля.
Нельзя ли вместо рекламы оплатить разработку прямо? Сколько это будет стоит? За год – 3*12=36 рублей + процент гугла = 50. Немного, но ощутимо каждый год, если таких приложений много.
А одной ставкой на 300 тысяч наверняка дело не обходится.

И тут возникает вопрос. А собственно, чем занимаются эти одна-две-три ставки на 300 тысяч? И нужно ли мне это?

Если подумать, мои интересы обычно противоположны. Я не хочу, чтобы приложение "развивалось". "Развитие" большинства приложений приносит мне только досаду и утрату привычных функций. Например, от Яндекс.Метро мне больше ничего не нужно. Я бы хотел, чтобы оно оставалось таким, какое есть. И я не хотел бы смотреть рекламу или каждый год платить за него. Удивительно, как эти интересы совпадают, и противоположны тому, что пользователь якобы должен хотеть!

Отчего же приложение не может быть таким? Ну, Яндекс.Метро приходится всё-таки следить за новыми станциями, хоть это не работа на полную ставку. Но почему какой-нибудь текстовый редактор или считалка калорий, то есть, приложения с простыми и понятными целями, не могут замереть и не тратить ни моих денег на разработку, ни моих нервов на обновления?
Почему мост можно построить и всё, а о приложениях стало модно думать как о бесконечно предоставляемой услуге?

Кто-то скажет: это тебя всё устраивает, а другим хочется большего. К тому же, автор желает делать своё приложение всё лучше и лучше. Почему он должен останавливаться на достигнутом?
В общем да. Но почему на достигнутом нельзя остановиться пользователю? Остановиться на той версии, которая устраивает. Больше ничего не платить.

И тут внезапно выясняется, что сделать это почти невозможно. Повсюду автоматические обновления. Вот система автоматических обновлений-то и внедряет в толпы привычку, что приложение это услуга. Да, можно выкачать пакет вручную, можно его сохранить, потом можно отключить обновления, переустанавливать из пакета… Но кто это будет делать?

Logrotate creates empty compressed log files

Case study: After some changes I've noticed logrotate flushes the main log (as it should) but all gzipped archived copies it creates are empty (20b). Logrotate destroys logs instead of preserving them.
You had one job, logrotate!

Turns out my logrotate file looked like this:

/var/log/httpd/*_log /custompath/log/*_log {
..
create ...
}

And the latter had been symlinked to the former.

It made sense when I wrote that. Cover all the bases. But the way logrotate works, it first scans all paths for files that need rotating and then applies rotation to them all.

So if I have /custompath/log/error_log reflected as /var/log/httpd/error_log, logrotate notices two files in need of rotation. It then compresses the first one, replaces it with empty log (create), then compresses the second one (now empty) and replaces the first .gz with an empty archive.

Nice job, logrotate. Make sure the collected filenames resolve to unique files? Nope. Maybe at least don't overwrite already existing gzips? Nope.

Tasks IG

У Гугла был удобный интерфейс к гугл-задачам, похожий на панель браузера. Назывался mail.google.com/tasks/ig. Разумеется, гугл его закрыл.
Убив больше времени, чем хотелось бы, я написал такое же с нуля:

https://github.com/himselfv/tasks-ig

  • Асинхронные запросы, как в старом клиенте
  • Дополнительный бэкенд, хранящий задачи в LocalStorage (впрочем, я бы всерьёз там задачи не хранил)
  • Когда-нибудь я напишу бэкенд на CalDAV Tasks, если никто не напишет
  • Можно написать отдельное расширение с бэкендом в extension storage, тогда ничего не надо будет хостить

Рабочую версию можно посмотреть на https://himselfv.github.io/tasks-ig/. К гуглу из неё подключиться вы не сможете, но локальные задачи работают.

Закон усреднения

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

Код, написанный хорошим программистом, обычно работает хорошо, и слабым программистам незачем его трогать. Они работают над другими вещами.

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

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

The Talos Principle

Portal от создателей Serious Sam, который набит попсовой философией. Интерес к этой игре проходит такие стадии:

1. Ох, игрой руководит Голос Бога. Это офигенно.
2. Ох, это Портал.
3. Ох, как же надоела эта унылая псевдофилософия. Особенно помощник Милтона. Бесцельные беседы с 3 неудачными вариантами ответа на каждом шаге это именно то, что убедительно передаёт ваши взгляды на сложные вопросы.
4. Ну ладно, так и быть, я найду все звёзды, пройду все дополнительные уровни, получу все концовки и ачивменты, только не подумайте, что я делаю это ради вас. Хмпф! Google: “как спасти помощника Милтона” “как спасти помощника Милтона, не проходя заново пол-игры” “talos principle быстрое прохождение”

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

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

Episode 3

Все читали пересказ сюжета Half-Life Episode 3, но делают разные выводы. Кое-кто пишет, что это хорошая концовка для серии и типа подходящая. Или что оставили задел под Half-Life 3 с Аликс.

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

Обратите внимание, что последний параграф написан для этого пересказа. Сюжет Episode 3 наверняка заканчивался на возвращении Фримена на Землю. А вот это “all the people I knew are gone” это уже приписка.

Если вычеркнуть последний абзац, то пересказ уже совсем не выглядит как “This is my last episode”. Просто закрытие арки Бореалиса и не более. Нормальный сюжет для третьего эпизода, почему его не сделали – я не понимаэ.

Изучаем хаскель

В последнее время пошла такая мода на форумах для программистов (в том числе реддит этим славен): публиковать статьи “Изучаем хаскель”, “Пишем свой первый трёхмерный движок”, “Пробуем читать ассемблер”.
И внутри автор действительно изучает хаскель, пишет свой первый трёхмерный движок и пробует читать ассемблер!
Понимаете? Не учит читателя, а сам изучает. И документирует свои неуклюжие первые шаги. Да кому это интересно? Зачем читать такую статью? Лучше уж разбираться самому.

В Скайриме герой может вступить в коллегию бардов. Барды это певцы, напоминаю. Играют на лютнях и поют песни. У бардов в коллегии свои комнаты. Можно заглянуть в них и посмотреть, как живут барды.
У большинства бардов на книжной полке стоит книга “Как убивать и не быть убитым”.

Viper

Выкладываю утилиту, которую написал сам для себя, но она разрослась. Может, кому-то пригодится:

Называется Viper, это менеджер служб с расширенными возможностями. Вот что он умеет:

  • Запуск/остановка/настройка служб пачками, по правой клавише.
  • Быстрый поиск, когда начинаете печатать название
  • Раскраска и подсветка, стили настраиваются
  • Редактирование прав доступа к службе, разблокировка защищённых (которые нельзя остановить)
  • Просмотр триггеров для каждой службы и их полный список
  • Службы можно разложить по папкам, переименовать, делать для себя примечания (хранятся в текстовых файлах).
  • Также показывает драйверы и службы-прототипы для Unistack-служб (они на самом деле называются USER_SERVICE).
  • Сохраняет/восстанавливает конфигурацию автозапуска служб, экспортирует службы, удаляет их

Вот ещё скриншоты

Качать отсюда

Если что у кого отвалится, то пишите, починю.