Почему у программистов ничего не получается даже с нейросетями

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

Полная зависимость от LLM вместо понимания

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

Отсутствие контекста и устаревшие практики

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

Избыточность, неэффективность и отсутствие профилирования

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

Нейросеть не проводит профилирование, не учитывает ограничения CPU и GPU, не заботится об утечках памяти. Она не анализирует, насколько эффективно выполняется код на практике. Оптимизация — это по-прежнему ручная работа, требующая анализа и экспертизы. Без неё приложения становятся медленными, нестабильными и ресурсоёмкими, даже если выглядят «правильно» с точки зрения структуры.

Уязвимости и угроза безопасности

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

Закон Парето и суть недоработки

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

Осторожный оптимизм

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

Нейросети — мощный инструмент. Но чтобы он работал на вас, а не против вас, нужна база, критическое мышление и готовность в любой момент взять управление в свои руки.

Gingerita Prototype Windows

Представляю вашему вниманию форк текстового редактора Kate под названием Gingerita. Почему форк, зачем, какая цель? Банально хочу добавить тот функционал который нужен мне в работе, чтобы при этом не ждать исправления, добавления фичей от команды Kate, или принятия моих исправлений в main ветку.
На текущий момент доступна версия прототип для Windows, практически ванильная версия Kate с минимальными изменениями. Для Gingerita я разработал два плагина – просмоторщик изображений прямо из редактора и встроенный браузер, для отладки своих веб проектов или для взаимодействия с ИИ помощниками такими как ChatGPT.

Версию для Windows можно опробовать по ссылке ниже:
https://github.com/demensdeum/Gingerita/releases/tag/prototype

Поддержка продуктов Demensdeum

Добро пожаловать на страницу поддержки!

Если у вас возникли вопросы, проблемы с продуктами Demensdeum или вы хотите предложить улучшения, мы всегда готовы помочь.

Как связаться с нами:
support@demensdeum.com

Мы стараемся отвечать на обращения в течение 3-5 рабочих дней.

Что указать в письме:

Название продукта
Версию (если известна)
Подробное описание проблемы
Скриншоты или видео (если возможно)
Устройство и операционную систему, на которой возникла проблема

Мы благодарим вас за использование наших продуктов и стремимся сделать ваш опыт максимально удобным и приятным.

С уважением,
Команда Demensdeum

Vibe-кодерские трюки: почему LLM пока не работают с SOLID, DRY и CLEAN

С развитием больших языковых моделей (LLM), таких как ChatGPT, всё больше разработчиков используют их для генерации кода, проектирования архитектуры и ускорения интеграции. Однако при практическом применении становится заметно: классические принципы архитектуры — SOLID, DRY, CLEAN — плохо уживаются с особенностями кодогенерации LLM.

Это не значит, что принципы устарели — напротив, они прекрасно работают при ручной разработке. Но с LLM подход приходится адаптировать.

Почему LLM не справляются с архитектурными принципами

Инкапсуляция

Инкапсуляция требует понимания границ между частями системы, знания о намерениях разработчика, а также следования строгим ограничениям доступа. LLM же часто упрощают структуру, делают поля публичными без причины или дублируют реализацию. Это делает код более уязвимым к ошибкам и нарушает архитектурные границы.

Абстракции и интерфейсы

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

DRY (Don’t Repeat Yourself)

LLM не стремятся минимизировать повторяющийся код — напротив, им проще дублировать блоки, чем выносить общую логику. Хотя они могут предложить рефакторинг по запросу, по умолчанию модели склонны генерировать «самодостаточные» фрагменты, даже если это приводит к избыточности.

CLEAN Architecture

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

Что работает лучше при работе с LLM

WET вместо DRY
Подход WET (Write Everything Twice) оказывается практичнее в работе с LLM. Дублирование кода не требует от модели удержания контекста, а значит — результат предсказуемее и легче исправляется вручную. Это также снижает вероятность появления неочевидных связей и багов.

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

Простые структуры вместо инкапсуляции

Избегая сложной инкапсуляции и полагаясь на прямую передачу данных между частями кода, можно значительно упростить как генерацию, так и отладку. Это особенно актуально при быстрой итеративной разработке или создании MVP.

Упрощённая архитектура

Простая, плоская структура проекта с минимальным количеством зависимостей и абстракций даёт более стабильный результат при генерации. Модель легче адаптирует такой код и реже нарушает ожидаемые связи между компонентами.

Интеграция SDK — вручную надёжнее

Большинство языковых моделей обучены на устаревших версиях документации. Поэтому при генерации инструкций по установке SDK часто появляются ошибки: устаревшие команды, неактуальные параметры или ссылки на недоступные ресурсы. Практика показывает: лучше всего использовать официальную документацию и ручную настройку, оставляя LLM вспомогательную роль — например, генерацию шаблонного кода или адаптацию конфигураций.

Почему принципы всё же работают — но при ручной разработке

Важно понимать, что сложности с SOLID, DRY и CLEAN касаются именно кодогенерации через LLM. Когда разработчик пишет код вручную, эти принципы продолжают демонстрировать свою ценность: снижают связанность, упрощают сопровождение, повышают читаемость и гибкость проекта.

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

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

Вывод

Большие языковые модели — полезный инструмент в разработке, особенно на ранних стадиях или при создании вспомогательного кода. Но важно адаптировать к ним подход: упростить архитектуру, ограничить абстракции, избегать сложных зависимостей и не полагаться на них при настройке SDK.

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

Demens TV Heads NFT

Хочу поделиться своим новым проектом — NFT-коллекцией “Demens TV Heads”.

Это серия цифровых арт-работ, в них отражены люди разных характеров и профессий, в стиле логотипа DemensDeum.
Первая работа – Fierce “Грозный” это стилизованный автопортрет.

Планирую выпустить всего 12 NFT, по одной каждый месяц.

Каждая работа существует не только в Ethereum-блокчейне, но и доступна на сайте DemensDeum и в GitHub-репозитории, вместе с метаданными.

Если интересно — посмотреть или просто оценить визуально, буду рад:
https://opensea.io/collection/demens-tv-heads
https://github.com/demensdeum/demens-tv-heads-collection
https://demensdeum.com/collections/demens-tv-heads/fierce.png
https://demensdeum.com/collections/demens-tv-heads/fierce-metadata.txt

Суперпрограммист

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

1. Пишет на C/C++ без единой уязвимости
buffer overflow? never heard of it.
У Суперпрограммиста в C++ нет неинициализированных переменных — они сами инициализируются от уважения. Он пишет new char[256], и компилятор молча добавляет проверку границ. Где другие ставят брейкпоинт — он ставит взгляд. И баг исчезает.

