Этика и безопасность искусственного интеллекта

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

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

В статье рассмотрим некоторые этические аспекты ИИ.

Иллюстрация сгенерирована Midjourney

Иллюстрация сгенерирована Midjourney

Проблема мирового масштаба

Некоммерческая организация Future of Life опубликовала письмо за подписью главы Tesla, SpaceX и Twitter Илона Маска, одного из создателей Apple Стива Возняка, сооснователя Pinterest Эвана Шарпа и ещё более тысячи экспертов в области ИИ. 

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

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

Присутствие ИИ в повседневности вызывает множество этических вопросов, которые с каждым годом становятся всё острее. Среди наиболее заметных примеров – смертельные ДТП с участием самоуправляемых автомобилей Tesla и Uber. Немаловажные проблемы в сфере использования ИИ касаются, в том числе, манипулирования информацией и различного рода дискриминацией. 

Ответственность и прозрачность ИИ

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

Автопилот Tesla определяет объекты, а ИИ принимает решения 

Автопилот Tesla определяет объекты, а ИИ принимает решения 

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

Респонденты поставлены перед выбором: разбить автомобиль, убив пассажиров, или совершить смертельный наезд на пешеходов.

Дилемма теста: убить пассажиров или совершить смертельный наезд на пешеходов

Дилемма теста: убить пассажиров или совершить смертельный наезд на пешеходов

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

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

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

Предвзятость алгоритмов

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

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

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

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

Использование технологий ИИ подчас задевают существующие в обществе ценности. Например, нарушаются такие основополагающие принципы как расовое и гендерное равенство. Явление пристрастности ИИ получило название AI bias.

Необъективность ИИ стала причиной возмущений общественности в связи с решениями уголовно-исполнительной системы США в отношении этнических меньшинств, которые были вызваны ошибками в распознавании лиц.

Известный случай дискриминации, связанной с использованием ИИ, произошел в 2018 году. Выяснилось, что алгоритм системы судейства при определении размера залога для подозреваемых в правонарушениях оказался пристрастным к афроамериканцам.

Недавно специалист в области информатики Джон Маккормик признался в непреднамеренном создании 25 лет назад «расово предвзятого» алгоритма ИИ для распознавания лиц.

The author’s 1998 head-tracking algorithm used skin color to distinguish a face from the background of an image.

Алгоритм отслеживал движения головы человека на основе данных с видеокамеры.

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

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

(Не)доверие к ИИ 

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

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

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

ИИ от IBM Watson for Oncology, предоставляющий рекомендации по лечению рака, так и не смог заслужить доверие онкологов.

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

Если рекомендации Watson противоречили мнению экспертов, те не доверяли программе, считая её некомпетентным. Алгоритмы машинного обучения были слишком сложными для понимания, врачи не видели объяснений эффективности лечения ИИ и полагались на свой опыт, игнорируя рекомендации ИИ.

Врачи-онкологи расходились с программой Watson почти в 70% случаях, поэтому медицинские учреждения решили отказаться от ее использования.

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

ИИ не считается абсолютно надежным в том числе потому, что создаётся людьми. То, что нельзя полагаться на эти технологии, подтверждается примерами ошибок, громогласно освещаемых в СМИ. В частности, то ДТП с автопилотом Tesla, закончившееся смертельным исходом. 

 Приватность данных

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

Так, исследование американских университетов Принстона и Беркли  и Швейцарской высшей технической школы Цюриха совместно с Google и DeepMind подтвердило вероятность утечки данных из систем создания изображений с применением ИИ – DALL-E, Imagen и Stable Diffusion.

Исходное и сгенерированное изображение из Stable Diffusion

Исходное и сгенерированное изображение из Stable Diffusion

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

Этические кодексы в сфере ИИ

В связи с развитием нейросетей и машинного обучения крупнейшие ИТ-компании мира стали проявлять особый интерес к этике ИИ. В числе первых  в 2016 году были опубликованы «10 Законов для искусственного интеллекта» Microsoft, в которых от имени генерального директора компании Сатьи Наделлы указаны ключевые требования к развитию этики ИИ. 

Свой взгляд на этику ИИ представила и IBM.

Почти полсотни крупных ИТ-компаний по всему миру обладают собственными кодексами и правилами, основанные на этических принципах, относящихся к применению и развитию ИИ. В числе таких компаний российские ABBYY, Сбер и Яндекс.

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

Этические нормы и ценности сформулированы в 13 из «23 принципов искусственного интеллекта» на Асиломарской конференции в 2017 году. В числе тех, кто подписал их, – Илон Маск, Стивен Хокинг, Рэй Курцвайл и другие. Эти принципы отразились в корпоративных нормах ряда компаний, чья деятельность связана с разработкой ИИ. 

Асиломарская конференция

Асиломарская конференция

Законодательное регулирование ИИ в России и за рубежом 

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

C 1 июля 2020 года в Москве проводится пятилетний эксперимент, направленный на разработку и внедрение технологии ИИ для заинтересованного бизнеса. Ранее ИИ не регулировался законодательно. Между тем, использование таких технологий порождает проблемы, включая, но не ограничиваясь:

  • необходимостью обезличивания и защиты персональных данных, особенно в области распознавания лиц, 

  • обеспечением доступа ИИ к большим массивам информации для полноценного развития, 

  • разграничением ответственности за действия ИИ и возможности доказательства.

Закон 123-ФЗ от 24 апреля 2020 года устанавливает в Москве специальный правовой режим в сфере ИИ. В нём указаны требования по защите персональных данных граждан и использования псевдоданных, собираемых в режиме анонимности. В частности, допускается обработка обезличенных персональных данных граждан для реализации эксперимента.

Цель этого экспериментального правового режима – повышение качества жизни населения, эффективности госуправления и деятельности бизнеса в ходе внедрения технологий ИИ. А также формирование комплексной системы регулирования общественных отношений, возникающих в связи с развитием и использованием ИИ. Эксперимент позволит создать правовую базу для этого. 

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

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

В России была создана рабочая группа по разработке принципов этики ИИ. В 2021 году в рамках I международного форума «Этика искусственного интеллекта: начало доверия» был принят российский «Кодекс этики в сфере ИИ». На 2023 год документ подписали более 150 российских организаций.

Необходимость выработки этических норм и нормативного регулирования для ИИ прописана в «Национальной стратегии развития искусственного интеллекта на период до 2030 года».

Ещё один важный документ – «Концепция развития регулирования отношений в сфере технологий искусственного интеллекта и робототехники на период до 2024 года».

В ней сказано, что развитие технологий ИИ и РТ должно основываться на базовых этических нормах и предусматривать:

  • Цель обеспечения благополучия человека должна преобладать над иными целями разработки и применения систем ИИ и РТ.

  • Запрет на причинение вреда человеку по инициативе систем ИИ и РТ. По общему правилу, следует ограничивать разработку, оборот и применение систем ИИ и РТ, способных по своей инициативе целенаправленно причинять вред человеку. 

  • Подконтрольность человеку в той мере, в которой это возможно с учётом требуемой степени автономности систем ИИ и РТ и иных обстоятельств.

  • Проектируемое соответствие закону, в том числе – требованиям безопасности: применение систем ИИ не должно заведомо для разработчика приводить к нарушению правовых норм.

В 2021 году принят российский «Кодекс этики в сфере ИИ»

В 2021 году принят российский «Кодекс этики в сфере ИИ»

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

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

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

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

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

