Slide 1

Slide 1 text

Никита Соболев github.com/sobolevn

Slide 2

Slide 2 text

sobolevn.me/talks/teamleadconf-2020 2

Slide 3

Slide 3 text

>_ X Микротаски на практике

Slide 4

Slide 4 text

Для кого?

Slide 5

Slide 5 text

Наверное, есть некоторая проблема

Slide 6

Slide 6 text

Наверное, есть некоторая проблема > Теперь я - тимлид, но почему мне так плохо?

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

Мой доклад для тех, кто вынужден управлять. Но хочет остаться инженером!

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

О чем поговорим со страдающими инженерами?

Slide 13

Slide 13 text

О чем поговорим со страдающими инженерами? > Про основу автоматизации управления

Slide 14

Slide 14 text

О чем поговорим со страдающими инженерами? > Про основу автоматизации управления > Слухи, скандалы, сплетни и домыслы

Slide 15

Slide 15 text

О чем поговорим со страдающими инженерами? > Про основу автоматизации управления > Слухи, скандалы, сплетни и домыслы > Реальные проблемы на пути

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

>_ X Чем занимаются инженеры?

Slide 18

Slide 18 text

Инженеры – автоматизируют задачи, которые мешают работе

Slide 19

Slide 19 text

Но как нам автоматизировать управление?

Slide 20

Slide 20 text

Чтобы автоматизировать, нужно измерить

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

Задача на неделю

Slide 24

Slide 24 text

Задача на неделю Задача на час

Slide 25

Slide 25 text

Задача на неделю

Slide 26

Slide 26 text

Задача на неделю > Может занять две. Или три. Или год

Slide 27

Slide 27 text

Задача на неделю > Может занять две. Или три. Или год > Будет конфликтовать с другими

Slide 28

Slide 28 text

Задача на неделю > Может занять две. Или три. Или год > Будет конфликтовать с другими > Может сожрать лишние ресурсы

Slide 29

Slide 29 text

Задача на неделю > Может занять две. Или три. Или год > Будет конфликтовать с другими > Может сожрать лишние ресурсы > Непрозрачна: нужен наш контроль

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

Задача на час

Slide 32

Slide 32 text

Задача на час > Маловероятно займет больше

Slide 33

Slide 33 text

Задача на час > Маловероятно займет больше > Не будет конфликтовать с другими

Slide 34

Slide 34 text

Задача на час > Маловероятно займет больше > Не будет конфликтовать с другими > Очень скромная по ресурсам

Slide 35

Slide 35 text

Задача на час > Маловероятно займет больше > Не будет конфликтовать с другими > Очень скромная по ресурсам > Прозрачна: наш контроль не нужен

Slide 36

Slide 36 text

1 час

Slide 37

Slide 37 text

Прогрессивная шкала оценки

Slide 38

Slide 38 text

15 30 60 120 Задачи в минутах

Slide 39

Slide 39 text

Деревья задач

Slide 40

Slide 40 text

Task Chains

Slide 41

Slide 41 text

Task Chains > Последовательность

Slide 42

Slide 42 text

Task Chains > Последовательность > Блокировки

Slide 43

Slide 43 text

Task Chains > Последовательность > Блокировки > Приоритеты и сроки

Slide 44

Slide 44 text

Task Chains > Последовательность > Блокировки > Приоритеты и сроки > До-дробление

Slide 45

Slide 45 text

Task Chains > Последовательность > Блокировки > Приоритеты и сроки > До-дробление > Отмены

Slide 46

Slide 46 text

Главный плюс = прозрачность

Slide 47

Slide 47 text

1 час

Slide 48

Slide 48 text

Что можно делать с прозрачностью?

Slide 49

Slide 49 text

Что можно делать с прозрачностью? > Мотивировать людей

Slide 50

Slide 50 text

Что можно делать с прозрачностью? > Мотивировать людей > Собирать статистику и предсказывать

Slide 51

Slide 51 text

Что можно делать с прозрачностью? > Мотивировать людей > Собирать статистику и предсказывать > Общаться с заказчиками