2. Пишет фичи без багов и тестирования
Он не нуждается в тестах. Его код сам себя тестирует по ночам, когда он спит (хотя… спит ли он?). Любая строка — это финальная стабильная версия, сразу с поддержкой 12 языков и Accessibility уровня NASA. А если баг всё же попался — значит, Вселенная тестирует его.

3. Работает быстрее, чем AI
Пока ChatGPT печатает “Какой хороший вопрос!”, Суперпрограммист уже зарелизил новую OS, портировал её на тостер и задокументировал всё в Markdown с диаграммами. Он не спрашивает StackOverflow — он его поддерживает своими вопросами из будущего. GPT учится на его коммитах.

4. Понимает чужой код лучше, чем автор
“Я, конечно, это писал… Но я не понимаю, как это работает.” — обычный автор.
“О, это из-за рекурсивного вызова в строке 894, который завязан на побочный эффект в Regex-фильтре. Умно.” — Суперпрограммист, не моргнув.
Он читает Perl с первой попытки, понимает аббревиатуры в названиях переменных, а баги улавливает по вибрации курсора.

5. Пишет на ассемблере кроссплатформенный код
Зачем писать на Rust, если можно на чистом x86, ARM и RISC-V сразу, с флагом “работает везде”? У него своя таблица опкодов. Даже CPU задумываются перед тем, как испортить его инструкции. Он не оптимизирует — он трансцендентирует.

6. Отвечает на вопросы о сроках вплоть до секунды
“Когда будет готово?”
“Через 2 часа, 17 минут и 8 секунд. И да, это с учётом багов, перекура и одного философского вопроса в чатике.”
Если кто-то просит сделать быстрее — он просто перестраивает пространство-время через make -j∞.

7. Реверсит и чинит проприетарные фреймворки
Проприетарный SDK отвалился, API без документации, всё шифруется Base92 и кашляет SEGFAULT’ами? Для Суперпрограммиста это обычный вторник. Он откроет бинарник, вдохнёт HEX, и спустя час уже будет патч с фиксом, улучшениями производительности и добавленным dark mode.

8. Сам себе дизайнер и UX-специалист
UI у него выходит такой, что люди плачут от красоты, а кнопки угадываются интуицией. Даже кошки справляются — проверено. Он не рисует интерфейс — он открывает его внутреннюю суть, как скульптор в мраморе. Каждое нажатие вызывает восторг.

9. Проводит маркетинговые исследования между коммитами
Между git push и coffee break он успевает собрать аналитику рынка, построить воронку продаж и переосмыслить стратегию монетизации. По выходным тестирует гипотезы. У него A/B тесты запускаются автоматически, когда он открывает ноутбук.

10. Повторяет Microsoft в одиночку
Что для корпораций 10 лет и тысяча инженеров, для него — вечер пятницы и хорошая пицца. Windows 11? Сделал Windows 12. Office? Уже есть. Excel? Работает на голосовом управлении и помогает планировать отпуск. Всё работает лучше и весит меньше.

11. Разворачивает и поддерживает инфраструктуру на 1 миллион пользователей
Его домашний NAS — это Kubernetes-кластер. Мониторинг? Grafana с мемами. Он разворачивает API быстрее, чем некоторые успевают открыть Postman. У него всё задокументировано, автоматизировано и надёжно как советский чайник.

12. Техподдержка не требуется
Пользователи его ПО не жалуются. Они просто используют его с благоговением. FAQ? Не нужен. Туториалы? Интуиция подскажет. Он — единственный разработчик, у кого кнопка “Help” ведёт на страницу благодарности.

13. Не спит, не ест, не отвлекается
Он питается кофеином и чистым желанием писать код. Вместо сна — рефакторинг. Вместо еды — debian packages. Его жизненный цикл — это непрерывный цикл разработки. CI/CD — это не pipeline, это стиль жизни.

14. Общается с заказчиками без боли
“Нам надо сделать Uber, но только лучше, за два дня.” — “Смотрите: вот roadmap, вот риски, вот MVP. И давайте вы сначала определитесь с целями.”
Он умеет говорить “нет” так, что заказчик отвечает: “Спасибо, теперь я понял, чего я хочу.”

15. Моментально программирует ядерные реакторы
Сколько тепла выделяется при расщеплении ядра урана? Суперпрограммист знает. И умеет это закодить в Rust, C, Swift, даже в Excel. Его реактор не только безопасен — он ещё и обновляется по OTA.

16. Обладает знаниями во всех возможных областях
Философия, физика, налоговая отчётность Монголии — всё у него в голове. Он участвует в викторинах, где сам себе ведущий. Если чего-то не знает — просто временно выключил память, чтобы освободить место под новые знания. Сейчас вернёт.

17. Знает все алгоритмы и паттерны проектирования
Не надо объяснять ему, как работает A*, Dijkstra или Singleton. Он сам их придумал. С ним паттерны ведут себя правильно. Даже антипаттерны исправляются сами — от стыда.

18. Работал в Apple, Google и ушёл от скуки
Он был везде: Apple, Google, NASA, IKEA (тестировал интерфейс шкафов). Потом понял, что уже слишком хорош, и ушёл разрабатывать бесплатные open-source проекты ради удовольствия. Деньги ему не нужны, потому что:

19. У него пресид биткоина и он — Сатоши Накамото
Да, это он. Просто не говорит. Все кошельки с миллионами BTC на самом деле у него на флешке, замурованной в бетон. А пока он пишет backend для фермерского кооператива в глубинке, потому что “интересно же было попробовать Kotlin Multiplatform”.

Заключение: немного серьёзности
На самом деле, программисты — обычные люди.
Мы ошибаемся. Мы устаём. Иногда мы настолько уверены в себе, что не видим очевидного — и именно тогда совершаются самые дорогие ошибки в истории IT.

Поэтому стоит помнить:

* Знать всё невозможно — но важно знать, где искать.
* Работа в команде — это не слабость, а путь к лучшему решению.
* Инструменты, которые нас оберегают — не “костыли”, а броня.
* Спрашивать — нормально. Сомневаться — правильно. Ошибаться — неизбежно. Учиться — необходимо.
* Ирония — наш щит. Код — наше оружие. Ответственность — наш компас.

А легенды про Суперпрограммиста — это напоминание, что все мы иногда стремимся к невозможному. И именно в этом — настоящая магия программирования.

