пятница, 12 октября 2012 г.

Анатомия ошибки

Вместо предисловия

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

Контекст

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

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

Сразу обзовем эти системы социотехническими. Так как это очень большой теоретический пласт, вкратце объясню что это такое.

У нас есть организация. Обзовем ее системой.

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

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

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

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

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

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

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

Первые сюрпризы

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

И в этом всем вареве есть парочка неприятных сюрпризов.

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

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

Второй неприятный сюрприз выглядит вот так:

Я про него уже писал раньше, но на всякий случай повторю.
Это модель тупого и острого конца. Ее придумали Доктор Вудс и Доктор Кук.

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

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

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

Обратно на фабрику

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

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

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

Если вы думаете, что никто еще не пытался проделать подобных фокусов, то вы жестоко ошибаетесь. Взять хотя бы индустрию мирного атома в США. Пресловутый Three Mile Island.

Это АЭС расположенная в штате Пенсильвания, примерно в 150км от Филадельфии, да и до Нью-Йорка там тоже недалеко. По понятным причинам автоматики там было более чем порядочно, и персонал состоял в основном из операторов этой самой автоматики. В 1979 году там сломался датчик, и автоматика сошла с ума. Операторы, перегруженные противоречивой информацией, поступающей с автоматики, пытались разобраться в чем проблема, но в итоге потеряли кучу времени, и случилась самая тяжелая ядерная авария в США. Это была бы самая тяжелая ядерная авария в мире, если бы через 7 лет не случился Чернобыль.

Как итог: один из реакторов не эксплуатируется до сих пор, а зараженную радиацией по самое нихачу зону в довольно густо населенном уголке США только в середине 90-х закончили чистить. К тому же, анализ ситуации привел к тотальному пересмотру обучения персонала на американских АЭС, сильно изменил подход к автоматике, которой пичкают ядерные станции, начали отрабатывать различные экстренные меры вплоть до эвакуации населения вокруг АЭС.

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

Шум в эфире

Для начала давайте посмотрим, как в любой системе происходит ошибка. Возьмем, например, большой и сочный факап. Между непосредственным появлением самой ошибки и разбором полетов условно выделим четыре фазы:
  1. Обнаружение. Очевидно, т.к. не обнаруженная проблема таковой не считается
  2. Исследование/Локализация. Прежде чем что-то делать, нам нужно понять, в чем именно суть проблемы, и надо ли ее вообще чинить
  3. Починка.
  4. Убедились, что все ОК. Мы же серьезные люди и не считаем фазу починки завершенной, пока не убедились, что проблема устранена.
В обычной ситуации все выглядит примерно так:
Нашли проблему - тут же испугались. Оценили масштабы бедствия, нашли что и где чинить - может даже слегка отпустило. Какое-то время чиним, и чем дольше мы это делаем, тем больше нарастает напряжение. А потом все становится ок, и нас отпускает.

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

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

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

Уборка мусора

Как писал Талеб - "человек - животное объясняющее". Нам нужно знать, почему произошла проблема. Ответ "не знаю" для нас неприемлим. Вы часто видите менеджеров которые честно говорят "не знаю"? Да этих чуваков учат чему угодно, только не этому. Другими словами:
"Основное правило: любое объяснение лучше его отсутствия" 
- Ницше про Root Cause Analysis
Да, Root Cause Analysis это именно то, чем в хорошем обществе занимаются после факапов. Но тут впору вспомнить о том, что у нас всю дорогу шум в эфире. Это приводит к двум серьезным (их на самом деле больше, но эти две самые опасные) проблемам - Ошибке Ретроспекции и Отклонению в Сторону Результата.