Slide 52

Slide 52 text

Что можно делать с прозрачностью? > Мотивировать людей > Собирать статистику и предсказывать > Общаться с заказчиками > Настраивать нотификации и быть спокойным

Slide 53

Slide 53 text

>_ X Слухи и сплетни

Slide 54

Slide 54 text

Слух: работа с маленькими задачами требует супер крутых менеджеров

Slide 55

Slide 55 text

Работать с маленькими задачами – очень просто

Slide 56

Slide 56 text

Берешь и создаешь!

Slide 57

Slide 57 text

Исполнитель может оценить задачу лучше всех

Slide 58

Slide 58 text

Но может потребоваться тренировка

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

Слух: работа с маленькими задачами на самом деле микро- менеджмент

Slide 61

Slide 61 text

Нет, обычно в работу человека никто не вмешивается. Но каждый ССЗБ

Slide 62

Slide 62 text

Слух: я могу просидеть над часовой задачей много дней из-за неверной оценки

Slide 63

Slide 63 text

Definition of Ready

Slide 64

Slide 64 text

Definition of Done

Slide 65

Slide 65 text

Задача может и должна заканчиваться не только кодом!

Slide 66

Slide 66 text

Задача может и должна порождать новые задачи!

Slide 67

Slide 67 text

Слух: значит я могу ничего не делать!

Slide 68

Slide 68 text

Прозрачность + человек = страшная сила

Slide 69

Slide 69 text

Что на самом деле сложно?

Slide 70

Slide 70 text

Что на самом деле сложно? > Управлять большим количеством задач

Slide 71

Slide 71 text

Что на самом деле сложно? > Управлять большим количеством задач > Гонять CI, делать ревью кода

Slide 72

Slide 72 text

Что на самом деле сложно? > Управлять большим количеством задач > Гонять CI, делать ревью кода > Архитектура

Slide 73

Slide 73 text

Что на самом деле сложно? > Управлять большим количеством задач > Гонять CI, делать ревью кода > Архитектура > Сохранять стабильность сборки

Slide 74

Slide 74 text

Что на самом деле сложно? > Управлять большим количеством задач > Гонять CI, делать ревью кода > Архитектура > Сохранять стабильность сборки > Деплоить и откатывать, мониторить

Slide 75

Slide 75 text

>_ X Управляем задачами

Slide 76

Slide 76 text

44

Slide 77

Slide 77 text

4,5 своих продукта, которые худо-бедно умеют управлять программистами. Но все еще плохо!

Slide 78

Slide 78 text

Основные требования

Slide 79

Slide 79 text

Основные требования > Удобно создавать Task Chains

Slide 80

Slide 80 text

Основные требования > Удобно создавать Task Chains > Выставить свой статус

Slide 81

Slide 81 text

Основные требования > Удобно создавать Task Chains > Выставить свой статус > Отказаться от задачи

Slide 82

Slide 82 text

Основные требования > Удобно создавать Task Chains > Выставить свой статус > Отказаться от задачи > Настроить напоминалки

Slide 83

Slide 83 text

Основные требования > Удобно создавать Task Chains > Выставить свой статус > Отказаться от задачи > Настроить напоминалки > Настроить таймауты

Slide 84

Slide 84 text

No content

Slide 85

Slide 85 text

TODO != задача

Slide 86

Slide 86 text

No content

Slide 87

Slide 87 text

И целая инфраструктура вокруг! github.com/wemake-services/kira

Slide 88

Slide 88 text

Необходимый список ботов

Slide 89

Slide 89 text

Необходимый список ботов > Бот для релизов

Slide 90

Slide 90 text

Необходимый список ботов > Бот для релизов > Бот для rebase

Slide 91

Slide 91 text

Необходимый список ботов > Бот для релизов > Бот для rebase > Бот для работы с задачами

Slide 92

Slide 92 text

Необходимый список ботов > Бот для релизов > Бот для rebase > Бот для работы с задачами > Бот для управления программистами

Slide 93

Slide 93 text