Почему документация — ваш лучший друг

(и как не оказаться гуру, чьи советы перестают работать после обновления)

“Apps may only use public APIs and must run on the currently shipping OS.” Apple App Review Guidelines

Если вы когда-либо начинали работу с новым фреймворком и ловили себя на мысли: “Сейчас всё сам пойму, документация — это для зануд” — вы точно не одиноки. У многих разработчиков срабатывает естественный инстинкт: сначала попробовать, и только потом — читать. Это нормально.

Но именно на этом этапе можно легко свернуть с правильного пути и оказаться в ситуации, где код работает… но только сегодня, и только “у меня”.

Почему просто “разобраться самому” — недостаточно?

Фреймворки, особенно закрытые и проприетарные, сложны и многослойны. В них много скрытой логики, оптимизаций и особенностей реализации, которые:

* не задокументированы;
* не гарантированы;
* могут измениться в любой момент;
* являются коммерческой тайной и могут быть защищены патентами
* содержат баги, недоработки, которые известны только разработчикам фреймворка.

Когда вы действуете “по наитию”, можно легко построить архитектуру на случайных наблюдениях, вместо опоры на чётко описанные правила. Это приводит к тому, что код становится уязвимым к обновлениям и edge-кейсам.

Документация — это не ограничение, а опора

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

* стабильность;
* поддержку;
* предсказуемое поведение.

Если вы выходите за эти рамки — всё, что произойдёт дальше, становится исключительно вашей ответственностью.

Эксперименты? Конечно. Но в рамках правил.
Любопытство — суперсила разработчика. Исследовать, пробовать нестандартное, тестировать границы — всё это необходимо. Но здесь есть важное “но”:

Экспериментировать нужно в рамках документации и best practices.

Документация — это не тюрьма, а карта. Она показывает, какие возможности действительно запланированы и поддерживаются. Именно такие эксперименты — не только полезны, но и безопасны.

Осторожно: Гуру

Иногда вы можете столкнуться с настоящими “экспертами”:

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

Но даже если они звучат убедительно, важно помнить:
если их подходы противоречат документации — они неустойчивы.

Такие “эмпирические паттерны” могут:

* работать только на конкретной версии фреймворка;
* быть уязвимыми к обновлениям;
* ломаться в непредсказуемых ситуациях.

Гуру — это круто, когда они уважают мануалы. В противном случае — их советы нужно фильтровать через официальную документацию.

Немного SOLID

Три идеи из принципов SOLID особенно актуальны здесь:

* Open/Closed Principle: расширяй поведение через публичные API, не лезь во внутренности.
* Liskov Substitution Principle: не полагайся на реализацию, полагайся на контракт. Нарушишь — всё сломается при замене реализации.
* Dependency Inversion: Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба типа должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

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

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

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

А если баг?

Иногда бывает, что вы всё сделали правильно, но работает некорректно. Это бывает — фреймворки не идеальны. В таком случае:

* Соберите минимальный воспроизводимый пример.
* Убедитесь, что вы используете только задокументированные API.
* Отправьте баг-репорт — вас точно поймут и, скорее всего, помогут.

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

Как выжать максимум из фреймворка

* Читайте документацию. Серьёзно.
* Следуйте гайдам и рекомендациям от авторов.
* Экспериментируйте — но в пределах описанного.
* Проверяйте советы (даже самых известных спикеров!) через мануал.
* Отлаживайте баги с минимальными кейсами и уважением к контракту.

Заключение

Фреймворки — это не чёрные ящики, а инструменты, у которых есть правила использования. Игнорировать их — значит писать код “на авось”. А мы ведь хотим, чтобы наш код жил долго, радовал пользователей, и не ломался от минорного апдейта.

Так что: доверяйте, но проверяйте. И да, читайте мануалы. Они — ваша суперспособность.

Источники

https://developer.apple.com/app-store/review/guidelines/
https://en.wikipedia.org/wiki/SOLID
https://en.wikipedia.org/wiki/API
https://en.wikipedia.org/wiki/RTFM

Cube Art Project 2

Встречайте — Cube Art Project 2

Вторая версия воксельного редактора, полностью переписанная на чистом JavaScript без WebAssembly.
Лёгкий, быстрый и запускается прямо в браузере — ничего лишнего.

Это эксперимент: кубики, цвет, свобода и немного медитативной 3D-геометрии.
Можно менять цвета с помощью RGB-слайдеров, сохранять и загружать сцены, перемещаться по пространству и просто играться.

Управление:
— WASD — перемещение камеры
— Мышь — вращение
— GUI — настройка цвета

Онлайн:
https://demensdeum.com/software/cube-art-project-2/

Исходники на GitHub:
https://github.com/demensdeum/cube-art-project-2

Проект написан на чистом JavaScript с использованием Three.js.
Без фреймворков, без сборщиков, без WebAssembly — только WebGL, шейдеры и немного любви к пиксельной геометрии.

Сцены можно сохранять и загружать — создавайте свои миры, сохраняйте как JSON, делитесь или возвращайтесь позже к доработке.

Безопасность Docker: почему запуск от root — это плохая идея

Docker стал незаменимым инструментом в современном DevOps и разработке. Он позволяет изолировать окружения, упрощать деплой и быстро масштабировать приложения. Однако по умолчанию Docker требует root-доступа, и это создает потенциально опасную зону, которую часто игнорируют на ранних этапах.

Почему Docker работает от root?

Docker использует возможности ядра Linux: cgroups, namespaces, iptables, mount, networking и другие системные функции. Эти операции доступны только суперпользователю.

Вот почему:
* демон dockerd запускается от root,
* команды docker передаются этому демону.

Это упрощает работу и даёт полный контроль над системой, но вместе с этим и открывает потенциальные уязвимости.

Чем это опасно: container breakout, CVE, RCE

Container breakout

При слабой изоляции злоумышленник может использовать chroot или pivot_root для выхода на хост.

Примеры реальных атак:

* CVE-2019-5736 — уязвимость в runc, позволяла перезаписать приложение и выполнить код на хосте.
* CVE-2021-3156 — уязвимость в sudo, позволяла получить root внутри контейнера и выбраться наружу.

RCE (Remote Code Execution)

Если приложение в контейнере уязвимо и запускается от root, RCE = полный контроль над хостом.

Rootless Docker: решение проблемы