Ошибка Ретроспекции заключается в том, что знание результата сильно влияет на анализ произошедшего. Реконструируя произошедший факап мы из подручных материалов сооружаем сильно упрощенное подобие реальности. То есть строим примерно такое:
Вместо вот такого:
Это приводит к соверешнно бесполезным советам вида "надо было быть внимательнее", потому что "все же как на ладони видно, надо просто не проморгать". И мы... соглашаемся. То есть на сложную проблему мы находим универсальный ответ "надо быть внимательнее". И пофиг, что принцип системостроительства говорит, что идеальная работа каждого звена это утопия! У нас есть универсальный ответ - "надо быть внимательнее". Как мы раньше жили без этого знания - непонятно. Почему я не был тогда достаточно внимателен? Не важно. Наш очень классный ответ на этот вопрос не отвечает. А другой на моем месте был бы достаточно внимателен? Тоже не важно - наш универсальный ответ такие глупые вопросы просто игнорирует.

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

Берем обычного ботана. Ботан идет домой поздно вечером. У ботана есть два варианта - срезать через темные переулки заводских окраин или долго топать по людной освещенной улице. И вот, скажем, ботан решает срезать. Не важно почему - просто решает. Ошибка. И ботан находит кучу денег. И доходит домой. И у него случается Отклонение в Сторону Результата - он решает, что поступил правильно, потому что нашел кучу денег. Т.е. считает ошибочное решение правильным, потому что оно случайно принеслу ему кучу денег. А потом он решает повторить решение - оно же правильное. И с ним случается то, что обычно случается с одинокими ботанами поздно вечером на заводских окраинах - ничего хорошего.

Теперь еще раз, для закрепления, напишу то, что любой мало-мальски профессиональный картежник выучивает очень быстро:
"Если ты получил кучу плюшек - это еще не значит, что ты все делал правильно"

Теперь перейдем непосредственно к Root Cause Analysis. Есть ряд техник, которые, к сожалению, используются еще и для оценки рисков. Вот некоторые названия:
  • Ишикава
  • FMEA
  • "Пять почему"
  • Дерево отказов
Их можно перечислять еще долго, но все они похожи на принцип домино. "Пять почему" отлично иллюстрируют всю бездну ужаса подобных методик. У вас случилась проблема и вы задаете вопрос "почему?". Ответив на этот вопрос вы задаете вопрос "почему?" уже ответу на первый вопрос. И так пять раз. Вы не получаете ответ на то, почему в действительности произошла ошибка - вы просто выстраиваете небольшую линейную цепочку. Или большую цепочку, если это Ишикава. Или большую ветвистую, но все еще линейную, если это дерево отказов. То есть вместо поиска причин вы делает вот это:
Такие вот узаконенные методы оценки рисков, целиком состоящие из Отклонения в Сторону Результата и Ошибки Ретроспекции. К тому же они очень сильно фокусируются на компонентах заданной цепочки, всячески игнорируя окружение.

Есть чуть более продвинутая модель:
Это Модель Швейцарского Сыра. Ее придумал Доктор Джеймс Ризон. Я о ней уже писал ранее, но опять повторю.
У нас есть куча слоев защиты. И согласно правилу моделестроения - все неидеальные. Т.е. дырявые, как швейцарский сыр. Как только дырки совпали - случилась ошибка.

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

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

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

Часть проблем тут технические. Часть люди. Часть вообще черте что. При этом часть проблем, вроде найма, вообще системного характера. Обычные методики Root Cause Analysis игнорируют системные проблемы.

Убрав любой из пунктов мы или не получим проблему вовсе или получим, но куда менее страшную. Очень похоже на сырную модель, только не линейное. При этом большую часть из этих проблем по традиции можно назвать "Root Cause". Какую именно? Зависит от ваших предпочтений. Не нравится администратор? Давайте его. Маркетинг? Ну вы поняли.

Мы можем начать рассматривать каждый элемент отдельно. Это сильно упростит задачу. И выглядеть будет как-то так:
Но тут получается проблема, с которой знаком каждый тестировщик, занимавшийся интеграционными тестами - каждый кусок по-отдельности может работать хорошо, а вот их взаимодействие может приводить к нежелательным последствиям. В плане организации все еще хуже - допустимые вариации в работе того или иного куска организации могут быть в норме, но все вместе они порой будут создавать резонанс с крайне печальными последствиями. Доктор Холлнагель назвал это явление "Функциональный Резонанс".

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

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

Учиться, учиться и еще раз учиться.

Откуда, собственно, учиться? Начнем с трех небольших тезисов.