В качестве заключения

В недавнем интервью Такеру Карлсону Илон Маск заявил, что ИИ может быть использован в качестве инструмента влияния, в том числе, на выборах. А если ИИ будет достаточно умён, неизбежно возникнет вопрос, кто кого использует: люди ИИ или ИИ людей. «Мы движемся в странном направлении, и движемся всё быстрее… Нам нужен надзорный орган. А в свою очередь, СМИ должны пристальнее следить за тем, что публикуется и печатается на их платформах. И работать с людьми, а не с GPT-ботами, притворяющимися людьми», – подчеркнул Маск.

Несмотря на все вызовы и опасности, которые стали актуальными, ИИ остаётся одной из самых перспективных технологий, которая может усилить наши возможности и упростить жизнь. Главное – помнить, что это всего лишь инструмент, который мы можем и должны использовать с максимальной осторожностью и этичностью.


ссылка на оригинал статьи https://habr.com/ru/companies/inferit/articles/745230/

Как погубить децентрализованную сеть (на примере Федиверса)

На дворе 2023 год. Весь Интернет – под контролем Империи GAFAM. Весь? Нет, несколько мелких анклавов пока не поддались их гнёту. А некоторые из этих непримкнувших стали объединять усилия, консолидируясь в «Федиверс».

В ходе дебатов на просторах Twitter и Reddit, Федиверс стал привлекать всё больше внимания и снискал славу. Люди стали всерьёз им пользоваться. Это не могло укрыться от внимания Империи.  

Капиталисты против конкуренции

Как выразился Питер Тиль, один из прославленных инвесторов Facebook (организация запрещена на территории РФ), «Конкуренция – для лузеров». Да, эти лицемеры, утверждающие, что «рыночек порешает» совсем не хотят подчиняться рынку, когда уже вошли на него. Им нужна монополия. Facebook с самого зарождения был настроен на подрыв любой конкуренции. Проще всего этого добиться, покупая компании, которые рано или поздно могут составить тебе конкуренцию. Такая судьба постигла, например,  Instagram и WhatsApp – их купили только потому, что они предлагали пользователям привлекательный продукт и отнимали поляну у Facebook.

Но Федиверс не купить – ведь это неофициальная совокупность серверов, обменивающихся информацией по протоколу ActivityPub. На этих серверах даже может использоваться разный софт (наиболее известный пример —  Mastodon, но также вы могли сталкиваться с Pleroma, Pixelfed, Peertube, WriteFreely, Lemmy и многими другими решениями).

Децентрализованную сеть нельзя купить!

Но есть другой путь: обесценить её. Именно так Google поступил с XMPP.

Как Google присоединился к федерации XMPP

В конце XX века службы обмена мгновенными сообщениями (инстант-мессенджеры) аошли в сок. Одним из первых успешных экземпляров была аська (ICQ), вслед за ней вскоре появился мессенджер MSN. Мессенджер MSN был тиктоком своего времени: миром, где подростки могли часами и днями зависать без присмотра взрослых.

Поскольку MSN входил в состав Microsoft, Google захотел составить ему конкуренцию и в 2005 году предложил Google Talk, включив его в интерфейс Gmail. Напомню, что в те времена не существовало смартфонов, а веб-приложения были наперечёт. Все приложения требовалось устанавливать на компьютере, и веб-интерфейс Gmail был прорывной технологией. В какой-то момент MSN даже вплели в Microsoft Windows, и удалить его из этой ОС было по-настоящему трудно. Но чаты Google в веб-интерфейсе Gmail были гораздо ближе к пользователю даже по сравнению с программой, встроенной в операционную систему.

Тем временем, пока Google и Microsoft сражались за гегемонию, энтузиасты свободного ПО пытались выстроить децентрализованный мессенджер. В результате появился XMPP, который, подобно электронной почте, работал по федеративному протоколу. Множество серверов могли обмениваться данными по этому протоколу, и каждый пользователь подключался к конкретному серверу через установленный у себя клиент. После этого пользователь мог общаться с любым другим пользователем, подключившимся к любому серверу через любой клиент. Именно по такому принципу сейчас работает протокол ActivityPub и, соответственно, Федиверс.

В 2006 Google talk стал совместим с XMPP. В Google отнеслись к XMPP со всей серьёзностью. Помню, в 2008 году мне однажды позвонили на работу. Кто-то на той стороне сказал: «Здравствуйте, мы из Google, хотим предложить вам работу». Я сделал несколько звонков – и оказалось, что меня нашли через список разработчиков XMPP. Они искали сисадминов для поддержки серверов XMPP .

Так Google серьёзно вошёл в федерацию. Насколько круто это воспринималось? Это означало, что внезапно все до единого пользователи Gmail стали пользователями XMPP. Для XMPP это только на благо, верно? Я был в экстазе.

Как Google погубил XMPP

Но, как говорится, «гладко было на бумаге». Прежде всего, несмотря на активное участие в разработке стандарта XMPP, Google готовил и закрытую реализацию, к изучению которой никого не подпускал. Оказывается, они не слишком бережно относились к тому протоколу, который разрабатывали. Реализовывали не всё. Они вынудили сообщество замедлить разработку XMPP, чтобы приспособиться к процессу. Приятные фичи не реализовывались или не использовались в XMPP-клиентах, так как оказывались несовместимы с Google Talk (аватарки мучительно долго не могли закрепиться в XMPP). Федерация иногда сбоила: случалось так, что целыми часами или днями не работала связь между серверами Google и обычными серверами XMPP. Сообщество XMPP переквалифицировалось в сторожей и отладчиков серверов Google, сообщая о нерегулярности и простоях (я сам это делал несколько раз; возможно, именно это подтолкнуло меня сменить работу).

Поскольку пользовательская аудитория Google talk была гораздо шире, чем аудитория «настоящих пользователей XMPP», почти не оставалось возможности «обойти вниманием пользователей Google talk». Новички, открывавшие для себя XMPP, не будучи при этом пользователями Google talk, сами воспринимали такой опыт болезненно, так как в списке контактов у них были в основном пользователи Google Talk. На первый взгляд, коммуникация с ними должна была бы пойти без труда, но фактически мессенджер XMPP представлял собой урезанную версию функционала Google talk. В типичный список контактов XMPP входили в основном пользователи Google Talk плюс несколько гиков.

В 2013 году в Google осознали, что большинство взаимодействий по XMPP всё равно происходит среди пользователей Google Talk. Гуглеры совершенно не пытались уважать протокол, который не контролировали на 100%. Поэтому они перекрыли проекту кислород и объявили, что федеративным он больше не будет. После чего началась долгая история по разработке собственного мессенджера; первым вариантом был Hangout (а затем Allo, Duo. Далее я не следил).

Ожидаемо, что никто из пользователей Google и бровью не повёл. Фактически, они и не поняли, что произошло. В худшем случае некоторые контакты у кого-то навсегда ушли в оффлайн. Вот и всё. Но с точки зрения федерации XMPP ситуация выглядела так, будто большинство пользователей внезапно куда-то исчезли. Даже закоренелым фанатикам XMPP, таким, как ваш покорный слуга, пришлось создать аккаунты Google, чтобы не потерять связь с друзьями. Напоминаю: для них мы просто оказались в оффлайне. Это была наша вина.

