Многие программисты, но вы можете научиться быть другим

Что такое карго-культ

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

Естественно, коренные племена, жившие на этих островах, были в восторге. Кто не любит магию и бесплатную еду?

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

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

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

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

Эта концепция хорошо выражена в этой потрясающей цитате Фейнмана:

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

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

Программирование культа груза

Итак, мы закончили урок истории. Единственная проблема в том, что история имеет свойство повторяться. Я чертовски надеюсь, что мы не находимся на пороге Третьей мировой войны, но Cargo Cults распространились повсюду, даже в сфере разработки программного обеспечения.

Что такое культовое программирование Cargo?

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

Страшный копипаст

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

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

Проблемы возникают, когда вы копируете и вставляете какой-то ответ Stack Overflow или другие части своей кодовой базы, не имея ни малейшего представления о том, что на самом деле делает этот код. Это сработало для этого человека, так почему бы это не сработать для вас?

Что ж, это мышление Cargo-Cult. Вы имеете дело с декорациями (код кажется похожим), не понимая первопричины (как это используется в этом конкретном контексте).

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

Злоупотребление наследованием в ООП

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

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

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

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

Слепое следование «лучшей практике»

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

Хорошим примером является бессистемное использование аннотации Transactional в приложениях, использующих Spring.

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

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

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

@Transactional
public void changeName(long id, String name) {
  User user = userRepository.getById(id);
  user.setName(name);
  if (StringUtils.isNotEmpty(name)) {
    userRepository.save(user);
  }
}
// All rights reserved to this fantastic article

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

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

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

Нет, это просто наша любимая аннотация Transactional делает свою работу.

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

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

Как избежать программирования Cargo Cult

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

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

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