Чтобы минимизировать эти риски, в Docker появился rootless-режим. В этом режиме и демон, и контейнеры запускаются от имени обычного пользователя, без каких-либо root-привилегий. Это означает, что даже если злоумышленник получит контроль над контейнером, он не сможет навредить хостовой системе.
Есть и ограничения: нельзя использовать порты ниже 1024 (например, 80 и 443), недоступен режим –privileged, а также некоторые сетевые режимы. Однако в большинстве сценариев разработки и CI/CD rootless Docker прекрасно справляется со своей задачей и значительно повышает уровень безопасности.

Исторически запуск от root — антипаттерн

В мире UNIX/Linux с самого начала действует принцип наименьших привилегий. Чем меньше прав у процесса — тем меньше вреда он может нанести. Docker изначально требовал root-доступ, но сегодня это считается потенциальной угрозой.

Источники

https://docs.docker.com/engine/security/rootless/
https://rootlesscontaine.rs/

Неочевидная проблема Docker-контейнеров: скрытые уязвимости

Неочевидная проблема Docker-контейнеров: скрытые уязвимости

Что такое “Dependency Hell” (DH)?

“Dependency Hell” (DH) — это термин, обозначающий проблему, возникающую при управлении зависимостями в программном обеспечении. Основные её причины заключаются в конфликте версий, сложностях интеграции различных библиотек и необходимости поддерживать совместимость между ними. В DH входят следующие аспекты:

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

Важно отметить, что хотя устранение уязвимостей является одной из причин выпуска обновленных версий библиотек, оно не является главной движущей силой возникновения DH. Основная проблема заключается в том, что каждое изменение — будь то исправление багов, добавление нового функционала или устранение уязвимости — может вызвать цепочку зависимостей, усложняющих стабильное развитие и поддержку приложения.

Как борьба с DH привела к созданию Docker?

В попытке решить проблемы DH разработчики искали способы создать изолированные и стабильные окружения для приложений. Docker стал ответом на этот вызов. Контейнеризация позволяет:

– Изолировать окружение: Все зависимости и библиотеки упаковываются вместе с приложением, что гарантирует стабильную работу в любом месте, где установлен Docker.
– Упрощать развертывание: Разработчик может один раз настроить окружение и использовать его для развертывания на любых серверах без дополнительных настроек.
– Минимизировать конфликты: Поскольку каждое приложение работает в собственном контейнере, риск конфликтов между зависимостями различных проектов существенно снижается.

Таким образом, Docker предложил эффективное решение для борьбы с проблемой DH, позволив разработчикам сосредоточиться на логике приложения, а не на сложностях настройки окружения.

Проблема устаревших зависимостей в Docker

Несмотря на все преимущества Docker, появилось новое направление проблем — устаревание зависимостей. Это происходит по нескольким причинам:

1. Контейнер застывает во времени

При создании Docker-образа фиксируется определённое состояние всех пакетов и библиотек. Даже если после сборки в базовом образе (например, `ubuntu:20.04`, `python:3.9`, `node:18-alpine`) обнаруживаются уязвимости или выпускаются новые версии, контейнер продолжает работать с изначально установленными версиями. Если образ не пересобирать, приложение может годами работать с устаревшими и потенциально уязвимыми компонентами.

2. Отсутствие автоматических обновлений

В отличие от традиционных серверов, где можно настроить автоматическое обновление пакетов через системные менеджеры (например, `apt upgrade` или `npm update`), контейнеры не обновляются автоматически. Обновление происходит только при пересборке образа, что требует дисциплины и регулярного контроля.

3. Фиксированные версии зависимостей

Чтобы обеспечить стабильность, разработчики часто фиксируют версии зависимостей в файлах вроде `requirements.txt` или `package.json`. Такой подход предотвращает неожиданные изменения, но одновременно замораживает состояние зависимостей, даже если в них впоследствии обнаруживаются ошибки или уязвимости.

4. Использование устаревших базовых образов

Базовые образы, выбранные для контейнеров, тоже могут со временем устаревать. Например, если приложение построено на образе `node:16`, а разработчики уже перешли на `node:18` из-за улучшений и исправлений, то ваше окружение останется с устаревшей версией, даже если внутри кода всё работает корректно.

Как избежать проблем с устаревшими зависимостями?

Включите в процесс CI/CD регулярные проверки на наличие устаревших зависимостей и уязвимостей:

– Для Python:

pip list --outdated

– Для Node.js:

npm outdated

– Используйте инструменты для анализа уязвимостей, например, `trivy`:

trivy image my-app

Следить за обновлениями базовых образов

Подписывайтесь на обновления базовых образов в Docker Hub или соответствующих репозиториях на GitHub, чтобы своевременно узнавать о критических исправлениях и обновлениях.

Заключение

Проблема Dependency Hell возникла не только из-за необходимости устранять уязвимости, но и как следствие сложностей в управлении и обновлении зависимостей. Docker предложил эффективное решение для борьбы с DH, обеспечив изолированные и стабильные окружения для приложений. Однако, с появлением контейнеризации возникла новая задача — необходимость регулярного обновления образов, чтобы не допустить устаревания зависимостей и появления критических уязвимостей.

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

Паттерн Builder: Поэтапное создание объекта во времени

Введение

В прошлой статье рассматривался общий случай использования паттерна Builder, но не затрагивался вариант, когда объект создается поэтапно во времени.
Паттерн Builder (Строитель) – это порождающий шаблон проектирования, который позволяет поэтапно создавать сложные объекты. Он особенно полезен, когда объект имеет много параметров или различных конфигураций. Одним из интересных примеров его использования является возможность разделения процесса создания объекта по времени.
Иногда объект нельзя создать сразу – его параметры могут становиться известными на разных этапах выполнения программы.

Пример на Python

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

import requests

def fetch_car_data():
    response = requests.get("https://api.example.com/car-info")
    return response.json()

builder = CarBuilder()

# Backend API data
car_data = fetch_car_data()
builder.set_model(car_data["model"])
builder.set_year(car_data["year"])

# User input
color = input("Car color: ")
builder.set_color(color)

gps_option = input("GPS feature? (yes/no): ").lower() == "yes"
builder.set_gps(gps_option)

car = builder.build()
print(car)

Представьте что вызов api, ввод данных происходят в разных частях приложения, или даже в разных библиотеках. Тогда использование паттерна Builder становится более очевидным, чем в простом примере выше.

Преимущества

– На выходе получается иммутабельная структура, которой не требуется хранить опциональные данные для временной сборки
– Объект собирается постепенно
– Избежание сложных конструкторов
– Код сборки объекта инкапсулируется лишь в одной сущности Builder
– Удобство понимания кода

Источники