Притом, что XMPP сохранился до наших дней и остаётся очень активным сообществом, мессенджер так и не оправился от того удара. Завышенные ожидания от «нас взяли в Google» обернулись жестким разочарованием и тихим сползанием в небытие. XMPP стал нишевым. Настолько нишевым, что, когда все ринулись в групповые чаты (Slack, Discord), сообщество разработчиков свободного ПО просто переизобрело такой протокол (его назвали Matrix), чтобы иметь возможность конкурировать – тогда как в XMPP уже была возможность создавать групповые чаты. (Оговорюсь: я никогда не изучал протокол Matrix, поэтому понятия не имею, как он соотносится с XMPP с технической точки зрения. Просто считаю, что он решает те же задачи, что и XMPP, а также конкурирует в том же пространстве).

Сложилась бы судьба XMPP иначе, если бы союз с Google не состоялся, либо если бы вопрос слияния с Google не рассматривался? Сейчас уже не скажешь. Но я убеждён, что сообщество росло бы медленнее и, возможно, выросло бы более здоровым. Оно было бы более крупным и значительным, чем является сегодня. Де-факто это была бы основная платформа для децентрализованной коммуникации. Я уверен в одном: без союза с Google XMPP чувствовал бы себя не хуже, чем сейчас.

Это был не первый случай: вспомним о Microsoft Playbook

То, что Google сотворил с XMPP, случалось и ранее. На самом деле, в 1998 году программист Винод Валлопллил из Microsoft написал открытую статью «Blunting OSS attacks» (примерный перевод: «Как умерить аппетиты опенсорса»), в которой предлагал «де-коммодитизировать (выводить из общего доступа) протоколы и приложения […]. Надстраивая эти протоколы и разрабатывая новые, мы сможем не допустить на рынок проекты, разрабатываемые как свободное ПО». Microsoft воплотила это на практике, выпустив ОС Windows 2000, в которой поддерживался протокол обеспечения безопасности Kerberos. Но затем этот протокол расширили. Спецификации таких расширений можно было свободно скачать, но при этом требовалось принять лицензию, запрещавшую внедрять эти расширения. Стоило вам нажать «ОК» — и вы теряли возможность работать с любой опенсорсной версией Kerberos. Это делалось с единственной целью – убить любой конкурирующий сетевой проект, например, Samba.

Эту историю приводит Глин Муди в своей книге «Rebel Code», чтобы продемонстрировать, что искоренение опенсорсных и децентрализованных проектов в самом деле велось сознательно. Такое никогда не происходит случайно и никогда не сводится к «просто не повезло».

Microsoft применила похожую тактику, чтобы обеспечить себе доминирование на рынке офисных приложений: в Microsoft Office стали использоваться проприетарные форматы (формат файла можно расценивать как протокол для обмена данными). Когда альтернативные решения (OpenOffice и LibreOffice) научились достаточно хорошо открывать файлы в форматах doc/xls/ppt, Microsoft выпустила новый формат, который назвала «открытым и стандартизированным». Этот формат целенаправленно сделали очень сложным (20 000-страничный комплект спецификаций!), а самое главное – неправильным. Да, в спецификацию были специально введены некоторые баги, и поэтому софт, полностью реализовывавший формат OOXML, работал бы иначе, чем Microsoft Office.

Эти баги плюс лоббирование в верхах, в частности, привели к тому, что город Мюнхен отказался от идеи полностью перейти на Linux. Так что это в самом деле действенная стратегия. Именно поэтому сегодня docx, xlsx и pptx – по-прежнему норма. Рассказываю об этом на собственном опыте, так как власти Мюнхена оплачивали мне работу по приближению OOXML-рендеринга в LibreOffice к стандартам Microsoft, что шло вразрез со спецификацией.

ОБНОВЛЕНИЕ:

Meta и Федиверс

Кто не учит уроков истории, обречён их пересдавать. Ровно та же история произошла между Meta (организация запрещена в России) и Федиверсом.

Ходили слухи, что Meta станет «Федиверс-совместимой». Вы сможете сделать себе аккаунт на Mastoson и следить с него за лентами ваших друзей из Инстаграма (организация запрещена в России).

Не знаю, есть ли в этих слухах зерно истины, возможно ли вообще, чтобы Meta рассматривала такой вариант. Но есть один момент, который я усвоил на собственном опыте, работая с XMPP и OOXML: если Meta присоединится к Федиверсу, то выиграет от этого только Meta. На самом деле, реакция подсказывает, что эта победа уже назревает: в Федиверсе начались споры о том, блокировать Meta или нет. Если блокировка состоится, то у нас получится удручающе фрагментированный двухуровневый Федиверс, малопривлекательный для новичков.

ОБНОВЛЕНИЕ: Эти слухи подтвердил, как минимум, один администратор Mastodon под ником kev, работающий в fosstodon.org. К нему обращались с приглашением принять участие в негласном совещании Meta. Он отреагировал наилучшим возможным образом: вежливо отказал и, что самое важное, опубликовал это письмо с указанием адресатов и адресанта. Спасибо тебе, kev!

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

Конкурируя с Meta на поле бездумной идеологии «рост любой ценой», мы наверняка проиграем. Они асы этой игры. Именно они пытаются перетянуть всех на своё поле, вовлечь людей в конкуренцию, а сами при этом будут продавать стволы соперничающим сторонам.

Федиверс может победить, лишь удержав свою территорию и говоря о свободе, морали, этике и ценностях. Ведя открытые некоммерческие переговоры, в которых никто ни за кем не шпионит. Признавая, что нет цели победить. Не «поддержать». Цель – остаться функциональным. Настолько, чтобы служить островком свободы для людей, связанных одной цепью. Такого вам никогда не сможет предложить коммерческая компания.


ссылка на оригинал статьи https://habr.com/ru/articles/745240/

Автоматика первобытных людей и древнего мира

Картинка Upklyak, Freepik

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

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

▍ Автоматика первобытных людей

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

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

Во время охоты древним людям частенько приходилось сталкиваться напрямую со зверем, что с учётом тогдашней «медицины» могло весьма плачевно закончиться. Также нужно помнить, что в сутках только 24 часа, а у человека только одна человеческая сила. Необходимо было каким-то образом поступить так, чтобы охота происходила неким образом, «сама собой». И были придуманы ловушки. Первобытные люди выкапывали ямы в земле, прикрывали их лёгким настилом, маскировали. Наступив на настил, животное проваливалось и оказывалась в ловушке.

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

В качестве одного такого вида ловушек можно назвать давильное устройство: тяжёлый камень ставился под наклоном, подпёртый палочкой, и под него клался кусок мяса. Зверь пытался вытащить мясо, задевал палочку и его придавливало упавшим камнем (для гарантии результата мясо могло быть даже привязано к палочке или насажено на неё).

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

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

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

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

Конструкция устройства показана на рисунке ниже:

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

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

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

По аналогичной логике работало устройство, называемое в наше время «черканом».

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

Конструкция может варьироваться и быть сделана, например, не «наподобие лука», а прямо из лука:

Источник

Некоторые учёные считают, что появление автоматических ловушек примерно 20 000 лет назад имеет такое же важнейшее значение для цивилизации, как и изобретение колеса.

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

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

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

▍ Автоматика древнего мира

2500 лет назад Древняя Греция была в самом зените своего развития, и именно здесь появились первые автоматические развлекательные устройства.

Одним из них стало создание известным греческим архитектором Дедалом (кстати говоря, считающимся изобретателем рубанка, отвеса и сверла) автоматической модели движения планеты Венеры.

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

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

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

