Статьи

Невнимание Слепота — Отсутствие очевидного

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

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

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

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

В чем дело?

Если вы не слышали об этом раньше, согласно Википедии, слепота невнимательности (иначе известная как слепота восприятия) это:

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

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

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

Конечный результат? Для них фактически этого не было.

Невидимое испытание гориллы

Один из самых известных примеров на эту тему — это тест на невидимую гориллу , который провели Дэниел Саймонс и Кристофер Чабрис . Если вы не знакомы с тестом, посмотрите это видео на YouTube. Испытуемых просили посмотреть видео, в котором две команды передают шары друг другу, и подсчитывают количество проходов одной командой. Субъектам не было сказано, что во время видео человек в костюме гориллы проходит через толпу, бьет ее в грудь и уходит. Вы думаете, это будет довольно очевидно, верно? Отчеты отличаются. Около 50% людей не указали, что видели гориллу.

Странно, правда? Человек в костюме гориллы явно входит и смотрит вокруг. Как кто-то мог пропустить что-то настолько очевидное?

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

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

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

Как это относится к программированию?

Недавно я прочитал интересную (и краткую) статью под названием « Что делает код трудным для понимания»? Майкл Хансен, Роберт Л. Голдстоун и Эндрю Ламсдейн. Резюме выглядит следующим образом:

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

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

Внимательно обратите внимание на последнюю часть реферата:

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

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

Специфический языковой опыт / ожидания программиста

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

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

  • Как насчет этого?
  • Вы пробовали X?
  • Вы думали сделать Y?

По иронии судьбы возросшие знания стали помехой, а не помощью. Вот конкретный пример; Неужели мы начинаем ожидать, что код должен быть написан определенным образом, например, с отступом в стиле K & R (Kernighan и Ritchie) или Allman ?

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

Перегрузка оператора

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

Возьмите следующий пример (из раздела операторов присваивания руководства по PHP):

$a = 3; 
$a += 5; 
$b = "Hello "; 
$b .= "There!";

Мы легко видим, что для $a$b Но что, если бы мы перепутали операторы следующим образом:

 $a = 3; 
$a .= 5; 
$b = "Hello "; 
$b += "There!";

Какими будут результаты сейчас?

Синтаксический шум

По словам Мартина Фаулера , синтаксический шум это:

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

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

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

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

Давайте посмотрим на пример «шумного» PHP. Это было изменено из исходного примера Java, используемого Полом В. Гомером:

 public function calcIndex() 
{ 
    $weightedSum = 0; $bondCount = 0; $status = false;
    for ($i = 0; $i < count($this->bonds); $i++) {
        $status = $this->yieldCalc($this->bondInfo, self::YIELD, true,
            $this->bondFacts);
        if ($status != true) {
            throw new YieldCalculationException(
                $this->getCalcError()); 
        } 
        $weightedSum += $this->calcWeight($this->bondFacts,
            Weight::NORMAL); 
        $bondCount++;
    } 
    return $weightedSum / $bondCount; 
}

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

 $weightedSum = 0.0; $bondCount = 0; $status = false;

Здесь мы инициализируем три переменные: $weightedSum$bondCount$status Возможно, будет понятнее, если мы инициализируем их по отдельности в отдельных строках.

 for ($i = 0; i < count($this->bonds); $i++) {

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

Вместо этого может быть более простой подход: foreach

 foreach ($this->bonds as $item) {

Намерение гораздо понятнее, и вводить ошибки труднее.

 $weightedSum += $this->calcWeight($this->bondFacts, Weight::NORMAL);
$bondCount++;

Здесь мы имеем компактный подход к присваиванию переменных ( +=++ Да, это занимает меньше места, но обязательно ли это понятно или показательно? Это зависит от вас, но, может быть, следующее будет яснее:

 $weightedSum = ($weightedSum + $this->calcWeight($this->bondFacts,
    Weight::NORMAL)); 
$bondCount = ($bondCount + 1);

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

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

Пробелы — вертикальные и горизонтальные

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

 public function __construct( 
    DbAdapter $zendDb, $tableName = null, 
    $identityColumn = null, $credentialColumn = null, 
    $credentialTreatment = null) 
{ 
    $this->zendDb = $zendDb; 

    if (null !== $tableName) { 
        $this->setTableName($tableName); 
    } 

    if (null !== $identityColumn) { 
        $this->setIdentityColumn($identityColumn); 
    } 

    if (null !== $credentialColumn) { 
        $this->setCredentialColumn($credentialColumn); 
    } 

    if (null !== $credentialTreatment) { 
        $this->setCredentialTreatment($credentialTreatment); 
    } 
}

При правильном использовании вертикальных пробелов мы можем видеть, какой код логически связан. Мы можем легко идентифицировать различные условия на основе $tableName$identityColumn$credentialColumn$credentialTreatment Кроме того, правильное использование кода горизонтального пробела (отступа) дает коду очень логичную и понятную структуру.

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

Представьте, что все это объединено без группировки, отступов или общего порядка. Будет ли это так легко понять?

Вывод

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

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

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