Необходимый список ботов > Бот для релизов > Бот для rebase > Бот для работы с задачами > Бот для управления программистами > Бот для ревью кода

Slide 94

Slide 94 text

>_ X Гоняем CI все время

Slide 95

Slide 95 text

No content

Slide 96

Slide 96 text

No content

Slide 97

Slide 97 text

No content

Slide 98

Slide 98 text

CI становится узким местом

Slide 99

Slide 99 text

CI становится узким местом Время 0 10 20 30 40 Июль

Slide 100

Slide 100 text

CI становится узким местом Время 0 10 20 30 40 Июль Время: 15 минут

Slide 101

Slide 101 text

CI становится узким местом Время 0 10 20 30 40 Июль Время: 15 минут Время: 15 минут

Slide 102

Slide 102 text

CI становится узким местом Время 0 10 20 30 40 Июль Время: 8 минут Время: 15 минут Время: 15 минут

Slide 103

Slide 103 text

test: script: - docker-compose run --rm web test

Slide 104

Slide 104 text

test: script: # Building test image and saving the cache: - docker pull "${IMAGE_NAME}:dev" - docker tag "${IMAGE_NAME}:dev" "${PROJECT_NAME}:dev" # The logic itself: - docker-compose build - docker-compose run --rm web test # Pushing back the result for future runs: - docker tag "${PROJECT_NAME}:dev" "${IMAGE_NAME}:dev" - docker push "${IMAGE_NAME}:dev"

Slide 105

Slide 105 text

test: script: # Building test image and saving the cache: - docker pull "${IMAGE_NAME}:dev" - docker tag "${IMAGE_NAME}:dev" "${PROJECT_NAME}:dev" # The logic itself: - docker-compose build - docker-compose run --rm web test # Pushing back the result for future runs: - docker tag "${PROJECT_NAME}:dev" "${IMAGE_NAME}:dev" - docker push "${IMAGE_NAME}:dev"

Slide 106

Slide 106 text

test: script: # Building test image and saving the cache: - docker pull "${IMAGE_NAME}:dev" - docker tag "${IMAGE_NAME}:dev" "${PROJECT_NAME}:dev" # The logic itself: - docker-compose build - docker-compose run --rm web test # Pushing back the result for future runs: - docker tag "${PROJECT_NAME}:dev" "${IMAGE_NAME}:dev" - docker push "${IMAGE_NAME}:dev"

Slide 107

Slide 107 text

test: script: # Building test image and saving the cache: - docker pull "${IMAGE_NAME}:dev" - docker tag "${IMAGE_NAME}:dev" "${PROJECT_NAME}:dev" # The logic itself: - docker-compose build - docker-compose run --rm web test # Pushing back the result for future runs: - docker tag "${PROJECT_NAME}:dev" "${IMAGE_NAME}:dev" - docker push "${IMAGE_NAME}:dev"

Slide 108

Slide 108 text

release-image: image: wemakeservices/kira-release:latest script: - docker push "${IMAGE_NAME}:latest"

Slide 109

Slide 109 text

release-image: image: wemakeservices/kira-release:latest before_script: - docker pull "${IMAGE_NAME}:latest" - docker pull "${IMAGE_NAME}:dev" - docker build -t "${IMAGE_NAME}:latest" --cache-from="${IMAGE_NAME}:latest" --cache-from="${IMAGE_NAME}:dev" --build-arg DJANGO_ENV=production -f docker/django/Dockerfile . script: - docker push "${IMAGE_NAME}:latest"

Slide 110

Slide 110 text

release-image: image: wemakeservices/kira-release:latest before_script: - docker pull "${IMAGE_NAME}:latest" - docker pull "${IMAGE_NAME}:dev" - docker build -t "${IMAGE_NAME}:latest" --cache-from="${IMAGE_NAME}:latest" --cache-from="${IMAGE_NAME}:dev" --build-arg DJANGO_ENV=production -f docker/django/Dockerfile . script: - docker push "${IMAGE_NAME}:latest"

Slide 111

Slide 111 text