А 2300 лет назад в Египте людей удивлял аппарат, отпускающий порции «священной воды» в ответ на опускание в щель монеты. Принцип действия устройства был следующим: внутри автомата был установлен рычаг, закреплённый посередине, и когда монета падала на правую его часть, левая часть рычага поднималась, приподнимала пробку, затыкающую сливное отверстие сосуда с водой, и вода начинала выливаться в руки страждущему. Так как монета не могла долго удерживаться на наклонившейся площадке на правой части рычага, она соскальзывала в хранилище для монет, а рычаг возвращался в исходное положение, перекрывая ход воды.

Источник

В деле создания автоматических устройств отличился и знаменитый древнегреческий учёный Архимед, благодаря трудам которого был создан планетарий, где можно было наблюдать за движением планет (так называемая «сфера Архимеда»). Модель системы небесных тел приводилась в движение водяным колесом.

Ниже показана попытка современной реконструкции этого устройства:

В работе другого знаменитого учёного Герона Александрийского — «Пневматика» (120 лет до н. э.) — описано любопытное устройство, находившееся в одном из храмов города, где был установлен алтарь, на котором разжигался огонь и священнослужитель начинал молиться. Тут же дверь храма открывалась и оставалась открытой, пока горел огонь. Когда молитва заканчивалась и огонь гас, двери храма так же плавно закрывались.

Весь секрет заключался в специальном пневматико-гидравлическом устройстве, установленном в подвале храма:

Источник

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

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

Усовершенствованную версию подобного устройства работы Леонардо да Винчи в реконструированном по чертежам виде вы можете увидеть ниже:

Источник

Ещё картинки

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

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

Источник

Ещё картинка

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

Устройство подобной лампы показано на рисунке ниже:

Источник

Как видно по схеме, при снижении уровня масла (а это говорит о том, что лампа некоторое время уже работала, и некоторое количество фитиля уже прогорело) поплавок снижался вместе с уровнем масла. Но он снижался не сам по себе, а вместе со связанной с ним зубчатой рейкой, которая вращает зубчатое колесо, вращающее, в свою очередь, дугообразную зубчатую рейку, связанную с фитилём. Таким образом, происходит постоянная автоматическая подача фитиля!

Для тех, кто не знает: фитиль во время горения, так же как и в свечках, не остаётся «нерушимым», а сгорает, и его требуется постоянно подавать. К чести изобретателя этого устройства (кстати говоря, того же Герона Александрийского) следует отметить, что много веков спустя, когда появились керосиновые лампы, они были устроены более примитивно, и требовали постоянной ручной подкрутки фитиля, чтобы сохранять яркость горения (возможно и существовали отдельные автоматически экземпляры, но явно не массово). То есть можно сказать, что изобретатель многократно опередил своё время.

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

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

Устроены они были следующим образом:

Такие часы представляли собой ёмкость с водой, в которой находился поплавок, связанный с одним концом стрелки.

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

Со временем они были усовершенствованы и, например, в древнем Вавилоне 2 000 лет назад уже использовались следующие часы:

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

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

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

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


ссылка на оригинал статьи https://habr.com/ru/companies/ruvds/articles/744040/

Zod: Типизация и валидация Вашего .env (Vite + React и не только)

Введение

Нередко в проектах необходимо заводить переменные окружения (environment variables). Существует много способов сделать это. Например, указать переменную «inline», как MY_VAR="my value" node index.js или обозначить источник командой source. Некоторые фреймворки имеют даже целые отдельные пакеты для формирования переменных окружения (прим. nest.js). Но чаще всего за годы работы в сфере фронтенд-разработки мне приходилось работать со способом, который подразумевает содержание .env файлов в проекте. Такие файлы имеют простейший синтаксис вида KEY=VALUE:

# .env  APP_TITLE="My application" PORT=3000

Для чего вообще нужны эти переменные и какого рода данные в них стоит записывать? Ответ:

  • какие-либо секретные значения, которые не стоит держать в репозитории.
    Пример: KEY_SECRET от стороннего API или данные для аутентификации БД;

  • значения, которые различаются для разных режимов работы приложения. Пример: BASE_URL для:

    • dev-стенда — https://dev.my-amazing-resource.com

    • test-стенда — https://stage.my-amazing-resource.com

    • production — https://my-amazing-resource.com

  • параметры конфигурации или глобальные константы. Пример: PORT, PROXY_URL, FEATURE_TOGGLE и т.д.

Таким образом, данные скрыты от чужих глаз и могут конфигурировать наше приложение в (и вне) зависимости от режима его работы. Удобно!

Проблема

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

# .env  APP_TITLE="My app" APP_VERSION=1 SHOW_VERSION=true # COMMENTED_REQUIRED_VALUE=

Во-первых, может показаться, что APP_TITLE, APP_VERSION и SHOW_VERSION — это строка, число и логическое значение соответственно. На самом же деле ВСЕ эти значения являются строками.

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

Что мы имеем по итогу:

  1. Для того, чтобы работать со значениями согласно задуманным им типам данных, необходимо сначала привести их к этим типам:

    • const title = process.env.APP_TITLE; // all is ok

    • const version = Number(process.env.APP_VERSION);

    • const showVersion = JSON.parse(process.env.SHOW_VERSION);

    На этом этапе приложение может сломать самая малая опечатка в конфиге, например, False вместо false или 1,0 вместо 1. Стоит подумать на счет разнообразных проверок, обработки ошибки парсинга и прочем.

  2. Так как .env не дает никакой валидации данных, мы, вызывая переменную COMMENTED_REQUIRED_VALUE, которая считается обязательной и всегда должна быть прописана, НО почему-то осталась закомментированной, получаем ошибку. Окей, просто добавить еще проверок наличия обязательного значения, приведения типов, проверок типов.

Добавили все необходимые приведения типов, проверки, и теперь код…

Нет.

Решение v0

Наверняка, вы уже самостоятельно додумали, что было дальше. Такое решение не очень-то красиво и удобно. Особенно, учитывая гораздо большее количество переменных, появление новых и другие аспекты. В этом разделе я хочу представить 🙌 хорошее 🙌 решение и более подробно разобрать сам подход, а в следующем разделе поговорим о его «доведенной до ума» версии — ✨ отличном ✨ решении.

За основу будет взят проект, созданный Vite по шаблону react-swc-ts, что значит React + SWC + TypeScript. На самом деле, описываемый подход не зависит от конкретно этих инструментов и может быть применен практически к любому стеку.

Установил зависимости, поставил prettier, настроил линтинг, отформатировал код, поставил @types/node, поправил package.json, поправил vite.config.ts. Теперь хорошо. Я не буду углубляться в структуру проекта, рассказывать какие-то подробности Vite или React, если они НЕ ИМЕЮТ отношения к делу. Только суть.

yarn dev # или vite
Такую страницу получаем при запуске приложения

Такую страницу получаем при запуске приложения

Чтобы избавиться от «лишнего шума» я удалю весь код, сгенерированный Vite и оставлю только один заголовок h1, который послужит для визуализации значений.

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

APP_TITLE="My app" APP_VERSION=1 SHOW_VERSION=true # COMMENTED_REQUIRED_VALUE=

Vite предоставляет немного своеобразный способ работы с переменными окружения, в частности с .env. Подробнее об этом можно прочитать в официальной документации, но пока что следует знать только то, что все переменные должны быть указаны с преифксом VITE_, а вызов этих переменных внутри приложения происходит через специальный объект import.meta.env.
Таким образом, получаем конфиг такого вида:

VITE_APP_TITLE="My app" VITE_APP_VERSION=1 VITE_SHOW_VERSION=true # VITE_COMMENTED_REQUIRED_VALUE=

И в приложении попробуем использовать переменную VITE_APP_TITLE, просто поместив ее внутрь заголовка h1, пользуясь интерполяцией JSX(TSX):

export const App = () => {   return <h1>{import.meta.env.VITE_APP_TITLE}</h1>; };
Результат

Результат

Отлично! Это работает. Но если посмотрим в коде на тот самый специальный объект import.meta.env, то увидим, что он вроде как и не содержит нужных нам свойств. Более того, любое его свойство, помимо встроенных BASE_URL, MODE, DEV, PROD, SSR, является значением типа any.

Посмотрим на решение, которое предоставляет Vite. Необходимо описать модуль env.d.ts, предварительно добавив его в директорию src или куда вам угодно, например, в src/types:

/// <reference types="vite/client" />  interface ImportMetaEnv {   readonly VITE_APP_TITLE: string;   readonly VITE_APP_VERSION: number;   readonly VITE_SHOW_VERSION: boolean;   readonly VITE_COMMENTED_REQUIRED_VALUE: any; }  interface ImportMeta {   readonly env: ImportMetaEnv }

Выглядит неплохо, теперь мы можем просматривать все переменные окружения, которые описали в модуле и опираться на их типы данных.

Но вопрос с валидацией данных остается открытым. IDE подсказывает, что переменная VITE_APP_VERSION является значением типа number. Но по факту, проверив значение через typeof, мы получаем string:

Такое решение может, скорее, сбить столку. Поэтому приступим к написанию собственного. Для начала добавим следующую структуру файлов: в директории src создаем новую директорию config, в которую помещаем два .ts документа:

  • index.ts

  • buildEnvProxy.ts

buildEnvProxy.ts будет содержать в себе и экспортировать одноименную функцию, которая принимает на вход следующие параметры: source — источник, из которого берутся переменные окружения (как вы помните, в нашем случае это import.meta.env) и необязательный transformKey — функция, которая поможет преобразовать ключи (названия переменных) конфига, если это потребуется.

С источником понятно, но зачем преобразовывать ключи? Дело в том, что мне бы не хотелось постоянно использовать префикс VITE_, поэтому через Proxy я буду подставлять его автоматически.

Функция возвращает этот самый Proxy, который имеет только один handler — get. Его и опишем.

Так как ключ в объекте — это string | symbol, а наш конфиг, по идее — это объект типа Record<string | unknown>, где ключ — это string, то нужно сначала привести этот ключ к строке с помощью String.

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

// buildEnvProxy.ts  export const buildEnvProxy = <T extends Record<string, unknown>>(   source: T,   transformKey: (key: string) => string, ) =>   new Proxy({} as T, {     get(_, key) {       const keyStr = String(key);       const envKey = transformKey ? transformKey(keyStr) : keyStr;        return source[envKey];     },   });

Внутри index.ts объявляем константу ENV и присваиваем ей результат выполнения описанной выше функции, указав в качестве generic Record<string, unknown>, а в качестве параметров: источник — import.meta.env и функцию преобразователь, которая подставляет к ключу корректный префикс:

// index.ts  import { buildEnvProxy } from './buildEnvProxy.ts';  const ENV = buildEnvProxy<Record<string, unknown>>(   import.meta.env,   (key) => `VITE_${key}`, );

Проверяем:

console.log('Without prefix:', ENV.APP_TITLE); console.log('With prefix', ENV.VITE_APP_TITLE);

Получаем результат:

Теперь приступим непосредственно к типизации конфига. Первым делом в этой же директории создаем документ config.types.ts, в котором описываем и экспортируем type Config с типами данных значений:

// config.types.ts  export type Config = {   APP_TITLE: string;   APP_VERSION: number;   SHOW_VERSION: boolean;   COMMENTED_REQUIRED_VALUE: any; };

Вот на этом моменте получается что-то похожее на решение, предоставленное Vite, т.к. типизация под конфиг имеется, но значения никак не преобразуются и по прежнему остаются типа string.

Для дальнейшего преобразования, внутри директории config заводим новую директорию configGetters, а в ней три документа, для начала:

  • getBoolean.ts

  • getNumber.ts

  • getString.ts

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

// getBoolean.ts  export const getBoolean = (   target: Record<string, unknown>,   key: string, ): boolean => {   const value = target[key];    try {     if (value === 'true' || value === true) return true;     if (value === 'false' || value === false) return false;      throw new Error();   } catch {     throw new Error(`Config value for "${key}" is not a boolean: "${value}"`);   } };
// getNumber.ts  export const getNumber = (   target: Record<string, unknown>,   key: string, ): number => {   const value = target[key];    try {     const numValue = Number(value);      if (isFinite(numValue) && !isNaN(numValue)) return numValue;      throw new Error();   } catch {     throw new Error(`Config value for "${key}" is not a number: "${value}"`);   } };
// getString.ts  export const getString = (   target: Record<string, unknown>,   key: string, ): string => {   const strValue = target[key];    try {     if (typeof strValue === 'string') return strValue;      throw new Error();   } catch {     throw new Error(`Config value for "${key}" is not a string: "${strValue}"`);   } };

Если значение из конфига не соответствует ожиданиям — будет выброшена ошибка.

Помимо создания функций, необходимо также указать, какая из функций соответствует конкретной переменной. Для этого поднимемся на уровень выше, т.е. вернемся в директорию config и создадим еще один документ — config.gettersMap.ts, в котором привяжем функции к переменным:

// config.gettersMap.ts  import type { Config } from './config.types.ts';  import { getString } from './configGetters/getString.ts'; import { getNumber } from './configGetters/getNumber.ts'; import { getBoolean } from './configGetters/getBoolean.ts';  export const CONFIG_GETTERS_MAP: {   [K in keyof Config]: (target: Record<string, unknown>, key: K) => Config[K]; } = {   APP_TITLE: getString,   APP_VERSION: getNumber,   SHOW_VERSION: getBoolean,   COMMENTED_REQUIRED_VALUE: getString };

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

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

Заключительной частью данной секции является сбор всего того, что мы написали вместе. Для этого на том же уровне создаем еще один, последний документ — buildConfigProxy.ts. Документ содержит одноименную функцию, которая принимает:

  1. generic для того, чтобы обозначить тип возвращаемого значения;

  2. два параметра:

    • env — источник переменных окружения, который мы получили ранее с помощью функции buildEnvProxy

    • envGettersMap — наш объект с присвоенными функциями преобразования — CONFIG_GETTERS_MAP

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

// buildConfigProxy.ts  export const buildConfigProxy = <T extends Record<string, unknown>>({   env,   envGettersMap, }: {   env: Record<string, unknown>;   envGettersMap: {     [K in keyof T]: (target: Record<string, unknown>, key: K) => T[K];   }; }) =>   new Proxy({} as T, {     get(_, key) {       const keyStr = String(key);       const getter = envGettersMap[keyStr];        if (!getter || typeof getter !== 'function') {         throw new Error(`Config: Proxy getter for "${keyStr}" is not defined`);       }        return getter(env, keyStr);     },   });

Остается только дополнить index.ts вызовом данной функции:

// index.ts  import { buildEnvProxy } from './buildEnvProxy.ts'; import { buildConfigProxy } from './buildConfigProxy.ts'; import { CONFIG_GETTERS_MAP } from './config.gettersMap.ts';  import type { Config } from './config.types.ts';  const ENV = buildEnvProxy<Record<string, unknown>>(   import.meta.env,   (key) => `VITE_${key}`, );  export const CONFIG = buildConfigProxy<Config>({   env: ENV,   envGettersMap: CONFIG_GETTERS_MAP, });

В качестве generic указали тип Config, о чем уже подсказывает IDE:

Проверяем:

# .env  VITE_APP_TITLE="My app" VITE_APP_VERSION=1 VITE_SHOW_VERSION=true # VITE_COMMENTED_REQUIRED_VALUE=
// App.tsx  import { CONFIG } from './config';  export const App = () =>    return (     <h1>       {CONFIG.SHOW_VERSION && (          <>           {CONFIG.APP_TITLE} v{CONFIG.APP_VERSION.toFixed(1)}         </>       )}     </h1>   ); };

Получаем результат:

Как видите, все значения были получены и код отработал корректно. Об этом свидетельствует, как отображение заголовка h1, так и выполненный над переменной CONFIG.APP_VERSION метод .toFixed(1), присущий типу number.

Теперь в .env закомментируем любую вызываемую переменную, например, VITE_APP_TITLE:

# VITE_APP_TITLE="My app" VITE_APP_VERSION=1 VITE_SHOW_VERSION=true # VITE_COMMENTED_REQUIRED_VALUE=

Получаем результат в качестве результата ошибку Config value for "APP_TITLE" is not a string: "undefined" и сразу понимаем, что стоит поправить в конфиге:

И для завершения раскомментируем переменную VITE_APP_TITLE и изменим теперь уже значение переменной VITE_APP_VERSION:

VITE_APP_TITLE="My app" VITE_APP_VERSION=1,0 VITE_SHOW_VERSION=true # VITE_COMMENTED_REQUIRED_VALUE=

Результат — ошибка Config value for "APP_VERSION" is not a number: "1,0":

Круто! Мы проделали хорошую работу: конфиг теперь типизирован и свалидирован. Помимо, простейших преобразований и проверок, таких как getNumber, getString и getBoolean, вы можете сделать любые другие. Например, enum:

export const getEnum =   <T>(     getter: (target: Record<string, unknown>, key: string) => unknown,     allowedValues: T[],   ): ((target: Record<string, unknown>, key: string) => T) =>   (target, key) => {     const value = getter(target, key) as T;      try {       if (allowedValues.includes(value)) return value;        throw new Error();     } catch {       throw new Error(         `Config value for "${key}" is not one of allowed values [${allowedValues}]: "${value}"`,       );     }   };

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

... MODE: getSpecific<'production' | 'development' | 'test'>(getString, [   'production',   'development',   'test', ]), ...

На этом секция про 🙌 хорошее 🙌 решение подошла к концу. Вот такая структура получилась в итоге:

Но что же с VITE_COMMENTED_REQUIRED_VALUE? Эта переменная как раз напрямую связана со вторым, ✨ отличным ✨ способом решения проблемы.

Решение v1

Итак, что если в конфиге необходимо обозначить объект?

VITE_COMMENTED_REQUIRED_VALUE как раз подразумевалась, как такая переменная.

Можно написать еще функций преобразования, подобных getNumber, getBoolean и т.д., но если таких переменных будет много и они все будут содержать объекты разных структур, то это уже не кажется хорошей идеей.

Здесь на помощь приходит Zod.

На официальном сайте сказано следующее:

Zod — это TypeScript-first библиотека объявления и проверки схем. Я использую термин «схема» для широкого обозначения любого типа данных от простого string к сложному вложенному объекту.

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

import { z } from "zod";  // создание схемы для строк (string) const mySchema = z.string();  // парсинг mySchema.parse("tuna"); // => "tuna" mySchema.parse(12); // => throws ZodError  // "безопасный" парсинг (не throw error валидация провалилась) mySchema.safeParse("tuna"); // => { success: true; data: "tuna" } mySchema.safeParse(12); // => { success: false; error: ZodError }

И еще немного значимых плюсов (опять же указанных на оф. сайте):

  • 0 зависимостей;

  • работает в Node.js и всех современных браузерах;

  • крошечный: 8kb minified + zipped;

  • работает с JS (TS необязателен) — в данном случае неактуально, но круто!

Приступим к внедрению Zod. Первым делом устанавливаем библиотеку, я сделаю это с помощью yarn:

yarn add zod

А затем удаляем из директории config ВСЕ, что мы написали в секции «Решение v0», кроме index.ts и buildEnvProxy.ts. Да, нам больше не требуются функции преобразования, buildConfigProxy, CONFIG_GETTERS_MAPZod все сделает за нас! (почти)

Создаем в директории новый документ — config.schema.ts. В этом документе опишем схему конфига и экспортируем функцию, которая будет принимать на вход наш ENV, парсить его и в случае успешного парсинга возвращать валидный объект конфига. В случае неудачного парсинга из-за неправильно указанного (или вовсе неуказанного) значения переменной окружения, функция будет выбрасывать ошибку.

Так как конфиг — это объект, обозначим схему, как z.object({}), а внутри, в фигурных скобках опишем этот объект с помощью других методов Zod’а:

// config.schema.ts  import { z } from 'zod';  const configSchema = z.object({   APP_TITLE: z.string(),   APP_VERSION: z.number(),   SHOW_VERSION: z.boolean(), });

Ниже экспортируем ту самую функцию, которая будет парсить конфиг:

export const parseConfig = (configObj: Record<string, unknown>) => {   const parseResult = configSchema.safeParse(configObj);    if (!parseResult.success) throw parseResult.error;    return parseResult.data; }

Внутри вызываем у схемы метод safeParse, в который передаем объект конфига. Результатом выполнения метода будет некий объект, который всегда содержит логическое свойство success, а также data в случае успеха и error в случае неудачи. Мы используем все эти свойства и в случае success возвращаем data, а в случае неудачи выбрасываем error.

Далее идем в index.ts и убираем все лишнее, то есть несуществующие импорты (потому что ранее мы удалили экспорты) и значение экспортируемой константы CONFIG, мы его перепишем:

import { buildEnvProxy } from './buildEnvProxy.ts'; import { parseConfig } from './config.schema.ts';  const ENV = buildEnvProxy<Record<string, unknown>>(   import.meta.env,   (key) => `VITE_${key}`, );  export const CONFIG = parseConfig(ENV);  export type Config = typeof CONFIG;

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

И сразу получаем ошибку. А также обратите внимание на белую страницу, она действительно даже не отрисовалась! В ошибке говорится о том, что переменные APP_VERSION и SHOW_VERSION должны быть number и boolean соответственно, но приходит string. Так и есть, как помните все указанные значения в .env являются строками. Следовательно, необходимо выполнить преобразование этих строк, и Zod имеет несколько способов сделать это. Я воспользуюсь способом «принуждение» — .coerce, потому что пока что мы имеем дело с примитивами (сейчас объясню):

const configSchema = z.object({   APP_TITLE: z.string(),   APP_VERSION: z.coerce.number(),   SHOW_VERSION: z.coerce.boolean(), });

В данной схеме как бы говорится «возьми переменную APP_VERSION и приведи ее к типу number«. Аналогично и с SHOW_VERSION. Если приведение к указанному типу и последующая валидация полученного значения проходит неудачно — получаем ошибку. Проверяем с правильно указанными значениями:

Все работает отлично. А теперь исправляем APP_VERSION на 1,0 и получаем ошибку о том, что ожидается значение типа number, но получается NaN (да, я знаю, но вот так — хорошо же!). Если закомментировать в конфиге какую-либо из описанных в схеме переменных — также получим ошибку, но о том, что вместо ожидаемого значения пришло undefined.

Все работает, как надо и Zod уже закрыл все изначальные потребности. Наконец займемся переменной COMMENTED_REQUIRED_VALUE. Определимся, что данная переменная должна содержать массив простых объектов, что-то вроде:

Array<{   solution: string;   rate: 'A' | 'B'; }>

Сразу становится понятно, что такой массив необходимо передавать в формате JSON, поэтому опишем переменную в конфиге следующим образом:

VITE_APP_TITLE="My app" VITE_APP_VERSION=1 VITE_SHOW_VERSION=true VITE_COMMENTED_REQUIRED_VALUE='[{"solution":"v1","rate":"A"},{"solution":"v0","rate":"B"}]'

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

Абсолютно точно, изначально значение является строкой, поэтому необходимо указать метод .string(). Когда получаем валидную строку, нужно проверить, что она также является валидным JSON-форматом. У Zod нет решения «из коробки» конкретно для JSON, но зато есть метод .transform(), который принимает в качестве параметра функцию преобразователь. Эта функция в свою очередь в качестве параметра имеет наше дошедшее к этому моменту значение — просто валидную строку. Эту строку нужно распарсить, как JSON — это и есть проверка и преобразование. Получается .transform((value) => JSON.parse(value)). А дальше все, как и в случае со схемой самого конфига: .object(...) внутри которого описываем свойства solution и rate. Но для того, чтобы сделать проверку над преобразованным методом .transform() значением, необходимо обернуть его методом .pipe(), то есть обозначить «пайплайн» проверки.

И единственное отличие в том, что данный преобразованный объект все таки является массивом. Для этого указания просто добавляем после метода .object() метод .array(): .object(...).array(). Посмотрим, что получилось:

... COMMENTED_REQUIRED_VALUE: z     .string() // Проверяем строку     .transform((val) => JSON.parse(val)) // Преобразуем в JSON     .pipe( // Указываем "пайплайн"       z         .object({ // Проверяем объект           solution: z.string(),           rate: z.enum(['A', 'B']),         })         .array(), // Проверяем, что это именно массив объектов     ), ...

В коде использовался еще один метод, который не упоминался ранее — .enum(). С помощью данного метода можно строго задать значения, которые могут быть приняты на вход. Кстати, помимо таких «enum’ов», Zod умеет также работать с нативными enum.

В конце концов слегка дополним компонент и посмотрим, что получилось:

import { CONFIG } from './config';  export const App = () => {   return (     <>       <h1>         {CONFIG.SHOW_VERSION && (           <>             {CONFIG.APP_TITLE} v{CONFIG.APP_VERSION.toFixed(1)}           </>         )}       </h1>       {CONFIG.COMMENTED_REQUIRED_VALUE.map(({ solution, rate }) => (         <div>           Solution {solution} — {rate}         </div>       ))}     </>   ); };

Результат:

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

Большим плюсом является то, что данное решение подходит для множества окружений: если проект Vite — используем функцию buildEnvProxy, куда передаем источник и transformKey, который подставляет префикс _VITE; если вдруг проект переводится на Webpack, то достаточно просто передать в функцию новый источник и убрать transformKey. А вот так можно улучшить эту функцию:

export const buildEnvProxy = <T extends Record<string, unknown>>(   envSources: {     source: Partial<T>;     transformKey?: (key: string) => string;   }[], ) =>   new Proxy({} as T, {     get(_, key) {       return envSources         .map(({ source, transformKey }) => {           const keyStr = String(key);           const envKey = transformKey ? transformKey(keyStr) : keyStr;            return source[envKey];         })         .find((v) => v !== undefined);     },   });

Теперь мы можем передавать сразу несколько источников и указывать или не указывать transformKey для каждого из них. Handler get будет искать запрашиваемую переменную последовательно во всех источниках, а порядок источников можно менять и тем самым настраивать приоритет.

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

Здесь гитхаб репозиторий с каждым решением (двумя) в отдельной ветке: https://github.com/bodasooqa/vite-react-config-validation


ссылка на оригинал статьи https://habr.com/ru/articles/743798/

Микроменеджер — горе в команде

Эта статья о микроменеджменте, его причинах и разрушительных последствиях. Обсудим, какой вред он наносит, подсветим проблемы, с которыми сталкиваются руководители из-за микроменеджмента, и покажем способы их  решения. А ещё, справедливости ради, в этом тексте будут примеры ситуаций, когда микроменеджмент всё же может быть нужен и полезен. Статья написана на основе доклада Евгения Антонова, старшего технического менеджера проектов Yandex Infrastructure, автора телеграм-канала «Тимлид Очевидность», соведущего подкаста «Кода кода» и ИТ-консультанта  TeamLeadConf 2023.

Почему родился этот доклад и статья

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

Также хотелось дать людям повод порефлексировать или поделиться этим материалом с кем-то, кому неплохо было бы тоже провести самодиагностику.

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

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

Из-за микроменеджмента страдают сотрудники, которых «микроменеджерят». Страдают руководители, которые бесконечно перерабатывают, выгорают, не успевают,  пытаются всё за всех сделать и проконтролировать. В итоге из-за такой неэффективности страдает бизнес, который за всё это платит.

Что такое микроменеджмент

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

У микроменеджмента есть ряд отличительных признаков. Вот чем занимается на работе микроменеджер.

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

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

Концентрируется на мелочах. Микроменеджер сосредотачивается на мелочах. Это следствие первого признака — контроля любого шага в процессе.

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

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

Хочет полного подчинения остальных. Микроменеджер негативно воспринимает любую несогласованную активность, ведь в его картине мира он уже придумал идеальное решение, и подчинённому осталось только его выполнить.

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

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

Стоит на своём до последнего. Микроменеджер часто стремится настоять на своём, потому что уверен в своей абсолютной правоте. В его представлении есть два мнения — его и неправильное.

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

Замыкает все важные дела на себя. Так как микроменеджер чересчур всё контролирует, он уверен, что только он знает единственно правильное решение, и зачастую завязывает все важные дела на себя.

Дальше мы поговорим о том, почему возникает такое поведение.

Откуда берётся микроменеджмент

Есть несколько причин возникновения микроменеджмента. Разберём всё по порядку.

Причина 1. Тревожность и страх. Страшно отпускать контроль. Тревожно оттого, что что-то может пойти неидеально.

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

Причина 2. Недоверие к коллегам. Микроменеджер может считать, что он самый умный, а остальные не столь хороши, поэтому надо делать только так, как он говорит. На диалог он идёт с неохотой.

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

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

Причина 4. Амбиции и эго. Порой они — спутники микроменеджера. Это же так круто — чувствовать свою важность, наслаждаться ей. Считать, что знаешь и умеешь всё лучше других и все обязательно должны тебе подчиняться. Ты один тут такой умный, всё на тебе держится, ничего-то без тебя не могут. Это и подпитывает некоторых  микроменеджеров.

