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

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

Эволюция JS-фреймворков

Пост, в котором весьма сжато изложена эволюция web’а от статических страниц до-javascript’ной эпохи до современных MPA-фреймворков. Описаны проблемы, которые возникали в процессе развития этой экосистемы и подходы, которые применялись в фреймворках для их решения. Требует быть чуточку в теме, но в целом хорош для ответа на вопросы типа “чем отличается React от Vue” или “почему SPA уже не модно”.

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

Павлик internal

Продолжаю делать Павликов, потому что все нужное как всегда глубоко закопано и надо выбирать стул. На этот раз на очереди internal, который ограничивает видимость элемента модулем (т.е. если он в какой-то библиотеке, то только библиотека имеет к нему доступ). Его очень любят использовать сами Jetbrains в Ktor, корутинах, Exposed и т.п.

Но на самом деле это только ограничение компилятора самого Kotlin — на уровне java нет никакой видимости “на уровне модуля”, и можно этот internal использовать как угодно. И на уровне Kotlin обойти его тоже элементарно: нужно всего лишь добавить @file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE").

При этом многострадальный package-private, который сообщество хочет чуть ли не с релиза, в язык не добавляют. И очень смешно, что один из основных аргументов это “ну, все равно особо ни от чего не защищает, используйте internal”.

В общем, типичная позиция JetBrains — если хочется, то совместимость с java — священная корова, а если очень надо — то и плевать на нее.

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

Поиск алгоритма умножения матриц нейронками

Год назад была работа про использование ML для сортировок. А на прошлой неделе — статья в Nature про использование нейронок для умножения матриц. Что интересно, для поиска оптимального алгоритма задачу представили в виде игры и переиспользовали наработки от AlphaZero (которая обыгрывала чемпионов мира по шахматам, сеги и го).

Как сказал один из моих студентов: “Не знал, что нейронные сети можно использовать для чего-то полезного” :)

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

Приборка подов в k8s

Поды, завершившиеся с ошибкой, могут висеть в кубере до посинения (тикет).

Чтобы почистить все руками, можно выполнить что-то вроде такого:

kubectl -n namespace delete pods --field-selector=status.phase=Failed

Хотя, конечно, лучше разобраться с первопричиной падения подов:)

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

Обучение через использование

Немного капитана очевидности.

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

Ни для кого не секрет, что для закрепления навыка его надо регулярно использовать. И причем использовать для чего-то, должна быть какая-то цель, а не просто “ну, надо поизучать” или “все это делают и мне надо делать”. Для достижения этой цели, возможно придется, не побоюсь этой фразы, “выйти из зоны комфорта” — специально делать что-то не в привычном русле и не с помощью регулярно применяемого и освоенного навыка, а с использованием нового.

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

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

Потребление ресурсов в k8s

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

kubectl get nodes --no-headers | cut -f1 -d\  | xargs -I {} sh -c 'echo {} ; kubectl describe node {} | grep Allocated -A 5 | grep -ve percent -ve -- ; echo '

Выведет потребление в формате

ip-1-2-3-4.some.host.cluster
  Resource                    Requests      Limits
  cpu                         1610m (83%)   3450m (178%)
  memory                      2566Mi (35%)  5478Mi (76%)
СсылкаКомментировать

Принципы разделения на компоненты

Занятный доклад Мартина (aka Uncle Bob, автор кучи книг по ООП, в т.ч. “Чистый код”) про то, как надо делить код на компоненты.

TLDR:

  1. Чем сложнее проект, тем больше вероятность, что он провалится.
  2. Coupling (связанность) — это плохо, O(n^2), с его возрастанием снижается продуктивность, найм новых людей не работает, т.к. они не знают всех нюансов “так исторически сложилось”, делают ошибки и все становится еще хуже.
  3. Минимально число однонаправленных связей = N-1, и это дерево. Но если добавить только 1 связь, получится цикл, и будет циклическая зависимость, и все может сломаться, как цепная реакция.
  4. Компонент — это бинарный модуль, который может быть задеплоен независимо — dll, exe, jar. Неймспейсы/пакеты — не компоненты, но могут им соответствовать. (Хотя лично я считаю, что ничего этому не мешает). Компоненты обязательно должны содержать классы (вроде умный чел, но слышал ли он, что есть программирование без классов?)
  5. Система компонентов, удобная для использования, неудобна для разработки и наоборот, она зависит от потребителей. На ранних стадиях она может быть удобной для разработки, на поздних — для пользователя.
  6. Три первых принципа находятся в противоречии друг с другом, надо искать баланс.
  7. Не надо упаковывать ни по фичам, ни по пакетам, потому что у разных компонентов разные причины для изменения.
  8. Множественное наследование не реализовали не для защиты пользователей, а потому что сложно написать компилятор, который его поддерживает:))