https://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional-ebook/dp/B000SEIBB8
https://demensdeum.com/blog/2019/09/23/builder-pattern/

DemensDeum Coding Challenge #1

Стартую DemensDeum Coding Challenge #1
Приз 100 USDT
1. Надо написать рендер картинки для Windows 11 64 bit
2. Рендерить
https://demensdeum.com/logo/demens1.png
3. Картинка должна быть интегрирована в приложение
4. Графические API – Direct3D или DirectDraw
5. Выигрывает тот чье приложение получился самым малым по размеру в байтах
6. Изображение должно быть 1 в 1 попиксельно как оригинальное, сохранить цвета
7. Любые языки/фреймворки не требующие дополнительной установки -> чтобы можно было запустить сразу из приложения. Например если решение только один Python скрипт, то такое решение не подходит т.к. требуется установка Python, Pygame и запуск вручную. Хороший пример: Python скрипт завернутый вместе с Python и Pygame в exe, который запускается без дополнительных установок.
8. Сдавать в форме ссылки на публичный репозиторий с исходным кодом, инструкцией по сборке приложения. Хороший пример: проект с инструкцией по сборке в Visual Studio Community Edition

Дедлайн: 1 июня подведение итогов конкурса

Референсное решение на Zig + SDL3 + SDL3_Image:
https://github.com/demensdeum/DemensDeum-Coding-Challenge-1

Ghost Contacts

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

Приложение онлайн:
https://demensdeum.com/software/ghost-contacts/

GitHub:
https://github.com/demensdeum/GhostContacts

Почему я выбрал WordPress

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

Преимущества WordPress

  • Простота использования
    Одной из главных причин, почему я выбрал WordPress, является его интуитивно понятный интерфейс. Даже если вы никогда раньше не работали с CMS, освоить WordPress можно за считанные дни.
  • Огромное количество плагинов
    WordPress предоставляет доступ к тысячам бесплатных и платных плагинов. Эти расширения позволяют добавить практически любую функциональность, связанную с ведением блога, от SEO-оптимизации до интеграции социальных сетей.
  • Масштабируемость
    WordPress отлично подходит для блогов любого масштаба. Начав с простого личного блога, я знаю, что могу легко развивать его, добавляя новые функции и возможности.
  • Широкий выбор тем
    На WordPress доступно огромное количество бесплатных и платных тем, которые позволяют создать достаточно хорошо выглядящий блог в короткие сроки. Для создания индивидуального дизайна потребуется чуткая рука дизайнера.
  • SEO-дружественность
    WordPress изначально настроен на дружелюбие к поисковым системам. С помощью плагинов, таких как Yoast SEO, можно легко оптимизировать контент для улучшения его позиций в поисковой выдаче.
  • Сообщество и поддержка
    У WordPress одно из крупнейших сообществ в мире. Если у вас возникнет проблема, вы почти наверняка найдёте решение на форумах или в блогах, посвящённых платформе.
  • Поддержка мультиязычности
    Благодаря плагинам вроде WPGlobus я могу вести блог на нескольких языках, что особенно важно для работы с аудиторией из разных стран.

Недостатки WordPress

  • Уязвимость к атакам
    Популярность WordPress делает его мишенью для хакеров. Без надлежащей защиты сайт может стать жертвой атак. Однако регулярные обновления и установка плагинов безопасности помогают минимизировать риски.
  • Зависимость от плагинов
    Иногда функциональность, которую вы хотите добавить, требует установки множества плагинов. Это может замедлить работу блога и вызвать конфликты между расширениями.
  • Сложности с производительностью
    На больших блогах WordPress может начать тормозить, особенно если используется много плагинов. Для решения этой проблемы приходится оптимизировать базу данных, внедрять кэширование и использовать более мощный хостинг.
  • Стоимость некоторых функций
    Хотя базовая версия WordPress бесплатна, многие профессиональные темы и плагины стоят денег. Для получения всех возможностей иногда приходится инвестировать.

Заключение

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

Wordex — программа для скорочтения на iOS

Недавно нашел приложение для скорочтения, которое хочу порекомендовать вам.

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

Что такое Wordex?

Wordex — это приложение для iOS, разработанное специально для развития навыков скорочтения. Оно помогает пользователям читать тексты быстрее, фокусироваться на ключевых идеях и избегать отвлекающих факторов. Программа основана на научных подходах и предлагает удобные инструменты для повышения скорости чтения.

Основные возможности Wordex

  • Режим скорочтения: текст отображается оптимизированно для быстрого восприятия. Пользователи могут регулировать скорость отображения текста в зависимости от своих потребностей.
  • Анализ прогресса: программа предоставляет подробную статистику, включая скорость чтения и динамику улучшений. Это помогает оценивать свои успехи и корректировать подход к чтению.
  • Импорт текстов: Wordex позволяет загружать собственные тексты для тренировки. Вы можете читать статьи, книги или учебные материалы прямо в приложении.
  • Интуитивно понятный интерфейс: приложение выполнено в минималистичном стиле, что делает его удобным для использования. Даже новички легко разберутся с функционалом.


Wordex Screenshot 1

Кому подойдет Wordex?

Wordex идеально подходит:

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


Wordex Screenshot 2

Преимущества Wordex

  • Мобильность: вы можете заниматься в любом месте и в любое время благодаря приложению на iPhone или iPad.
  • Персонализация: возможность настроить отображение текста под свои потребности.


Wordex Screenshot 3

Почему стоит попробовать Wordex?

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

Заключение

Если вы хотите освоить скорочтение или улучшить существующие навыки, Wordex — отличный выбор. Простое в использовании и эффективное приложение поможет вам достичь ваших целей и сэкономить драгоценное время. Скачайте Wordex из App Store и начните тренироваться уже сегодня!

AppStore:
https://apps.apple.com/us/app/speed-reading-book-reader-app/id1462633104

Почему важен DRY

Существует множество статей на тему DRY, я рекомендую прочитать первоисточник “Программист-прагматик” за авторством Andy Hunt и Dave Thomas. Однако я всё равно вижу как у множества разработчиков вызывает вопросы данный принцип в разработке программного обеспечения.

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

class Client {
    public let name: String
    private var messages: [String] = []
    
    init(name: String) {
        self.name = name
    }
    
    func receive(_ message: String) {
        messages.append(message)
    }
}

class ClientController {
    func greet(client: Client?) {
        guard let client else {
            debugPrint("No client!")
            return
        }
        client.receive("Hello \(client.name)!")
    }

