Минутка просвещения

Читать в телеге. Когда-то там были посты не только от меня.

Есть ли будущее у мутационного тестирования?

Интересная заметка про мутационное тестирование. Тезисно:

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

Большие запросы без пагинации и scroll'а в ElasticSearch

Параметр search_after позволяет выполнить последовательность запросов без использования пагинации (у которой есть ограничения на размер page*size, по умолчанию 10 000) и без использования scroll (который практически создает слепок индекса и жрет память). Идея довольно простая: использовать сортировку по какому-то полю, взять первые N результатов, а потом сделать запрос, в которого значение поля сортировки больше, чем у N-ного результата.

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

СсылкаКомментировать

CQRS

CQRS (Command and Query Responsibility Segregation) — это очень простой принцип построения систем, который является продолжением CQS (сommand-query separation). Напомню, что CQS говорит о том, что всякий метод является либо командой, которая меняет данные, но ничего не возвращает, либо запросом, который возвращает данные, но не меняет их. А CQRS дополняет его, говоря о том, для обработки команд и обработки запросов используются разные сущности (например, сервисы).

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

СсылкаКомментировать

Иерархия мотивации

Один из самых классных докладов на конференции TeamLead 2020 был про мотивацию.

В нем обозначена проблема, что руководство пытается лечить симптомы (поведение), а не корневую причину. Рассмотрены 6 мотивационных статусов:

  1. Автоматическая мотивация — делаешь на автомате, мысли о другом.
  2. Внешняя — ждешь награду, не обязательно материальную.
  3. Навязанная — избегаешь “наказания” (увольнения, стыда, позора, провала и т.п.).
  4. Согласованная — видишь связь со своей целью. “Я хочу заниматься этой задачей”.
  5. Интегрированная — получаешь удовольствие, чувствуешь связь с призванием, “работа мечты”. Ошибки воспринимаются как полезный опыт.
  6. Поток — наслаждение, “хочу делать только это, на остальное пофиг”. Важен процесс, нет гарантии результата.

В 4-6 цель внутри, задачи выполняются ответственно, мотивация оптимальная. В 1-3 цель вне задач и они выполняются для галочки. Долго в низких уровнях мало кто может находится. Кроме этого, существуют 3 базовых психологических потребности: автономия, принадлежность, компетентность. Если какая-то не закрыта, то с мотивацией будут проблемы.

Чтобы повысить мотивацию, есть 2 основных способа:

  1. Внезапно, устранить проблемы, если у демотивации есть объективная причина.
  2. Включить саморегуляцию: осознанность (чтобы сотрудник думал о себе, рефлексировал), цели (для чего он к ней идет), ценности (которые определяют направление его движения и помогают ставить цели, принимать решения).

Задайте себе вопрос — если бы пропали деньги из мира, стали бы вы заниматься тем, чем занимаетесь сейчас?

СсылкаКомментировать

Макакачность

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

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

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

Начал замечать за собой такое поведение: например, когда реализовывал поиск по префиксному дереву с учетом разовой ошибки. Все тесты были уже готовы, просто хотел решить сам, чтобы понять, какие трудности могут возникнуть у моих студентов. Алгоритмы там очень простые, накидал почти не думая решение — тесты не прошли. Поправил немного в месте, где скорее всего ошибка — не прошли другие. Как макака, повторял эти действия. Через пару часов очнулся: вместо кода — лапша с костылями al dente, тесты не проходят. Все стер, включил мозги и написал минут за 10 нормально.

Вот смотрю на себя и на то, что вокруг, и думаю: индустрия хотела 10x-инженеров, а получила 10x-макак.

СсылкаКомментировать

Большие стрелки и маленькие квадратики

Когда готовил доклад про скучное программирование, то не нашел эту статью, поэтому заменил затравку на цитату Хоара (“Inside every large program is a small program struggling to get out.”).

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

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

СсылкаКомментировать

Автоматическая репликация на все узлы Elasticsearch

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

СсылкаКомментировать

Самоорганизующаяся команда

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

TLDR:

  1. Директивное управление работает на энергии руководителя, кончится она — кончится команда.
  2. У команды должна быть четкая и понятная цель, общее видение и ответственность.
  3. Члены команда должна знать контекст друг друга, работа всех должна быть прозрачна.
  4. Если переборщить с самостоятельностью, то можно начать выходить за зоны своей ответственности или указывать бизнесу на его недочеты (и это может быть как плюс, так и минус).
  5. Чем больше нужно согласований для действий, тем меньше инициативы в команде.

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

СсылкаКомментировать

Коммит в соавторстве

Иногда на GitHub можно увидеть коммит от нескольких авторов (например). Сделать совместный коммит довольно просто: нужно просто добавить строку в коммит с текстом

Co-authored-by: name <name@example.com>

Разумеется, туда можно вписать что угодно. Отображение соавторства поддерживается GitHub и GitLab, но это не стандартная фича git. При этом есть и другие “прицепы”.

СсылкаКомментировать

Индексирование нового поля в ElasticSearch

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

POST your-index/_update_by_query?conflicts=proceed&wait_for_completion=false
{
  "query": {
    "bool": {
      "must_not": [{
        "exists": {
          "field": "new.field"
        }
      }],
      "must": [{
        "exists": {
          "field": "exisiting.field.as.flag"
        }
      }]
    }
  }
}

СсылкаКомментировать