Тезис Первый. Человеческий фактор - это не причина ошибки, а лишь побочный эффект.

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

Тезис Второй. Успех - это частный случай ошибки.

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

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

Тезис Третий. Ошибка - это частный случай успеха.

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

Но по большому счету разницы между факапом и успехом нет. Ваша система просто работает, и работает нормально, пока не случится резонанс нескольких ее компонент, который приводит к факапу. Вспомните модель швейцарского сыра, один слой повернулся - и все нормально. Нет ошибки. Повернулся не так - встречайте проблему. И чтобы этого не происходило надо минимизировать количество дырок на каждом слое. Надо искать источники энтропии. Нужно не просто задавать себе вопрос "почему случился факап?", но и вопрос "почему у нас все хорошо?". Это здорово увеличивает выборку для анализа, ведь если вы читаете это, то у вас дела чаще идут хорошо, чем плохо. Так же это позволяет хоть как-то бороться с Ошибкой Ретроспекции и Отклонением в Сторону Результата - у вас будет больше разнообразных результатов, на которых вы почти наверняка будете строить разные цепочки событий.

То есть учимся не только на ошибках, но и на успехах.

И на основе этого уже выстраивается стандартная цепочка превентивных мер:

  1. Прогнозирование. Т.е. попытки предугадать то, что стоит ожидать
  2. Мониторинг. Т.е. надо знать куда смотреть (так проще искать - вспомните невидимую гориллу)
  3. Ответные меры. Т.е. в случае чего надо не бегать кругами, а просто знать, что делать для минимизации проблемы. Вырабатывать план эвакуации, когда у вас уже плавится реактор - плохая идея
  4. Обучение. Т.е. нужно точно знать, что произошло. Это самый важный пункт, т.к. без него первые три не работают - им неоткуда черпать информацию
И для упрощения этого обучения нужно не упускать из виду следующие вещи:
  • Избегать ошибок оценки решений - ошибки ретроспекции и отклонения в сторону результата
  • Понимать, что происходит на "остром" конце. Подобные коммуникации - это практически единственный способ справляться со сложностью системы
  • Проверять, к каким уязвимостям могут привести изменения на любом уровне системы
  • Технологии нужны, чтобы помочь человеку, а не для того чтобы его заменить. Особенно, если этот человек принимает кричиные и сложные решения
  • Надо понять, что безопасных систем не существует в принципе - все ломаются. Путь самурая вас прикончит, тогда как путь минимизации ущерба от ошибок и их частоты может сильно помочь
  • Человеческая ошибка - это данность, она прилагается к любой сложной системе.
  • Не стоит пытаться оправдывать человеческой ошибкой что-либо - это путь, на котором вы отказываетесь учиться на ошибках
  • Человеческая ошибка не случайна

4 комментария:

  1. Молодец, Серега. Интересно пишешь

    ОтветитьУдалить
  2. Есть 3 интересные работы на эту тему:
    Дитрих Дернер Логика Неудачи (Dietrich Doerner The Logic of Failure)
    Klein The Sources of Power
    Chip Heath, Richard P. Larrick, and Joshua Klayman COGNITIVE REPAIRS: HOW ORGANIZATIONAL PRACTICES CAN COMPENSATE FOR
    INDIVIDUAL SHORTCOMINGS - русский перевод здесь
    http://blog.perevedem.ru/2010/08/25/%D0%9A%D0%BE%D0%BC%D0%BF%D0%B5%D0%BD%D1%81%D0%B0%D1%86%D0%B8%D1%8F-%D0%BD%D0%B5%D0%B4%D0%BE%D1%81%D1%82%D0%B0%D1%82%D0%BA%D0%BE%D0%B2-%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%BD%D0%B8%D1%8F-i/

    ОтветитьУдалить
  3. У Дернера есть еще старенькая хорошая статья “On The Difficulties People Have In Dealing With Complexity".

    Но в целом да, оно. Спасибо :)

    ОтветитьУдалить
  4. Спасибо большое, статья просто великолепная!
    Ушла в дальнейшее чтение Кука:)

    ОтветитьУдалить