    func goodbye(client: Client?) {
        guard let client else {
            debugPrint("No client!!")
            return
        }
        client.receive("Bye \(client.name)!")
    }
}

Как можно увидеть в методе greet и goodbye передается опциональный инстанс класса Client, который затем нужно проверять на nil, после чего начинать работу с ним. Чтобы соблюсти метод DRY, нужно убрать повторяющуюся проверку на nil для инстанса класса. Реализовать это можно множеством путей, один из вариантов это передавать инстанс в конструктор класса, после чего необходимость в проверках отпадет.

Соблюдаем DRY с помощью специализации ClientController на единственном инстансе Client:

class Client {
    public let name: String
    private var messages: [String] = []
    
    init(name: String) {
        self.name = name
    }
    
    func receive(_ message: String) {
        messages.append(message)
    }
}

class ClientController {
    private let client: Client

    init(client: Client) {
        self.client = client
    }

    func greet() {
        client.receive("Hello \(client.name)!")
    }

    func goodbye() {
        client.receive("Bye \(client.name)!")
    }
}

Также DRY касается процессов которые происходят во время разработки программного обеспечения. Представим ситуацию при которой команде разработчиков приходится выкладывать релиз в маркет самостоятельно, отвлекая их от разработки ПО, это тоже нарушение DRY. Такая ситуация разрешается с помощью подключения CI/CD пайплайна, при котором релиз выпускается автоматически, при соблюдении определенных условий разработчиками.

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

У Стива Джобса было выражение “Строка кода, которую не пришлось писать, — это строка кода, которую вам никогда не придется дебажить.”

Источники

https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/
https://youtu.be/-msIEOGvTYM

Я помогу вам в разработке iOS для Swift или Objective-С

Рад сообщить, что теперь я предлагаю свои услуги как iOS-разработчик на Fiverr. Если вам нужна помощь в разработке качественных iOS-приложений или улучшении существующих проектов, ознакомьтесь с моим профилем:
https://www.fiverr.com/s/Q7x4kb6

Буду рад возможности поработать над вашим проектом.
Email: demensdeum@gmail.com
Telegram: https://t.me/demensdeum

Динамическая линковка Qt приложений на macOS

Сегодня я выпустил версию RaidenVideoRipper для устройств Apple с macOS и процессоров M1/M2/M3/M4 (Apple Silicon). RaidenVideoRipper это приложение для быстрого монтажа видео, которое позволяет вырезать часть видеофайла в новый файл. Также можно делать gif, экспортировать звуковую дорожку в mp3.

Далее я коротко опишу какие команды я использовал для того чтобы это осуществить. Теорию того что здесь происходит, документацию утилит, можно прочитать по следующим ссылкам:
https://www.unix.com/man-page/osx/1/otool/
https://www.unix.com/man-page/osx/1/install_name_tool/
https://llvm.org/docs/CommandGuide/llvm-nm.html
https://linux.die.net/man/1/file
https://www.unix.com/man-page/osx/8/SPCTL/
https://linux.die.net/man/1/chmod
https://linux.die.net/man/1/ls
https://man7.org/linux/man-pages/man7/xattr.7.html
https://doc.qt.io/qt-6/macos-deployment.html

Для начала установите Qt на свою macOS, также установите окружение для Qt Desktop Development. После этого соберите свой проект например в Qt Creator, далее я опишу что нужно для того чтобы зависимости с внешними динамическими библиотеками корректно отрабатывали при дистрибутизации приложения конечным пользователям.

Создайте в папке YOUR_APP.app/Contents вашего приложения директорию Frameworks, сложите в нее внешние зависимости. Для примера так выглядит Frameworks для приложения RaidenVideoRipper:

Frameworks
├── DullahanFFmpeg.framework
│   ├── dullahan_ffmpeg.a
│   ├── libavcodec.60.dylib
│   ├── libavdevice.60.dylib
│   ├── libavfilter.9.dylib
│   ├── libavformat.60.dylib
│   ├── libavutil.58.dylib
│   ├── libpostproc.57.dylib
│   ├── libswresample.4.dylib
│   └── libswscale.7.dylib
├── QtCore.framework
│   ├── Headers -> Versions/Current/Headers
│   ├── QtCore -> Versions/Current/QtCore
│   ├── Resources -> Versions/Current/Resources
│   └── Versions
├── QtGui.framework
│   ├── Headers -> Versions/Current/Headers
│   ├── QtGui -> Versions/Current/QtGui
│   ├── Resources -> Versions/Current/Resources
│   └── Versions
├── QtMultimedia.framework
│   ├── Headers -> Versions/Current/Headers
│   ├── QtMultimedia -> Versions/Current/QtMultimedia
│   ├── Resources -> Versions/Current/Resources
│   └── Versions
├── QtMultimediaWidgets.framework
│   ├── Headers -> Versions/Current/Headers
│   ├── QtMultimediaWidgets -> Versions/Current/QtMultimediaWidgets
│   ├── Resources -> Versions/Current/Resources
│   └── Versions
├── QtNetwork.framework
│   ├── Headers -> Versions/Current/Headers
│   ├── QtNetwork -> Versions/Current/QtNetwork
│   ├── Resources -> Versions/Current/Resources
│   └── Versions
└── QtWidgets.framework
    ├── Headers -> Versions/Current/Headers
    ├── QtWidgets -> Versions/Current/QtWidgets
    ├── Resources -> Versions/Current/Resources
    └── Versions

Для упрощения я распечатал только второй уровень вложенности.

Далее печатаем текущие динамические зависимости вашего приложения:

otool -L RaidenVideoRipper 

Вывод для бинарика RaidenVideoRipper, который лежит в RaidenVideoRipper.app/Contents/MacOS:

RaidenVideoRipper:
	@rpath/DullahanFFmpeg.framework/dullahan_ffmpeg.a (compatibility version 0.0.0, current version 0.0.0)
	@rpath/QtMultimediaWidgets.framework/Versions/A/QtMultimediaWidgets (compatibility version 6.0.0, current version 6.8.1)
	@rpath/QtWidgets.framework/Versions/A/QtWidgets (compatibility version 6.0.0, current version 6.8.1)
	@rpath/QtMultimedia.framework/Versions/A/QtMultimedia (compatibility version 6.0.0, current version 6.8.1)
	@rpath/QtGui.framework/Versions/A/QtGui (compatibility version 6.0.0, current version 6.8.1)
	/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 2575.20.19)
	/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO (compatibility version 1.0.0, current version 1.0.0)
	/System/Library/Frameworks/Metal.framework/Versions/A/Metal (compatibility version 1.0.0, current version 367.4.0)
	@rpath/QtNetwork.framework/Versions/A/QtNetwork (compatibility version 6.0.0, current version 6.8.1)
	@rpath/QtCore.framework/Versions/A/QtCore (compatibility version 6.0.0, current version 6.8.1)
	/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
	/System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration (compatibility version 1.0.0, current version 1.0.0)
	/System/Library/Frameworks/UniformTypeIdentifiers.framework/Versions/A/UniformTypeIdentifiers (compatibility version 1.0.0, current version 709.0.0)
	/System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility version 1.0.0, current version 1.0.0)
	/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1800.101.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1351.0.0)