release-image: image: wemakeservices/kira-release:latest before_script: - docker pull "${IMAGE_NAME}:latest" - docker pull "${IMAGE_NAME}:dev" - docker build -t "${IMAGE_NAME}:latest" --cache-from="${IMAGE_NAME}:latest" --cache-from="${IMAGE_NAME}:dev" --build-arg DJANGO_ENV=production -f docker/django/Dockerfile . script: - docker push "${IMAGE_NAME}:latest"

Slide 112

Slide 112 text

release-image: image: wemakeservices/kira-release:latest before_script: - docker pull "${IMAGE_NAME}:latest" - docker pull "${IMAGE_NAME}:dev" - docker build -t "${IMAGE_NAME}:latest" --cache-from="${IMAGE_NAME}:latest" --cache-from="${IMAGE_NAME}:dev" --build-arg DJANGO_ENV=production -f docker/django/Dockerfile . script: - docker push "${IMAGE_NAME}:latest"

Slide 113

Slide 113 text

No content

Slide 114

Slide 114 text

No content

Slide 115

Slide 115 text

No content

Slide 116

Slide 116 text

Уже лучше

Slide 117

Slide 117 text

Уже лучше Время 0 10 20 30 40 Было Стало

Slide 118

Slide 118 text

Уже лучше Время 0 10 20 30 40 Было Стало Время: 15 минут Время: 15 минут

Slide 119

Slide 119 text

Уже лучше Время 0 10 20 30 40 Было Стало Время: 4 минут Время: 15 минут Время: 15 минут Время: 15 минут

Slide 120

Slide 120 text

Уже лучше Время 0 10 20 30 40 Было Стало Время: 5 минут Время: 8 минут Время: 4 минут Время: 15 минут Время: 15 минут Время: 15 минут

Slide 121

Slide 121 text

А что с Code Review?

Slide 122

Slide 122 text

Он служит для контроля корректности автоматики

Slide 123

Slide 123 text

Код-ревью за 15 минут или меньше 69 sobolevn.me/talks/dumpconf-2019

Slide 124

Slide 124 text

Расходы против выгоды

Slide 125

Slide 125 text

>_ X Архитектура

Slide 126

Slide 126 text

Требования:

Slide 127

Slide 127 text

Требования: > Атомарность

Slide 128

Slide 128 text

Требования: > Атомарность > Гибкость и простота

Slide 129

Slide 129 text

Требования: > Атомарность > Гибкость и простота > Одна причина для редактирования

Slide 130

Slide 130 text

github.com/dry-python

Slide 131

Slide 131 text

Enforcing Single Responsibility Principle in Python sobolevn.me/2019/03/enforcing-srp

Slide 132

Slide 132 text

>_ X Стабильность сборки

Slide 133

Slide 133 text

Trunk Based Development trunkbaseddevelopment.com

Slide 134

Slide 134 text

No content

Slide 135

Slide 135 text

No content

Slide 136

Slide 136 text

+ squash-rebase only

Slide 137

Slide 137 text

Compatible migrations github.com/3YOURMIND/django-migration-linter

Slide 138

Slide 138 text

No content

Slide 139

Slide 139 text

Что проверяем?

Slide 140

Slide 140 text

Что проверяем? > Удаление полей

Slide 141

Slide 141 text

Что проверяем? > Удаление полей > Переименование полей

Slide 142

Slide 142 text

Что проверяем? > Удаление полей > Переименование полей > Создание новых non-null полей

Slide 143

Slide 143 text

Compatible tasks

Slide 144

Slide 144 text

@celery.task() def send_email(email: str) -> None: ...

Slide 145

Slide 145 text

@celery.task() def send_email(email: str, message: str) -> None: ...

Slide 146

Slide 146 text

@celery.task() def send_email(email: str, message: str) -> None: ...

Slide 147

Slide 147 text

Compatible platform

Slide 148

Slide 148 text

Хорошие абстракции

Slide 149

Slide 149 text

Feature toggles

Slide 150

Slide 150 text

Legacy-first tools

