«Остаться в живых» Лоуренса Гонсалеса

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

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

И это логично, потому что он считает, что:

Универсальные правила выживания способны принести пользу в любой трудной ситуации, связанной с повышенным нервно‑эмоциональным напряжением: развод; потеря работы; тяжелые физические травмы; борьба с болезнью; управление предприятием в стремительно изменяющемся мире

Начинается книга с рассказа о том, что человек — не такое уж рациональное существо, как мы привыкли думать:

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

…во время опасности человек должен осознавать, что он несколько неадекватен. Причем измененное состояние сознания затрагивает самые разные сферы: и восприятие, и познание, и память, и чувства

И рассказа, почему в состоянии стресса трудно вспомнить простые вещи:

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

В целом эмоции работают быстрее, чем рациональная часть мозга, потому что эволюция их оттачивала тысячелетиями:

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

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

Организм до сих пор считает себя в состоянии постоянного выживания:

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

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

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

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

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

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

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

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

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

Очень хорошо о том, как люди ставят себя в центр мира, а потом разочаровываются:

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

Я не в состоянии изменить мир; единственное, что я могу изменить, — это самого себя. Чтобы в этом мире выжить, необходимо его видеть и понимать. Я должен был признать мир, в котором оказался. Я должен был успокоиться и начать в нем жить. Точно так же как в дзен‑буддизме, боевых искусствах и стрельбе из лука, такое поведение поможет перенести восприятие и ощущения в настоящее

И хорошо о том, что реальность не познаваема в принципе, а мы основываем представление о мире только на том, что дают нам наши органы чувств:

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

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

Необходимые вам знания начинаются не с информации, а с опыта и восприятия

Нейробиолог Джозеф Леду… писал: «Мозг, который вспоминает, не является тем же мозгом, который запомнил изначальную информацию. Информация должна быть обновлена, чтобы воспоминание стало мозгу понятным». Вот одна из печальных причин, почему память так несовершенна

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

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

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

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

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

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

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

И это отлично описывает программные системы. Например, вот почему нужно писать тесты:

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

А вот о том, как команда пилит типичный проект:

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

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

Но есть и конкретно про выживание:

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

Основной вывод, сделанный мной, — не впадать в панику и сохранять душевное равновесие

Первое и самое главное жизненное правило: будь здесь и сейчас

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

Даже юмор есть!

На доске объявлений я прочитал: «Хочу умереть во сне, как умер мой дедушка». Ниже мелким шрифтом была приписка: «А не с воплями и криками, как умерли пассажиры той машины, которой он управлял». Типичный юмор летчиков

Короче, рекомендую.

С этой книгой зайдут:

«Чистый код», часть 3

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

Глава 9. Юнит‑тесты

Коротко:

  • тесты важны настолько же, насколько важен продакшн‑код;
  • тесты должны быть прозрачными и понятными.

Три закона ТДД:

  • писать продакшн‑код можно после того, как будет написан отказной тест для этого кода;
  • объём кода для этого теста не должен быть больше, чем необходимый, чтобы тест отказал;
  • объём продакшн‑кода не должен быть больше, чем необходимый, чтобы тест был пройден.

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

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

// плохо
const result = testedFunction()

it('should be okay', () => {
  expect(typeof result).toEqual('number')
  expect(result / Math.abs(result)).toEqual(1)
  expect(isFinite(result)).toEqual(true)
})

// хорошо
const result = testedFunction()

it('should return number', () => {
  expect(typeof result).toEqual('number')
})

it('should return positive number', () => {
  expect(result / Math.abs(result)).toEqual(1)
})

it('should return finite number', () => {
  expect(isFinite(result)).toEqual(true)
})

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

Глава 10. Классы

Коротко:

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

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

Название класса должно полно отображать, какие обязанности он выполняет. Имя же помогает определить обязанности класса. Слова наподобие Processor, Manager, Super намекают, что класс слишком большой, и его можно разбить. Идеально — когда класс можно описать 25 словами (прим. автора поста — откуда такие цифры, ну?) без использования «но», «если», «или».

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

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

Главы 11–12. Системы и проектирование

Коротко:

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

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

const getService = () => {
  if (!service) service = new SomeService()
  return service
}

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

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

Дизайн (в плане проектирования программной системы) должен быть прозрачным и простым. Простой дизайн:

  • проходит все тесты;
  • не содержит дублирования;
  • отражает то, что хотел сделать программист;
  • содержит минимально‑необходимое количество классов и компонентов.

Оставшиеся главы

Я рекомендую прочесть полностью самим.

В 13‑й рассказывается о параллельных вычислениях, для веба не очень актуально, но интересно. В 16‑й — о рефакторинге, когда его проводить, с чего начинать. Самая интересная — 17‑я. Это большой список признаков, что код необходимо отрефакторить. В ней признаки сгруппированы по типам: комментарии, зависимости, функции и т. д.

Предыдущие части и ссылки по теме

Гданьск, октябрь 2017

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

Вид на улице — 1
Вид на улице — 2
Вид на улице — 3

Клёвые фасады:

Фасады домов — 1
Фасады домов — 2

Но во дворах бывает и так :–)

Большая лужа во дворе — 1
Большая лужа во дворе — 2

Иногда улицы становятся вот настолько узкими:

Узкие улицы — 1
Узкие улицы — 2

Вода в городе тоже есть, река Мотлава:

Вид на реку Мотлава

Костёл Святой Катажины:

Костёл Святой Катажины — 1
Костёл Святой Катажины — 2

Ещё немного города:

Вид с улиц города — 1
Вид с улиц города — 2
Вид с улиц города — 3
Вид с улиц города — 4

Детская площадка:

Детская площадка

С рекламой и вывесками тоже не всегда всё хорошо:

Старое здание, завешенное рекламой

Если будете в Гданьске, обязательно сходите в музей Второй мировой войны. Там, наверное, самая сильная экспозиция, которую я видел.

Музей Второй мировой войны — 1
Музей Второй мировой войны — 2
Музей Второй мировой войны — 3
Музей Второй мировой войны — 4

Плакаты и газеты:

Вырезка из газеты с сообщением о нападении на Польшу
Советская пропаганда — 1
Советская пропаганда — 2
Плакат «Искореним шпионов и диверсантов»

Раздел Польши:

Карта с границей раздела Польши

Блокада Ленинграда:

Экспозиция, посвящённая блокаде Ленинграда

Оружие:

Оружие — 1
Пулемёт Максим
Сравнение размеров бомбы с человеческим ростом

Энигма:

Шифровальная машина Энигма

Танки:

Руины города с танком по центру

Весь музей построили вокруг двух танков.

Вырезка из истории музея

Разрушенные города:

Фотографии руин городов с их названиями

Одна из трещёток, которыми предупреждали о газовых атаках:

Трещётка, которыми предупреждали о газовых атаках

Бомбоубежище:

Воссозданная обстановка бомбоубежища

А вот на колесо обозрения не советую. Билет туда стоит дороже: 28 злотых (420 ₽ по курсу на октябрь) против 23 в музее (350 ₽), а вид примерно такой:

Вид с колеса обозрения — 1
Вид с колеса обозрения — 2
Вид с колеса обозрения — 3

Из мест «поесть» рекомендую Mandu — порция дамплингов с курицей стоит 20 злотых (300 ₽).

Есть хорошее мексиканское место — Pueblo. Кесадильи с сыром 17 злотых (260 ₽). Чаевые в 10% включают в счёт.

Роллы — в Mito Sushi. Такой набор обойдётся в 135 злотых (2100 ₽).

Мороженое — в Paulo Gelateria. Порция мороженого — 18 злотых (270 ₽), какао — 10 (150 ₽).

Вегетарианское меню — Avocado. Фалафель с кучей риса — 19 злотых (290 ₽).

«Чистый код», часть 2

Продолжаем читать книгу «Чистый код» Роберта Мартина. В прошлый раз мы обсудили именование переменных, функции и комментарии. Сегодня рассмотрим главы 5–8.

Глава 5. Форматирование

Коротко:

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

Форматирование кода помогает его быстрее считывать. Вертикальное и горизонтальное форматирование равноценно важны.

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

// плохо
import _ from 'lodash'
import userTemplate from './templates'
const transformUsersList = (users) => {
  return _.chain(users).filter(user => !!user.id).map(user => ({...userTemplate, id: user.id, name: user.name})).value()
}
export default transformUsersList

// хорошо
import _ from 'lodash'
import userTemplate from './templates'

const transformUsersList = (users=[]) => {
  return _
    .chain(users)
    .filter(user => !!user.id)
    .map(user => ({
      ...userTemplate, 
      id: user.id, 
      name: user.name
     }))
    .value()
}

export default transformUsersList

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

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

// плохо
const showUsersList = () => {
  /* ... */
}

const fetchUsersList = () => {
  /* ... */
  // вызывает showUsersList
}

const handleButtonClick = () => {
  /* ... */
  // вызывает fetchUsersList
}


// хорошо
const handleButtonClick = () => {
  /* ... */
  // вызывает fetchUsersList
}

const fetchUsersList = () => {
  /* ... */
  // вызывает showUsersList
}

const showUsersList = () => {
  /* ... */
}

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

Горизонтальное выравнивание по большей части бесполезно. Если добавится переменная с большим количеством символов в названии, придётся изменять выравнивание:

// бессмысленно
const users     = []
const fakeUsers = []

// добавилась другая переменная, форматирование надо менять
const users     = []
const fakeUsers = []
const confirmedUsers = []

Лучше подобрать не выравнивание, а оптимальное количество переменных. Если требуется, то вынести какую‑то часть кода в отдельную функцию.

Наблюдение за форматированием надо отдавать роботам. Заведите в проекте линтеры, которые будут следить за переносами, индентацией и прочим.

Глава 6. Объекты и структуры данных

Коротко:

  • объекты и структуры данных — не одно и то же;
  • слабая связанность — хорошо.

Разница между объектами и структурами данных в том, что объекты прячут данные за абстракциями и предоставляют функции для работы с данными. Структуры данных наоборот данные не прячут.

Поэтому в процедурный код (использующий структуры данных) легче добавлять новые функции без изменения структуры. В объектно‑ориентированный — легче добавлять классы без изменения существующих функций.

По закону Деметры объект‑клиент должен избегать вызовов методов объектов, внутренних членов, возвращенных методом объекта‑сервиса. Грубо говоря цепочки методов (паровозики) нарушают закон:

// плохо 
userInstance.getName().getInitials()

// хорошо
userInstance.getInitials()

Глава 7. Обработка ошибок

Коротко:

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

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

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

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

При обработке сторонних АПИ старайтесь минимизировать зависимость от них. Обработка ошибок должна быть максимально отделённой от бизнес‑логики.

Глава 8. Разграничения

Коротко:

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

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

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

В следующих главах обсудим:

  • юнит‑тесты и три закона ТДД;
  • работу с классами;
  • масштабирование систем.

Ссылки по теме:

Ссылки №15

Мало, но полезно:

Раньше ↓