Как можно увидеть у RaidenVideoRipper в зависимостях Qt и dullahan_ffmpeg. Dullahan FFmpeg это форк FFmpeg который инкапсулирует его функционал в динамическую библиотеку, с возможностью получения текущего прогресса выполнения и отмены, с помощью Си процедур.
Далее заменяйте у приложения и всех необходимых библиотек пути с помощью install_name_tool.

Команда для этого такая:

install_name_tool -change old_path new_path target

Пример использования:

install_name_tool -change /usr/local/lib/libavfilter.9.dylib @rpath/DullahanFFmpeg.framework/libavfilter.9.dylib dullahan_ffmpeg.a

После того как вы пропишете все правильные пути, приложение должно стартовать корректно. Проверьте что все пути к библиотекам относительные, перенесите бинарик, и откройте заново.
Если вы видите какую-то ошибку, то проверяйте пути через otool и меняйте снова через install_name_tool.

Также бывает ошибка с путаницей зависимостей, когда у замененной вами библиотеки отсутствует символ в таблице, проверить наличие или отсутствие символа можно так:

nm -gU path

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

file path

Утилита file покажет вам к какой архитектуре принадлежит библиотека или приложение.

Также Qt требует наличия папки Plugins в папке Contents вашей директории YOUR_APP.app, скопируйте плагины из Qt в Contents. Далее проверьте работоспособность приложения, после этого можете приступать к оптимизации папки Plugins, удаляя элементы из этой папки и тестируя приложение.

Безопасность macOS

После того как вы скопируете все зависимости и поправите пути для динамической линковки, вам нужно будет подписать приложение подписью разработчика, и еще дополнительно отправить версию приложения в Apple для нотаризации.

Если у вас нет 100$ на лицензию разработчика или вы не хотите ничего подписывать, то тогда напишите вашим пользователям инструкцию по запуску приложения.

Эта инструкция работает также и для RaidenVideoRipper:

  • Отключение Gatekeeper: spctl –master-disable
  • Разрешить запуск из любых источников в Privacy & Security: Allow applications переключить на Anywhere
  • Удалить флаг карантина после скачивания с zip или dmg приложения: xattr -d com.apple.quarantine app.dmg
  • Проверите что флаг карантина (com.apple.quarantine) отсутствует: ls -l@ app.dmg
  • Дополните подтвердите запуск приложения если необходимо в Privacy & Security

Ошибка с флагом карантина обычно воспроизводится тем что на экране пользователя появляется ошибка “Приложение повреждено”. В этом случае надо убрать флаг карантина из метаданных.

Ссылка на сборку RaidenVideoRipper для Apple Silicon:
https://github.com/demensdeum/RaidenVideoRipper/releases/download/1.0.1.0/RaidenVideoRipper-1.0.1.0.dmg

Стабилизация видео с помощью ffmpeg

Если вы хотите стабилизировать видео и убрать дрожание камеры, инструмент `ffmpeg` предлагает мощное решение. Благодаря встроенным фильтрам `vidstabdetect` и `vidstabtransform`, можно добиться профессионального результата без использования сложных видеоредакторов.

Подготовка к работе

Прежде чем начать, убедитесь, что ваш `ffmpeg` поддерживает библиотеку `vidstab`. В Linux это можно проверить командой:

bash  
ffmpeg -filters | grep vidstab  

Если библиотека не установлена, её можно добавить:

sudo apt install ffmpeg libvidstab-dev  

Установка для macOS через brew:

brew install libvidstab
brew install ffmpeg

Теперь перейдём к процессу.

Шаг 1: Анализ движения

Сначала нужно провести анализ движения видео и создать файл с параметрами стабилизации.

ffmpeg -i input.mp4 -vf vidstabdetect=shakiness=10:accuracy=15 transfile=transforms.trf -f null -  

Параметры:

shakiness: Уровень дрожания видео (по умолчанию 5, можно увеличить до 10 для более сложных случаев).
accuracy: Точность анализа (по умолчанию 15).
transfile: Имя файла для сохранения параметров движения.

Шаг 2: Применение стабилизации

Теперь можно применить стабилизацию, используя файл трансформаций:

ffmpeg -i input.mp4 -vf vidstabtransform=input=transforms.trf:zoom=5 output.mp4

Параметры:

input: Указывает на файл с параметрами трансформации (созданный на первом шаге).
zoom: Коэффициент масштабирования для устранения черных краев (например, 5 — автоматическое увеличение до устранения артефактов).

Автоматический анализ кода с помощью Bistr

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

Что такое Bistr?

Bistr — это утилита для анализа исходного кода, которая позволяет интегрировать локальную LLM (large language model) модель, такую как Ollama, для анализа и обработки кода. С помощью Bistr вы можете анализировать файлы на различных языках программирования, например, Python, C, Java, JavaScript, HTML и других.

Bistr использует модель для того, чтобы проверить файлы на соответствие определенным запросам, например, для поиска ответа на вопрос о функциональности кода или его части. Это позволяет получить структурированный анализ, который помогает в разработке, тестировании и поддержке проектов.

Как работает Bistr?

  • Загрузка состояния: Когда вы начинаете анализ, утилита проверяет, было ли ранее сохранено состояние анализа. Это помогает продолжить с того места, где вы остановились, без необходимости повторного анализа тех же файлов.
  • Анализ кода: Каждый файл анализируется с использованием модели Ollama. Утилита отправляет запрос к модели для анализа конкретного фрагмента кода. Модель возвращает информацию о релевантности кода в ответ на запрос, а также предоставляет текстовое объяснение, почему данный фрагмент имеет отношение к задаче.
  • Сохранение состояния: После анализа каждого файла состояние обновляется, чтобы в следующий раз продолжить с актуальной информацией.
  • Вывод результатов: Все результаты анализа можно экспортировать в HTML-файл, который содержит таблицу с рейтингом файлов по релевантности, что помогает понять, какие части кода наиболее важны для дальнейшего анализа.