Собственно принципы:

  1. Release Equivalency Principle — есть процесс релиза с версиями. Самый маленький компонент — это самый маленький кусок кода, который вы хотите переиспользовать.
  2. Common Closure Principle — SRP для компонента. Новая фича должна затрагивать ровной один компонент. Т.е. классы, которые изменяются по одной причине, должны быть в одном компоненте. “Все классы для работы с БД должны быть в одном компоненте” (sic!).
  3. Component Reuse Principle — Первый компонент зависит от второго, во втором поменялась какая-то мелочь, и первый пришлось обновлять/он сломался, хотя он и не зависел от этой мелочи. Такого быть не должно: если можно использовать только часть компонента, то надо его выделять в отдельный.
  4. Acyclic Dependencies Principle — зависимости компонентов между собой не должны создавать цикла.
  5. Stable Dependencies Principle — лучше зависеть от того, что тяжело изменить. Забавная аналогия: есть “взрослые компоненты”, которые не зависят от других, но от которых зависят многие, и “детские”, которые “безответственны”, но зависят от многих. И более нестабильный компонент должен зависеть от менее нестабильного, иначе легкий для изменения компонент перестанет быть таковым.
  6. Stable Abstractions Principle — на верхних уровнях все должны быть максимально конкретны, на нижних, от которых все зависят — максимально абстрактны. Но это касается только тех компонентов, которые активно развиваются и не касается всяких библиотечных классов, от которых все зависят, но при этом они очень конкретны.

Я может чего-то не понимаю, но под все эти принципы идеально подходит is-even/left-pad, и я не думаю, что экосистема npm — это эталон. В целом вроде доклад “умный”, но 1, 4 и 5 — очевидны, 2 и 3 противоречивы, 6 так вообще с непонятными исключениями. Конкретных приемов, как все это подружить, Мартин, увы, не приводит, поэтому практическая польза не очень высокая, но как затравка для холивара — неплохая тема.

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

Бесполезные зависимости

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

Прошлогоднее исследование зависимостей java-проектов показало, что с 2011 по 2021 среднее число неиспользованных транзитивных зависимостей возросло с 20 до 60, и оно растет для большинства проектов. Т.е. бесполезный мусор на самом деле есть, и его размер растет.

Для чистки зависимостей рекомендуют использовать плагин DepClean, разработанный, разумеется, авторами статьи. Но, что иронично, с собственными зависимостями у этого плагина все не очень гладко, потому что там внутри две CVE :)

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

Не деплойте в облака пацаны, вы матерям еще нужны

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

Однако “all magic comes with a price”:

  1. Трахание с железом и сервисами на самом деле заменяется на трахание с настройками и нюансами облачного провайдера. Причем если опыт с сервисами и железом плюс-минус переносимый, то у каждого провайдера свои приколы, разумеется.
  2. Отдельно выделю вопросы распределения ролей, настроек доступов и прочих аспектов связанных с ИБ. Про свой опыт с гуглом уже рассказывал. Во всем это зрелый DevOps может на неделю сгинуть для простой задачи, а разраб — вообще умереть.
  3. Облачные версии сервисов часто представляются собой форк опенсорсных со своими “расширениями” (например, амазоновский OpenSearch — это форк ElasticSearch), обычно от старой версии. Иногда присутствует EEE во всей красе. Причем расширения обычно нужны для интеграции в облачную экосистему и хреново поддерживаются, а решение для опенсорсного варианта может не подойти для облачного.
  4. Поскольку сервисом управляете не вы, то может не получится его тонко настроить или поставить какие-нибудь плагины.
  5. Как следствие, возникает привязка к облачному провайдеру, когда съехать с облака становится очень дорого, потому что все настройки или даже архитектура заточены под него.
  6. Условия могут внезапно поменяться к худшему и это может быть затратно (например, недавно Heroku убрал бесплатный тариф)
  7. Конфиденциальность — гомоморфное шифрование пока не применяют, так что облачный провайдер имеет доступ ко всем данным.
  8. Если что-то сломается, то вы ничего не сможете с этим поделать, только ждать и надеяться, что все будет быстро исправлено.
  9. Ложная уверенность в 100% надежности облака могут привести к тому, что ночью никто не будет дежурить и следить за работоспособностью сервиса (впрочем, и без облаков это можно делать).

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

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

Влияние размера организации на эффективность

Жизненная гипотеза: чем больше людей в компании, тем больше времени тратится на совещания и организацию работы, продвигаются те, у кого лучше подвешен язык, а те, кто собственно работу делают — уходят. В итоге ничего и не делается. Много усилий тратится на поддержание процессов, регламентов, отчетости и т.п., и в итоге результаты могут получаться по остаточному принципу. Формализация процессов, которая часто возникает при увеличении количества людей, хорошо работает для простых или однообразных задач, однако мешает при выполнении сложных задач. Сильная формализация затрудняет оценку достижений (а без формализации никак, потому что будут конфликты интересов), что может сильно демотивировать сотрудников, особенно если ценится только героизм устранения последствий, а не кропотливость их предотвращения.

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

В (нормальных) маленьких компаниях меньше стоит проблема контроля и они лучше адаптируются к изменениям, но и риски там обычно выше. При этом менеджерам проще уделять внимание рядовым сотрудникам.

Интересно, что в некоторых компаниях решили проблему размера разделением на несколько мелких. Эдакие компании-микросервисы. Это забавно коррелирует с заявлениями в стиле “Наша компания большая, про нее много плохих отзывов, но все зависит от департамента/отдела/команды, вот у нас-то все классно!”

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