Slide 151

Slide 151 text

github.com/life4/flakehell 91

Slide 152

Slide 152 text

>_ X Деплой, откаты, мониторинг

Slide 153

Slide 153 text

No content

Slide 154

Slide 154 text

No content

Slide 155

Slide 155 text

А у вас молоко убежало!

Slide 156

Slide 156 text

No content

Slide 157

Slide 157 text

>_ X А теперь примеры!

Slide 158

Slide 158 text

No content

Slide 159

Slide 159 text

Примеры из реальной жизни github.com/wemake-services/wemake-python-styleguide

Slide 160

Slide 160 text

Простой баг или фича > Сломалось: github.com/wemake- services/wemake-python-styleguide/ issues/1127 > Новинка: github.com/wemake- services/wemake-python-styleguide/ issues/1111

Slide 161

Slide 161 text

Новая фича на несколько шагов

Slide 162

Slide 162 text

Добавляем поддержку python3.8 в большой OpenSource продукт github.com/wemake-services/wemake-python-styleguide/milestone/10

Slide 163

Slide 163 text

class NodeVisitor(object): def visit_Num(self, node: ast.Num) -> None: ... def visit_Bytes(self, node: ast.Bytes) -> None: ... def visit_Str(self, node: ast.Str) -> None: ... def visit_NameConstant(self, node) -> None: ...

Slide 164

Slide 164 text

class NodeVisitor(object): def visit_Constant(self, node: ast.Constant) -> None: ...

Slide 165

Slide 165 text

Подзадачи 105

Slide 166

Slide 166 text

Подзадачи 2. Новый умный слой абстракции: github.com/wemake- services/wemake-python-styleguide/issues/1135 105

Slide 167

Slide 167 text

Подзадачи 2. Новый умный слой абстракции: github.com/wemake- services/wemake-python-styleguide/issues/1135 1. Новая методика подсчета покрытия: github.com/ wemake-services/coverage-conditional-plugin 105

Slide 168

Slide 168 text

Подзадачи 2. Новый умный слой абстракции: github.com/wemake- services/wemake-python-styleguide/issues/1135 1. Новая методика подсчета покрытия: github.com/ wemake-services/coverage-conditional-plugin 3. Постепенный рефакторинг: https://github.com/ wemake-services/wemake-python-styleguide/issues/ 1141 105

Slide 169

Slide 169 text

Новое большое бизнес требование к старой большой логике

Slide 170

Slide 170 text

if user := get_user(): greet(user)

Slide 171

Slide 171 text

Добавляем понемногу github.com/wemake-services/wemake-python-styleguide/issues/1137

Slide 172

Slide 172 text

Проводим исследования > Понять, какие зависимости можно удалить: github.com/wemake-services/ wemake-python-styleguide/issues/1139 > Добавить полезное из другой библиотеки: github.com/wemake- services/wemake-python-styleguide/ issues/422 > Проверить, что зависимости работают с python3.8: github.com/wemake-services/ wemake-python-styleguide/issues/1138

Slide 173

Slide 173 text

Architecture Decision Record

Slide 174

Slide 174 text

No content

Slide 175

Slide 175 text

No content

Slide 176

Slide 176 text

>_ X Выводы

Slide 177

Slide 177 text

Если вы не хотите управлять (но надо), перекладывайте все на автоматику

Slide 178

Slide 178 text

Чтобы автоматизировать управление, нужна единица работы

Slide 179

Slide 179 text

Маленькие задачи – ваши лучшие друзья

Slide 180

Slide 180 text

Полезные ссылки > Microtasks at GitHub: dev.to/mscccc/ how-we-use-ship-small-to-rapidly- build-new-features-at-github-5cl9 > Microtasks at Google: google.github.io/eng-practices/ review/developer/small-cls.html > Program development by stepwise refinement: dl.acm.org/doi/ 10.1145/362575.362577

Slide 181

Slide 181 text

t.me/ opensource_findings 118

Slide 182

Slide 182 text

sobolevn.me Вопросы? github.com/sobolevn