Установка и запуск

Для использования Bistr необходимо установить и запустить Ollama — платформу, которая предоставляет LLM модели на вашей локальной машине. Инструкция по установке Ollama для macOS, Windows и Linux описана ниже.

Загрузите последнюю версию Bistr из git:
https://github.com/demensdeum/Bistr/

После установки Ollama и Bistr можно запускать анализ кода. Для этого нужно подготовить исходный код и указать путь к директории, содержащей файлы для анализа. Утилита позволяет продолжить анализ с того места, где вы остановились, а также предоставляет возможность экспортировать результаты в HTML-формате для удобства дальнейшего анализа.

Пример команды для запуска анализа:


python bistr.py /path/to/code --model llama3.1:latest --output-html result.html --research "What is the purpose of this function?"

В этой команде:

–model указывает модель, которая будет использоваться для анализа.
–output-html задает путь для сохранения результатов анализа в HTML-файле.
–research позволяет задать вопрос, на который вы хотите получить ответ, анализируя код.

Преимущества использования Bistr

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

Локальные нейросети с помощью ollama

Если у вас было желание запустить подобие ChatGPT и у вас достаточно мощный компьютер, например с видеокартой Nvidia RTX, то тогда вы можете запустить проект ollama, который позволит использовать одну из готовых LLM моделей, на локальный машине, абсолютно бесплатно. ollama обеспечивает возможность общения с LLM моделями, на манер ChatGPT, также в последней версии объявлена возможность прочтения изображений, форматирование выходных данных в формат json.

Сам проект я запускал также и на макбуке с процессором Apple M2, и мне известно что поддерживаются последние модели видеокарт от AMD.

Для установки на macOS зайдите на сайт ollama:
https://ollama.com/download/mac

Нажмите “Download for macOS”, у вас загрузится архив вида ollama-darwin.zip, внутри архива будет Ollama.app который нужно скопировать в “Applications”. После этого запускайте Ollama.app, скорее всего при первом запуске произойдет процесс установки. После этого в трее вы увиделе иконку ollama, трэй это справа сверху рядом с часами.

После этого запускайте обычный терминал macOS, и набирайте команду загрузки, установки и запуска любой модели ollama. Список доступных моделей, описания, их характеристик можно увидеть на сайте ollama:
https://ollama.com/search

Выбирайте модель с наименьшим количеством параметров, если она не влезает в вашу видеокарту на запуске.

Для примера командв запуск модели llama3.1:latest:


ollama run llama3.1:latest

Установка для Windows и Linux в целом похожа, в одном случае будет установщик ollama и дальнейшая работа с ней через Powershell.
Для Linux установка производится скриптом, однако я рекомендую использовать версию конкретно вашего пакетного менеджера. В Linux ollama запустить также можно через обычный терминал bash.

Источники
https://www.youtube.com/watch?v=Wjrdr0NU4Sk
https://ollama.com

Unreal Engine на Macbook M2

Если вы смогли запустить Unreal Engine 5 Editor на Macbook с процессором Apple, то вы могли заметить что эта штука достаточо сильно тормозит.

Чтобы увеличить производительность редактора и движка, проставьте Engine Scalability Settings -> Medium. После этого движок начнет рисовать все не так красиво, зато вы сможете нормально поработать с движком на своем макбуке.

Исправление мобильного меню в WordPress


document.addEventListener('DOMContentLoaded', function() {
    new navMenu('primary');
    new navMenu('woo');
});

Если у вас тоже несколько лет не открывалось меню блога на iOS/Android в вашем блоге на WordPress, при использовании темы Seedlet, то просто добавьте:
В функцию замыкание файла wp-content/themes/seedlet/assets/js/primary-navigation.js, рядом с дефолтной подпиской window addEventListener ‘load’.

Radio-Maximum-Electron

Радио Максимум Electron — это мощное и удобное приложение, предназначенное для прослушивания потока радиостанции “Радио Максимум” на вашем компьютере под управлением операционных систем Windows, Linux и macOS. Этот плеер сочетает в себе простоту использования с высокой функциональностью, обеспечивая вам доступ к потоку в реальном времени с минимальными усилиями.

Просто скачайте приложение с GitHub:

https://github.com/demensdeum/Radio-Maximum-Electron/releases

Автор не имеет отношение к Радио Максимум, ему просто очень нравится это радио.
Основной функционал реализован проектом Nativifier

https://github.com/nativefier/nativefier

Лицензия на скрипты сборки MIT, у рантайма своя лицензия!

Подводное Приключение Полярного Мишки

Простенькая игра с бесконечно генерируемыми лабиринтами на ThreeJS.

Создавалась в рамках 3-х дневного геймджема “Начни игру” на тему “Семейная игра”.

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

Теперь его цель — найти выход из этой подводной ловушки и вернуться к своей маме, преодолевая опасности морских глубин и решая загадки.

https://demensdeum.com/demos/arctica/

Nixy Player

Nixy Player – Небольшой, расширяемый, кросс-платформенный JavaScript-runtime.

Кросс-платформенный: доступен на Windows, macOS и Linux, а также на любой другой платформе с поддержкой C++ и динамических библиотек.
Легковесный: минимальное потребление ресурсов с эффективной производительностью.
Расширяемый: создан для легкого расширения с помощью плагинов и дополнительных библиотек.

Пожалуйста, посетите страницу “Релизы”, чтобы быть в курсе последних выпусков и обновлений:
https://github.com/demensdeum/NixyPlayer/releases/

Raiden Video Ripper

Raiden Video Ripper – это проект с открытым исходным кодом, предназначенный для редактирования видео и конвертации форматов. Он создан с использованием Qt 6 (Qt Creator) и позволяет обрезать и конвертировать видео в форматы MP4, GIF и WebM. Вы также можете извлекать аудио из видео и конвертировать его в формат MP3.
Интерфейс RaidenVideoRipper

Кадр из COSTA RICA IN 4K 60fps HDR (ULTRA HD)
https://www.youtube.com/watch?v=LXb3EKWsInQ

Пожалуйста, посетите страницу “Релизы”, чтобы быть в курсе последних выпусков и обновлений:
https://github.com/demensdeum/RaidenVideoRipper/releases

Donki Hills

За месяц сделал забавный гэг, игру-пародию с помощью движка Unreal Engine 5. Разработка велась на Twitch стриме.

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

https://demensdeum.itch.io/donki-hills