Причина 5. Job security. Если микроменеджер — «во всех бочках затычка», всё про всех знает, все процессы на себя завязал и всё старается контролировать, то это и есть один из вариантов обеспечения job security. Довольно вредный для команды и компании, но зато лично микроменеджеру определённую безопасность на работе обеспечивает.  Его, скорее всего, не уволят, ведь всё работает исключительно под его указку.

Но тут есть и негативный эффект — его никогда и не повысят,  ведь если сдвинуть его с занимаемой позиции, всё развалится.

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

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

Причина 7. Нежелание и боязнь изменений. Из-за этого микроменеджмент скорее не начинается, а продолжается.

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

Почему микроменеджмент — это плохо

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

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

Небольшой спойлер: потом всё будет плохо.

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

Отличия менеджмента от микроменеджмента

Адекватный менеджер отличается от микроменеджера тем, что говорит не КАК делать, а ЧТО делать, осуществляя не постоянный, а промежуточный контроль.

Несколько лет назад на TeamLead Conf был хороший пример разницы микроменеджмента и менеджмента: вы приходите в ресторан, чтобы съесть омлет. Заказываете омлет, повар его готовит. Это менеджмент.

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

Звучит довольно абсурдно, но, если вдуматься и присмотреться, порой в нашей работе можно встретить абсурд аналогичного уровня.

Второе различие между менеджментом и микроменеджментом — в уровне контроля. При менеджменте он промежуточный, периодический, при микроменеджменте — постоянный.

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

Промежуточное сбалансированное состояние между микроменеджментом и чайка-менеджментом и есть нормальный менеджмент.

Зачем команде руководитель

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

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

Но от руководителя требуется и достижение командой результата в будущем. И иногда это чуть ли не противоположные вещи.

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

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

Получается, что основные задачи руководителя:

  • достижение командой результата сейчас;

  • достижение командой результата в будущем;

  • достижение командой результата без руководителя.

К сожалению, микроменеджмент противоречит и мешает всем этим задачам.

Вред микроменеджмента

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

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

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

Перформанс команды в моменте у микроменеджмента тоже страдает, потому что микроменеджер, как бы он ни пытался отрастить, как Спанч Боб с этой картинки, дополнительные руки, всё сделать не успеет — это просто физически не получится.

В результате перформанс всей команды упрётся в перформанс одного конкретного микроменеджера.

Пример из жизни. Команда успевает сделать множество всего, но релизить это нельзя, потому что микроменеджер занят и не может посмотреть и апрувнуть. А потом ещё уезжает в отпуск, и команде приходится две недели ждать его возвращения, а  дело так никуда и не двигается.

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

В ответ ей предлагают нанять кого-нибудь взамен. Но нанимать команда не умеет, потому что и этим занимался микроменеджер. И бизнес не умеет, потому что тоже расслабился и не следил ни за чем. Ведь всё же работало. В итоге все процессы «встают колом».

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

1. Они уходят и «дальше сами разбирайтесь, как хотите».

2. Они остаются, но взамен получают часть бизнеса.

И им отдавали часть бизнеса, хотя это было очень больно и накладно. Но компания понимала, что без микроменеджера дело встанет очень надолго, а останавливаться надолго было нельзя.

Итак, микроменеджмент — это не благо, а вред, ведь с ним:

  • команда не развивается, а стагнирует. Со временем даже деградирует;

  • страдает качество.Микроменеджер не успевает сделать всё сам с нужным качеством;

  • единая точка отказа. После ухода микроменеджера наступает коллапс.

Микроменеджмент менеджеров

Микроменеджмент менеджеров подрывает саму идею руководства.

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

Представим, что есть тимлид с командой в подчинении и собственным руководителем, который его микроменеджерит. Этот руководитель говорит тимлиду: «Встречи one-to-one с подчинёнными провожу я, у кого какая зарплата, кого увольнять, кого нанимать, на каком стеке работать, даже какой грейд у кого будет, тоже решаю я».

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

На этом фоне, вполне возможно, у тимлида возникнет конфликт с руководителем. Потому что если его наняли или повысили до тимлида, но при этом ему не дают делать то, что требуется от тимлида, или не доверяют, то зачем тогда продолжать вместе работать?

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

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

Выученная беспомощность

 

В теме микроменеджмента очень важно обсудить понятие выученной беспомощности.

Что это такое

Однажды проводился эксперимент на собаках. Взяли две клетки, одна была обычной, а во второй пол был под напряжением, и собак периодически били током. Сначала они пытались найти выход из клетки, но вскоре понимали, что выхода нет, ложились и смирялись.

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

Как это проявляется в работе?

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

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

Пример из жизни. Хороший специалист, проработавший 10 лет в индустрии, которого замикроменеджили в последние несколько лет работы, привык за каждой мелкой кнопочкой или надписью ходить за одобрением к руководителю. И самостоятельных решений он уже не принимал, даже если надо было срочно и быстро. Всё только строго через руководителя. А со временем он уже и сам признавал, что не хочет ничего решать. Какой смысл? Всё равно же всё до мельчайших деталей должно быть не так, как он, специалист, предложит, а так, как его руководитель захочет. Для чего стараться?

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

Как победить микроменеджмент

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

Но микроменеджерам бывает сложно и страшно делегировать. Если вы нашли в себе черты микроменеджера и вам страшно или не хочется делегировать, то вы должны помнить: вы не можете всё досконально знать за всех, если только у вас не огромная голова, как у Мегамозга, и нет маховика времени, как у Гермионы. Сто процентов, что вы не будете достаточно компетентны и не сможете физически всё успевать делать за всех.

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

Но при  делегировании есть три важные составляющие:

  • обязанности; 

  • полномочия;

  • вознаграждение.

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

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

Ситуационное лидерство

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

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

Микроменеджмент является отправной точкой на этом пути развития сотрудника.

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

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

Распространение знаний

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

Распространяя знания, вы доносите другим, что, как и почему вы делаете, какая у вас стратегия. Людям становится понятно, что вы не работаете с ними по принципу «я — начальник, ты — дурак» или «меньше знаешь – крепче спишь».

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

Как распространять знания

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

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

Через людей. Классический институт менторинга, когда в пару к новому сотруднику становится старший товарищ.

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

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

Когда микроменеджмент оправдан

Бывает ли микроменеджмент оправдан? Есть две ситуации, когда он временно уместен:

  1. В команде низкий уровень мотивации и компетенции. Это отсылка к ситуационному лидерству, когда у вас низкоквалифицированный джун. Первое время ему действительно нужно уделять много внимания. Но важно вовремя «отпустить велосипед». 

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

Похоже, это все варианты, когда микроменеджмент оправдан. Если у вас есть ещё какие-то, напишите про них в комментариях к статье.

Подведём итоги

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

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

  • Нужно уметь передавать знания и заниматься этим регулярно. Настоящие и будущие коллеги будут вам благодарны.

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

Бонус: что почитать про управление командой

Книги, которые позволяют лучше понять роль руководителя в команде:

  • Питер Друкер «Эффективный руководитель».

  • Ицхак Адизес «Идеальный руководитель. Почему им нельзя стать и что из этого следует».

Книги, которые наглядно расскажут, чем плохо «всё завязывать на себя» и как одно «бутылочное горлышко» может тормозить целую большую систему:

  • Элияху Голдратт «Цель. Процесс непрерывного совершенствования».

  • Джим Кин, Джордж Спаффорд, Кевин Бер «Проект Феникс. Роман о том, как DevOps меняет бизнес к лучшему».


ссылка на оригинал статьи https://habr.com/ru/companies/oleg-bunin/articles/744104/