Русский
Русский
English
Статистика
Реклама

Scrum

Пишем Slack бота для Scrum покера на Go. Часть 1

04.03.2021 00:14:15 | Автор: admin

Здравствуйте! Сегодня мы напишем Slack бота для Scrum покера на языке Go. Писать будем по возможности без фреймворков и внешних библиотек, так как наша цель разобраться с языком программирования Go и проверить, насколько этот язык удобен для разработки подобных проектов.

Дисклеймер

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

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

Хватит прелюдий, вперед в бой!

Итоговый результат

Анимация работы будущего бота

Для тех, кому читать код интересней, чем статью прошу сюда.

Структура приложения

Разобьем нашу программу на следующие слои. У нас предполагается слой взаимодействия (web), слой для рисования интерфейса средствами Slack UI Block Kit (ui), слой для сохранения / получения результатов (storage), а также место для хранения настроек (config). Давайте создадим следующие папки в проекте:

config/storage/ui/web/-- clients/-- server/main.go

Сервер

Для сервера будем использовать стандартный сервер из пакета http. Создадим структуру Server следующего вида в web -> server:

server.go
package serverimport ("context""log""net/http""os""os/signal""sync/atomic""time")type Server struct {  // Здесь мы будем определять все необходимые нам зависимости и передавать их на старте приложения в main.gohealthy        int32logger         *log.Logger}func NewServer(logger *log.Logger) *Server {return &Server{logger: logger,}}

Эта структура будет выступать хранилищем зависимостей для наших хэндлеров. Есть несколько подходов для организации работы с хэндлерами и их зависимостями. Например, можно объявлять и запускать все в main.go, там же где мы создаем экземпляры наших структур и интерфейсов. Но это плохой путь. Еще есть вариант использовать глобальные переменные и просто их импортировать. Но в таком случае становится сложно покрывать проект тестами. Дальше мы увидим плюсы выбранного мной подхода. Итак, нам нужно запустить наш сервер. Напишем метод:

server.go
func (s *Server) setupRouter() http.Handler {  // TODOrouter := http.NewServeMux()  return router}func (s *Server) Serve(address string) {server := &http.Server{Addr:         address,    Handler:      s.setupRouter(),ErrorLog:     s.logger, // Наш логгерReadTimeout:  5 * time.Second,WriteTimeout: 10 * time.Second,IdleTimeout:  15 * time.Second,}  // Создаем каналы для корректного завершения процессаdone := make(chan bool)quit := make(chan os.Signal, 1)  // Настраиваем сигнал для корректного завершения процессаsignal.Notify(quit, os.Interrupt)go func() {<-quits.logger.Println("Server is shutting down...")    // Эта переменная пригодится для healthcheck'а напримерatomic.StoreInt32(&s.healthy, 0)    // Даем клиентам 30 секунд для завершения всех операций, прежде чем сервер будет остановленctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)defer cancel()    // Информируем сервер о том, что не нужно держать существующие коннектыserver.SetKeepAlivesEnabled(false)    // Выключаем серверif err := server.Shutdown(ctx); err != nil {s.logger.Fatalf("Could not gracefully shutdown the server: %v\n", err)}close(done)}()s.logger.Println("Server is ready to handle requests at", address)  // Переменная для проверки того, что сервер запустился и все хорошоatomic.StoreInt32(&s.healthy, 1)  // Запускаем серверif err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {s.logger.Fatalf("Could not listen on %s: %v\n", address, err)}  // Когда сервер остановлен и все хорошо, снова получаем управление и логируем результат<-dones.logger.Println("Server stopped")}

Теперь давайте создадим первый хэндлер. Создадим папку в web -> server -> handlers:

healthcheck.go
package handlersimport ("net/http")func Healthcheck() http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {w.Write("OK")})}

Добавим наш хэндлер в роутер:

server.go
// Наш код вышеfunc (s *Server) setupRouter() http.Handler {router := http.NewServeMux()router.Handle("/healthcheck",handlers.Healthcheck(),)  return router}// Наш код ниже

Идем в main.go и пробуем запустить наш сервер:

package mainimport ("log"  "os"  "go-scrum-poker-bot/web/server")func main() {  // Создаем логгер со стандартными флагами и префиксом "INFO:".   // Писать он будет только в stdoutlogger := log.New(os.Stdout, "INFO: ", log.LstdFlags)app := server.NewServer(logger)app.Serve(":8000")}

Пробуем запустить проект:

go run main.go

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

NGROK

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

ngrok http 8000

Если все хорошо, то вы увидите что-то вроде этого:

ngrok by @inconshreveable                                                                                                            (Ctrl+C to quit)                                                                                                                                                     Session Status                online                                                                                                                 Account                       Sayakhov Ilya (Plan: Free)                                                                                             Version                       2.3.35                                                                                                                 Region                        United States (us)                                                                                                     Web Interface                 http://127.0.0.1:4040                                                                                                  Forwarding                    http://ffd3cfcc460c.ngrok.io -> http://localhost:8000                                                                  Forwarding                    https://ffd3cfcc460c.ngrok.io -> http://localhost:8000                                                                                                                                                                                                                      Connections                   ttl     opn     rt1     rt5     p50     p90                                                                                                          0       0       0.00    0.00    0.00    0.00     

Нас интересует строчка https://ffd3cfcc460c.ngrok.io. Она нам понадобится дальше.

Slash commands

Создадим наше приложение в Slack. Для этого нужно перейти сюда -> Create New App. Далее указываем имя GoScrumPokerBot и добавляем его в свой Workspace. Далее, нам нужно дать нашему боту права. Для этого идем в OAuth & Permissions -> Scopes и добавляем следующие права: chat:write, commands. Первый набор прав нужен, чтобы бот мог писать в каналы, а второй для slash команд. И наконец нажимаем на Reinstall to Workspace. Готово! Теперь идем в раздел Slash commands и добавляем нашу команду /poker .

В Request URL нужно вписать адрес из пункта выше + путь. Пусть будет так: https://ffd3cfcc460c.ngrok.io/play-poker.

Slash command handler

Теперь создадим хэндлер для обработки событий на только созданную команду. Идем в web -> server -> handlers и создаем файл play_poker.go:

func PlayPokerCommand() http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {    w.Header().Set("Content-Type", "application/json")    w.Write([]byte(`{"response_type": "ephemeral", "text": "Hello world!"}`))})}

Добавляем наш хэндлер в роутер:

server.go
func (s *Server) setupRouter() http.Handler {router := http.NewServeMux()router.Handle("/healthcheck",handlers.Healthcheck(),)router.Handle("/play-poker",handlers.PlayPokerCommand(),)  return router}

Идем в Slack и пробуем выполнить эту команду: /poker. В ответ вы должны получить что-то вроде этого:

Но это не единственный вариант взаимодействия со Slack. Мы также можем слать сообщения в канал. Этот вариант мне понравился больше и плюс у него больше возможностей в сравнении с ответом на команду. Например вы можете послать сообщение в фоне (если оно требует долгих вычислений). Давайте напишем наш http клиента. Идем в web -> clients. Создаем файл client.go:

client.go
package clients// Создадим новый тип для наших хэндлеровtype Handler func(request *Request) *Response// Создадим новый тип для middleware (о них чуть позже)type Middleware func(handler Handler, request *Request) Handler// Создадим интерфейс http клиентаtype Client interface {Make(request *Request) *Response}// Наша реализация клиентаtype BasicClient struct {client     *http.Clientmiddleware []Middleware}func NewBasicClient(client *http.Client, middleware []Middleware) Client {return &BasicClient{client: client, middleware: middleware}}// Приватный метод для всей грязной работыfunc (c *BasicClient) makeRequest(request *Request) *Response {payload, err := request.ToBytes() // TODOif err != nil {return &Response{Error: err}}  // Создаем новый request, передаем в него данныеreq, err := http.NewRequest(request.Method, request.URL, bytes.NewBuffer(payload))if err != nil {return &Response{Error: err}}  // Применяем заголовкиfor name, value := range request.Headers {req.Header.Add(name, value)}  // Выполняем запросresp, err := c.client.Do(req)if err != nil {return &Response{Error: err}}defer resp.Body.Close()  // Читаем тело ответаbody, err := ioutil.ReadAll(resp.Body)if err != nil {return &Response{Error: err}}err = nil  // Если вернулось что-то отличное выше или ниже 20x, то ошибкаif resp.StatusCode > http.StatusIMUsed || resp.StatusCode < http.StatusOK {err = fmt.Errorf("Bad response. Status: %d, Body: %s", resp.StatusCode, string(body))}return &Response{Status:  resp.StatusCode,Body:    body,Headers: resp.Header,Error:   err,}}// Наш публичный метод для запросовfunc (c *BasicClient) Make(request *Request) *Response {if request.Headers == nil {request.Headers = make(map[string]string)}    // Применяем middlewarehandler := c.makeRequestfor _, middleware := range c.middleware {handler = middleware(handler, request)}return handler(request)}

Теперь создадим файл web -> clients:

request.go
package clientsimport "encoding/json"type Request struct {URL     stringMethod  stringHeaders map[string]stringJson    interface{}}func (r *Request) ToBytes() ([]byte, error) {if r.Json != nil {result, err := json.Marshal(r.Json)if err != nil {return []byte{}, err}return result, nil}return []byte{}, nil}

Сразу напишем тесты к методу ToBytes(). Для тестов я взял testify/assert, так как без нее была бы куча if'ов, а меня они напрягают :) . К тому же, я привык к pytest и его assert, да и как-то глазу приятнее:

request_test.go
package clients_testimport ("encoding/json""go-scrum-poker-bot/web/clients""reflect""testing""github.com/stretchr/testify/assert")func TestRequestToBytes(t *testing.T) {  // Здесь мы делаем что-то вроде pytest.parametrize (жаль, что в Go нет сахара для декораторов, это было бы удобнее)testCases := []struct {json interface{}data []byteerr  error}{{map[string]string{"test_key": "test_value"}, []byte("{\"test_key\":\"test_value\"}"), nil},{nil, []byte{}, nil},{make(chan int), []byte{}, &json.UnsupportedTypeError{Type: reflect.TypeOf(make(chan int))}},}  // Проходимся по нашим тест кейсамfor _, testCase := range testCases {request := clients.Request{URL:     "https://example.com",Method:  "GET",Headers: nil,Json:    testCase.json,}actual, err := request.ToBytes()    // Проверяем результатыassert.Equal(t, testCase.err, err)assert.Equal(t, testCase.data, actual)}}

И нам нужен web -> clients:

response.go
package clientsimport "encoding/json"type Response struct {Status  intHeaders map[string][]stringBody    []byteError   error}// Я намеренно сделал универсальный метод, чтобы можно было привезти любой ответ к нужному и не писать каждый раз эти богомерзкие if err != nilfunc (r *Response) Json(to interface{}) error {if r.Error != nil {return r.Error}return json.Unmarshal(r.Body, to)}

И также, напишем тесты для метода Json(to interface{}):

response_test.go
package clients_testimport ("errors""go-scrum-poker-bot/web/clients""testing""github.com/stretchr/testify/assert")// Один тест на позитивный кейсfunc TestResponseJson(t *testing.T) {to := struct {TestKey string `json:"test_key"`}{}response := clients.Response{Status:  200,Headers: nil,Body:    []byte(`{"test_key": "test_value"}`),Error:   nil,}err := response.Json(&to)assert.Equal(t, nil, err)assert.Equal(t, "test_value", to.TestKey)}// Один тест на ошибкуfunc TestResponseJsonError(t *testing.T) {expectedErr := errors.New("Error!")response := clients.Response{Status:  200,Headers: nil,Body:    nil,Error:   expectedErr,}err := response.Json(map[string]string{})assert.Equal(t, expectedErr, err)}

Теперь, когда у нас есть все необходимое, нам нужно написать тесты для клиента. Есть несколько вариантов написания тестов для http клиента. Я выбрал вариант с подменой http транспорта. Однако есть и другие варианты, но этот мне показался удобнее:

client_test.go
package clients_testimport ("bytes""go-scrum-poker-bot/web/clients""io/ioutil""net/http""testing""github.com/stretchr/testify/assert")// Для удобства объявим новый типtype RoundTripFunc func(request *http.Request) *http.Responsefunc (f RoundTripFunc) RoundTrip(request *http.Request) (*http.Response, error) {return f(request), nil}// Создание mock тестового клиентаfunc NewTestClient(fn RoundTripFunc) *http.Client {return &http.Client{Transport: RoundTripFunc(fn),}}// Валидный тестfunc TestMakeRequest(t *testing.T) {url := "https://example.com/ok"  // Создаем mock клиента и пишем нужный нам ответhttpClient := NewTestClient(func(req *http.Request) *http.Response {assert.Equal(t, req.URL.String(), url)return &http.Response{StatusCode: http.StatusOK,Body:       ioutil.NopCloser(bytes.NewBufferString("OK")),Header:     make(http.Header),}})  // Создаем нашего http клиента с замоканным http клиентомwebClient := clients.NewBasicClient(httpClient, nil)response := webClient.Make(&clients.Request{URL:     url,Method:  "GET",Headers: map[string]string{"Content-Type": "application/json"},Json:    nil,})assert.Equal(t, http.StatusOK, response.Status)}// Тест на ошибочный responsefunc TestMakeRequestError(t *testing.T) {url := "https://example.com/error"httpClient := NewTestClient(func(req *http.Request) *http.Response {assert.Equal(t, req.URL.String(), url)return &http.Response{StatusCode: http.StatusBadGateway,Body:       ioutil.NopCloser(bytes.NewBufferString("Bad gateway")),Header:     make(http.Header),}})webClient := clients.NewBasicClient(httpClient, nil)response := webClient.Make(&clients.Request{URL:     url,Method:  "GET",Headers: map[string]string{"Content-Type": "application/json"},Json:    nil,})assert.Equal(t, http.StatusBadGateway, response.Status)}

Отлично! Теперь давайте напишем middleware. Я привык для каждой, даже самой маленькой задачи, писать отдельную маленькую middleware. Так можно легко переиспользовать такой код в разных проектах / для разных API с разными требованиями к заголовкам / авторизации и так далее. Slack требует при отправке сообщений в канал указывать Authorization заголовок с токеном, который вы сможете найти в разделе OAuth & Permissions. Создаем в web -> clients -> middleware:

auth.go
package middlewareimport ("fmt""go-scrum-poker-bot/web/clients")// Токен будем передавать при определении middleware на этапе инициализации клиентаfunc Auth(token string) clients.Middleware {return func(handler clients.Handler, request *clients.Request) clients.Handler {return func(request *clients.Request) *clients.Response {request.Headers["Authorization"] = fmt.Sprintf("Bearer %s", token)return handler(request)}}}

И напишем тест к ней:

auth_test.go
package middleware_testimport ("fmt""go-scrum-poker-bot/web/clients""go-scrum-poker-bot/web/clients/middleware""testing""github.com/stretchr/testify/assert")func TestAuthMiddleware(t *testing.T) {token := "test"request := &clients.Request{Headers: map[string]string{},}handler := middleware.Auth(token)(func(request *clients.Request) *clients.Response {return &clients.Response{}},request,)handler(request)assert.Equal(t, map[string]string{"Authorization": fmt.Sprintf("Bearer %s", token)}, request.Headers)}

Также в репозитории вы сможете найти middleware для логирования и установки Content-Type: application/json. Здесь я не буду приводить этот код в целях экономии времени и места :).

Давайте перепишем наш PlayPoker хэндлер:

play_poker.go
package handlersimport ("errors""go-scrum-poker-bot/ui""go-scrum-poker-bot/web/clients""go-scrum-poker-bot/web/server/models""net/http""github.com/google/uuid")func PlayPokerCommand(webClient clients.Client, uiBuilder *ui.Builder) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {    // Добавим проверку, что нам пришли данные из POST Form с текстом и ID каналаif r.PostFormValue("channel_id") == "" || r.PostFormValue("text") == "" {w.Write(models.ResponseError(errors.New("Please write correct subject"))) // TODOreturn}resp := webClient.Make(&clients.Request{URL:    "https://slack.com/api/chat.postMessage",Method: "POST",      Json: uiBuilder.Build( // TODO: Напишем builder позжеr.PostFormValue("channel_id"),uuid.New().String(),r.PostFormValue("text"),nil,false,),})if resp.Error != nil {w.Write(models.ResponseError(resp.Error)) // TODOreturn}})}

И создадим в web -> server -> models . Файл errors.go для быстрого формирования ошибок:

errors.go
package modelsimport ("encoding/json""fmt")type SlackError struct {ResponseType string `json:"response_type"`Text         string `json:"text"`}func ResponseError(err error) []byte {resp, err := json.Marshal(SlackError{ResponseType: "ephemeral",Text:         fmt.Sprintf("Sorry, there is some error happened. Error: %s", err.Error()),},)if err != nil {return []byte("Sorry. Some error happened")}return resp}

Напишем тесты для хэндлера:

play_poker_test.go
package handlers_testimport ("errors""go-scrum-poker-bot/config""go-scrum-poker-bot/ui""go-scrum-poker-bot/web/server/handlers""go-scrum-poker-bot/web/server/models""net/http""net/http/httptest""net/url""strings""testing""github.com/stretchr/testify/assert")func TestPlayPokerHandler(t *testing.T) {config := config.NewConfig() // TODOmockClient := &MockClient{}uiBuilder := ui.NewBuilder(config) // TODOresponseRec := httptest.NewRecorder()router := http.NewServeMux()router.Handle("/play-poker", handlers.PlayPokerCommand(mockClient, uiBuilder))payload := url.Values{"channel_id": {"test"}, "text": {"test"}}.Encode()request, err := http.NewRequest("POST", "/play-poker", strings.NewReader(payload))request.Header.Set("Content-Type", "application/x-www-form-urlencoded")router.ServeHTTP(responseRec, request)assert.Nil(t, err)assert.Equal(t, http.StatusOK, responseRec.Code)assert.Empty(t, responseRec.Body.String())assert.Equal(t, true, mockClient.Called)}func TestPlayPokerHandlerEmptyBodyError(t *testing.T) {config := config.NewConfig()mockClient := &MockClient{}uiBuilder := ui.NewBuilder(config)responseRec := httptest.NewRecorder()router := http.NewServeMux()router.Handle("/play-poker", handlers.PlayPokerCommand(mockClient, uiBuilder))payload := url.Values{}.Encode()request, _ := http.NewRequest("POST", "/play-poker", strings.NewReader(payload))request.Header.Set("Content-Type", "application/x-www-form-urlencoded")router.ServeHTTP(responseRec, request)expected := string(models.ResponseError(errors.New("Please write correct subject")))assert.Equal(t, http.StatusOK, responseRec.Code)assert.Equal(t, expected, responseRec.Body.String())assert.Equal(t, false, mockClient.Called)}func TestPlayPokerHandlerRequestError(t *testing.T) {errMsg := "Error msg"config := config.NewConfig() // TODOmockClient := &MockClient{Error: errMsg}uiBuilder := ui.NewBuilder(config) // TODOresponseRec := httptest.NewRecorder()router := http.NewServeMux()router.Handle("/play-poker", handlers.PlayPokerCommand(mockClient, uiBuilder))payload := url.Values{"channel_id": {"test"}, "text": {"test"}}.Encode()request, _ := http.NewRequest("POST", "/play-poker", strings.NewReader(payload))request.Header.Set("Content-Type", "application/x-www-form-urlencoded")router.ServeHTTP(responseRec, request)expected := string(models.ResponseError(errors.New(errMsg)))assert.Equal(t, http.StatusOK, responseRec.Code)assert.Equal(t, expected, responseRec.Body.String())assert.Equal(t, true, mockClient.Called)}

Теперь нам нужно написать mock для нашего http клиента:

common_test.go
package handlers_testimport ("errors""go-scrum-poker-bot/web/clients")type MockClient struct {Called boolError  string}func (c *MockClient) Make(request *clients.Request) *clients.Response {c.Called = truevar err error = nilif c.Error != "" {err = errors.New(c.Error)}return &clients.Response{Error: err}}

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

Теперь можно приступить к написанию UI строителя интерфейсов для Slack UI Block Kit. Там все довольно просто, но много однотипного кода. Отмечу лишь, что Slack API мне не очень понравился и было тяжело с ним работать. Сам UI Builder можно глянуть в папке ui здесь. А здесь, в целях экономии времени, я не буду на нем заострять внимания. Отмечу лишь, что в качестве якоря для понимания того, событие от какого сообщения пришло и какой был текст для голосования (его мы не будем сохранять у себя, а будем брать непосредственно из события) будем использовать block_id. А для определения типа события будем смотреть на action_id.

Давайте создадим конфиг для нашего приложения. Идем в config и создаем:

config.go
package configtype Config struct {App   *AppSlack *SlackRedis *Redis}func NewConfig() *Config {return &Config{App: &App{ServerAddress: getStrEnv("WEB_SERVER_ADDRESS", ":8000"),PokerRanks:    getListStrEnv("POKER_RANKS", "?,0,0.5,1,2,3,5,8,13,20,40,100"),},Slack: &Slack{Token: getStrEnv("SLACK_TOKEN", "FILL_ME"),},    // Скоро понадобитсяRedis: &Redis{Host: getStrEnv("REDIS_HOST", "0.0.0.0"),Port: getIntEnv("REDIS_PORT", "6379"),DB:   getIntEnv("REDIS_DB", "0"),},}}// Получаем значение из env или выставляем defaultfunc getStrEnv(key string, defaultValue string) string {if value, ok := os.LookupEnv(key); ok {return value}return defaultValue}// Получаем int значение из env или выставляем defaultfunc getIntEnv(key string, defaultValue string) int {value, err := strconv.Atoi(getStrEnv(key, defaultValue))if err != nil {panic(fmt.Sprintf("Incorrect env value for %s", key))}return value}// Получаем список (e.g. 0,1,2,3,4,5) из env или выставляем defaultfunc getListStrEnv(key string, defaultValue string) []string {value := []string{}for _, item := range strings.Split(getStrEnv(key, defaultValue), ",") {value = append(value, strings.TrimSpace(item))}return value}

И напишем тесты к нему. Будем тестировать только публичные методы:

config_test.go
package config_testimport (    "go-scrum-poker-bot/config"    "os"    "testing"    "github.com/stretchr/testify/assert")func TestNewConfig(t *testing.T) {    c := config.NewConfig()    assert.Equal(t, "0.0.0.0", c.Redis.Host)    assert.Equal(t, 6379, c.Redis.Port)    assert.Equal(t, 0, c.Redis.DB)    assert.Equal(t, []string{"?", "0", "0.5", "1", "2", "3", "5", "8", "13", "20", "40", "100"}, c.App.PokerRanks)}func TestNewConfigIncorrectIntFromEnv(t *testing.T) {    os.Setenv("REDIS_PORT", "-")    assert.Panics(t, func() { config.NewConfig() })}

Я намеренно сделал обязательность выставления значений по умолчанию, хотя это не самый правильный путь. Изменим main.go:

main.go
package mainimport ("fmt""go-scrum-poker-bot/config""go-scrum-poker-bot/ui""go-scrum-poker-bot/web/clients"clients_middleware "go-scrum-poker-bot/web/clients/middleware""go-scrum-poker-bot/web/server"  "log""net/http""os""time")func main() {logger := log.New(os.Stdout, "INFO: ", log.LstdFlags)config := config.NewConfig()builder := ui.NewBuilder(config)webClient := clients.NewBasicClient(&http.Client{Timeout: 5 * time.Second,},[]clients.Middleware{ // Наши middlewareclients_middleware.Auth(config.Slack.Token),clients_middleware.JsonContentType,clients_middleware.Log(logger),},)app := server.NewServer(logger,webClient,builder,)app.Serve(config.App.ServerAddress)}

Теперь при запуске команды /poker мы в ответ получим наш симпатичный минималистичный интерфейс.

Slack Interactivity

Давайте научимся реагировать на события при взаимодействии пользователя с ним. Зайдем Your apps -> Наш бот -> Interactivity & Shortcuts. В Request URL введем:

https://ffd3cfcc460c.ngrok.io/interactivity

Создадим еще один хэндлер InteractionCallback в web -> server -> handlers:

interaction_callback.go
package handlersimport ("go-scrum-poker-bot/storage""go-scrum-poker-bot/ui""go-scrum-poker-bot/ui/blocks""go-scrum-poker-bot/web/clients""go-scrum-poker-bot/web/server/models""net/http")func InteractionCallback(userStorage storage.UserStorage,sessionStorage storage.SessionStorage,uiBuilder *ui.Builder,webClient clients.Client,) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {var callback models.Callback    // Об этом нижеdata, err := callback.SerializedData([]byte(r.PostFormValue("payload")))if err != nil {http.Error(w, err.Error(), http.StatusBadRequest)return}    // TODO: Скоро доберемся до нихusers := userStorage.All(data.SessionID)visible := sessionStorage.GetVisibility(data.SessionID)err = nil    // Определяем какое событие к нам поступило и реализуем немного логики исходя из негоswitch data.Action.ActionID {case ui.VOTE_ACTION_ID:users[callback.User.Username] = data.Action.SelectedOption.Valueerr = userStorage.Save(data.SessionID, callback.User.Username, data.Action.SelectedOption.Value)case ui.RESULTS_VISIBILITY_ACTION_ID:visible = !visibleerr = sessionStorage.SetVisibility(data.SessionID, visible)}if err != nil {http.Error(w, err.Error(), http.StatusInternalServerError)return}    // Шлем ответ перерисовывая интерфейс сообщения через response URL. Для пользователя все пройдет незаметноresp := webClient.Make(&clients.Request{URL:    callback.ResponseURL,Method: "POST",Json: &blocks.Interactive{ReplaceOriginal: true,Blocks:          uiBuilder.BuildBlocks(data.Subject, users, data.SessionID, visible),LinkNames:       true,},})if resp.Error != nil {http.Error(w, resp.Error.Error(), http.StatusInternalServerError)return}})}

Мы пока не определили наше хранилище. Давайте определим их интерфейсы и напишем тест на этот хэндлер. Идем в storage:

storage.go
package storagetype UserStorage interface {All(sessionID string) map[string]stringSave(sessionID string, username string, value string) error}type SessionStorage interface {GetVisibility(sessionID string) boolSetVisibility(sessionID string, state bool) error}

Я намеренно разбил логику на два хранилища, поскольку так удобнее тестировать и если будет нужно, то легко можно будет перевести например хранение голосов пользователей в базу данных, а настройки сессии оставить в Redis (как пример).

Теперь нужно создать модель Callback. Идем в web -> server -> models:

callback.go
package modelsimport ("encoding/json""errors""go-scrum-poker-bot/ui")type User struct {Username string `json:"username"`}type Text struct {Type string `json:"type"`Text string `json:"text"`}type Block struct {Type    string `json:"type"`BlockID string `json:"block_id"`Text    *Text  `json:"text,omitempty"`}type Message struct {Blocks []*Block `json:"blocks,omitempty"`}type SelectedOption struct {Value string `json:"value"`}type Action struct {BlockID        string          `json:"block_id"`ActionID       string          `json:"action_id"`Value          string          `json:"value,omitempty"`SelectedOption *SelectedOption `json:"selected_option,omitempty"`}type SerializedData struct {SessionID stringSubject   stringAction    *Action}type Callback struct {ResponseURL string    `json:"response_url"`User        *User     `json:"user"`Actions     []*Action `json:"actions"`Message     *Message  `json:"message,omitempty"`}// Грязно достаем ID сессии, но другого способа я не смог придуматьfunc (c *Callback) getSessionID() (string, error) {for _, action := range c.Actions {if action.BlockID != "" {return action.BlockID, nil}}return "", errors.New("Invalid session ID")}// Текст для голосованияfunc (c *Callback) getSubject() (string, error) {for _, block := range c.Message.Blocks {if block.BlockID == ui.SUBJECT_BLOCK_ID && block.Text != nil {return block.Text.Text, nil}}return "", errors.New("Invalid subject")}// Какое событие к нам пришлоfunc (c *Callback) getAction() (*Action, error) {for _, action := range c.Actions {if action.ActionID == ui.VOTE_ACTION_ID || action.ActionID == ui.RESULTS_VISIBILITY_ACTION_ID {return action, nil}}return nil, errors.New("Invalid action")}func (c *Callback) SerializedData(data []byte) (*SerializedData, error) {err := json.Unmarshal(data, c)if err != nil {return nil, err}sessionID, err := c.getSessionID()if err != nil {return nil, err}subject, err := c.getSubject()if err != nil {return nil, err}action, err := c.getAction()if err != nil {return nil, err}return &SerializedData{SessionID: sessionID,Subject:   subject,Action:    action,}, nil}

Давайте напишем тест на наш хэндлер:

interaction_callback_test.go
package handlers_testimport ("encoding/json""go-scrum-poker-bot/config""go-scrum-poker-bot/ui""go-scrum-poker-bot/web/server/handlers""go-scrum-poker-bot/web/server/models""net/http""net/http/httptest""net/url""strings""testing""github.com/stretchr/testify/assert")func TestInteractionCallbackHandlerActions(t *testing.T) {config := config.NewConfig()mockClient := &MockClient{}mockUserStorage := &MockUserStorage{}mockSessionStorage := &MockSessionStorage{}uiBuilder := ui.NewBuilder(config)router := http.NewServeMux()router.Handle("/interactivity",handlers.InteractionCallback(mockUserStorage, mockSessionStorage, uiBuilder, mockClient),)actions := []*models.Action{{BlockID:        "test",ActionID:       ui.RESULTS_VISIBILITY_ACTION_ID,Value:          "test",SelectedOption: nil,},{BlockID:        "test",ActionID:       ui.VOTE_ACTION_ID,Value:          "test",SelectedOption: &models.SelectedOption{Value: "1"},},}  // Проверяем на двух разных типах событийfor _, action := range actions {responseRec := httptest.NewRecorder()data, _ := json.Marshal(models.Callback{ResponseURL: "test",User:        &models.User{Username: "test"},Actions:     []*models.Action{action},Message: &models.Message{Blocks: []*models.Block{{Type:    "test",BlockID: ui.SUBJECT_BLOCK_ID,Text:    &models.Text{Type: "test", Text: "test"},},},},})payload := url.Values{"payload": {string(data)}}.Encode()request, err := http.NewRequest("POST", "/interactivity", strings.NewReader(payload))request.Header.Set("Content-Type", "application/x-www-form-urlencoded")router.ServeHTTP(responseRec, request)assert.Nil(t, err)assert.Equal(t, http.StatusOK, responseRec.Code)assert.Empty(t, responseRec.Body.String())assert.Equal(t, true, mockClient.Called)}}

Осталось определить mock для наших хранилищ. Обновим файл common_test.go:

common_test.go
// Существующий кодtype MockUserStorage struct{}func (s *MockUserStorage) All(sessionID string) map[string]string {return map[string]string{"user": "1"}}func (s *MockUserStorage) Save(sessionID string, username string, value string) error {return nil}type MockSessionStorage struct{}func (s *MockSessionStorage) GetVisibility(sessionID string) bool {return true}func (s *MockSessionStorage) SetVisibility(sessionID string, state bool) error {return nil}

Добавив в роутер новый хэндлер:

server.go
// Существующий кодfunc (s *Server) setupRouter() http.Handler {router := http.NewServeMux()router.Handle("/healthcheck",handlers.Healthcheck(),)router.Handle("/play-poker",handlers.PlayPokerCommand(s.webClient, s.uiBuilder),)router.Handle("/interactivity",handlers.InteractionCallback(s.userStorage, s.sessionStorage, s.uiBuilder, s.webClient),)return router}// Существующий код

Все хорошо, но наш сервер никак не уведомляет нас о том, что к нему поступил запрос + если мы где-то поймаем панику, то сервер может упасть. Давайте это исправим через middleware. Создаем папку web -> server -> middleware:

log.go
package middlewareimport ("log""net/http")func Log(logger *log.Logger) func(http.Handler) http.Handler {return func(next http.Handler) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {defer func() {logger.Printf("Handle request: [%s]: %s - %s - %s",r.Method, r.URL.Path, r.RemoteAddr, r.UserAgent(),)}()next.ServeHTTP(w, r)})}}

И напишем для нее тест:

log_test.go
package middleware_testimport ("bytes""go-scrum-poker-bot/web/server/middleware""log""net/http""net/http/httptest""os""strings""testing""github.com/stretchr/testify/assert")type logHandler struct{}func (h *logHandler) ServeHTTP(http.ResponseWriter, *http.Request) {}func TestLogMiddleware(t *testing.T) {var buf bytes.Bufferlogger := log.New(os.Stdout, "INFO: ", log.LstdFlags)  // Выставляем для логгера output наш буффер, чтобы все писалось в негоlogger.SetOutput(&buf)handler := &logHandler{}  // Берем mock recorder из стандартной библиотеки GoresponseRec := httptest.NewRecorder()router := http.NewServeMux()router.Handle("/test", middleware.Log(logger)(handler))request, err := http.NewRequest("GET", "/test", strings.NewReader(""))router.ServeHTTP(responseRec, request)assert.Nil(t, err)assert.Equal(t, http.StatusOK, responseRec.Code)  // Проверяем, что в буффер что-то пришло. Этого нам достаточно, чтобы понять, что middleware успешно отработалаassert.NotEmpty(t, buf.String())}

Остальные middleware можете найти здесь.

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

Для начала научимся сохранять и получать всех пользователей переданной Scrum Poker сессии. Идем в storage:

users.go
package storageimport ("context""fmt""github.com/go-redis/redis/v8")// Шаблоны ключейconst SESSION_USERS_TPL = "SESSION:%s:USERS"const USER_VOTE_TPL = "SESSION:%s:USERNAME:%s:VOTE"type UserRedisStorage struct {redis   *redis.Clientcontext context.Context}func NewUserRedisStorage(redisClient *redis.Client) *UserRedisStorage {return &UserRedisStorage{redis:   redisClient,context: context.Background(),}}func (s *UserRedisStorage) All(sessionID string) map[string]string {users := make(map[string]string)  // Пользователей будем хранить в set, так как сортировка для нас не принципиальна.   // Заодно избавимся от необходимости искать дубликатыfor _, username := range s.redis.SMembers(s.context, fmt.Sprintf(SESSION_USERS_TPL, sessionID)).Val() {users[username] = s.redis.Get(s.context, fmt.Sprintf(USER_VOTE_TPL, sessionID, username)).Val()}return users}func (s *UserRedisStorage) Save(sessionID string, username string, value string) error {err := s.redis.SAdd(s.context, fmt.Sprintf(SESSION_USERS_TPL, sessionID), username).Err()if err != nil {return err}  // Голоса пользователей будем хранить в обычных ключах.   // Я сделал вечное хранение, но это легко можно поменять, изменив -1 на нужное значениеerr = s.redis.Set(s.context, fmt.Sprintf(USER_VOTE_TPL, sessionID, username), value, -1).Err()if err != nil {return err}return nil}

Напишем тесты:

users_test.go
package storage_testimport ("errors""fmt""go-scrum-poker-bot/storage""testing""github.com/go-redis/redismock/v8""github.com/stretchr/testify/assert")func TestAll(t *testing.T) {sessionID, username, value := "test", "user", "1"redisClient, mock := redismock.NewClientMock()usersStorage := storage.NewUserRedisStorage(redisClient)  // Redis mock требует обязательного указания всех ожидаемых команд и результаты их выполненияmock.ExpectSMembers(fmt.Sprintf(storage.SESSION_USERS_TPL, sessionID),).SetVal([]string{username})mock.ExpectGet(fmt.Sprintf(storage.USER_VOTE_TPL, sessionID, username),).SetVal(value)assert.Equal(t, map[string]string{username: value}, usersStorage.All(sessionID))}func TestSave(t *testing.T) {sessionID, username, value := "test", "user", "1"redisClient, mock := redismock.NewClientMock()usersStorage := storage.NewUserRedisStorage(redisClient)mock.ExpectSAdd(fmt.Sprintf(storage.SESSION_USERS_TPL, sessionID),username,).SetVal(1)mock.ExpectSet(fmt.Sprintf(storage.USER_VOTE_TPL, sessionID, username),value,-1,).SetVal(value)assert.Equal(t, nil, usersStorage.Save(sessionID, username, value))}func TestSaveSAddErr(t *testing.T) {sessionID, username, value, err := "test", "user", "1", errors.New("ERROR")redisClient, mock := redismock.NewClientMock()usersStorage := storage.NewUserRedisStorage(redisClient)mock.ExpectSAdd(fmt.Sprintf(storage.SESSION_USERS_TPL, sessionID),username,).SetErr(err)assert.Equal(t, err, usersStorage.Save(sessionID, username, value))}func TestSaveSetErr(t *testing.T) {sessionID, username, value, err := "test", "user", "1", errors.New("ERROR")redisClient, mock := redismock.NewClientMock()usersStorage := storage.NewUserRedisStorage(redisClient)mock.ExpectSAdd(fmt.Sprintf(storage.SESSION_USERS_TPL, sessionID),username,).SetVal(1)mock.ExpectSet(fmt.Sprintf(storage.USER_VOTE_TPL, sessionID, username),value,-1,).SetErr(err)assert.Equal(t, err, usersStorage.Save(sessionID, username, value))}

Теперь определим хранилище для "покерной" сессии. Пока там будет лежать статус видимости голосов:

sessions.go
package storageimport ("context""fmt""strconv""github.com/go-redis/redis/v8")// Шаблон для ключейconst SESSION_VOTES_HIDDEN_TPL = "SESSION:%s:VOTES_HIDDEN"type SessionRedisStorage struct {redis   *redis.Clientcontext context.Context}func NewSessionRedisStorage(redisClient *redis.Client) *SessionRedisStorage {return &SessionRedisStorage{redis:   redisClient,context: context.Background(),}}func (s *SessionRedisStorage) GetVisibility(sessionID string) bool {value, _ := strconv.ParseBool(s.redis.Get(s.context, fmt.Sprintf(SESSION_VOTES_HIDDEN_TPL, sessionID)).Val(),)return value}func (s *SessionRedisStorage) SetVisibility(sessionID string, state bool) error {return s.redis.Set(s.context,fmt.Sprintf(SESSION_VOTES_HIDDEN_TPL, sessionID),strconv.FormatBool(state),-1,).Err()}

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

sessions_test.go
package storage_testimport ("errors""fmt""go-scrum-poker-bot/storage""strconv""testing""github.com/go-redis/redismock/v8""github.com/stretchr/testify/assert")func TestGetVisibility(t *testing.T) {sessionID, state := "test", trueredisClient, mock := redismock.NewClientMock()mock.ExpectGet(fmt.Sprintf(storage.SESSION_VOTES_HIDDEN_TPL, sessionID),).SetVal(strconv.FormatBool(state))sessionStorage := storage.NewSessionRedisStorage(redisClient)assert.Equal(t, state, sessionStorage.GetVisibility(sessionID))}func TestSetVisibility(t *testing.T) {sessionID, state := "test", trueredisClient, mock := redismock.NewClientMock()mock.ExpectSet(fmt.Sprintf(storage.SESSION_VOTES_HIDDEN_TPL, sessionID),strconv.FormatBool(state),-1,).SetVal("1")sessionStorage := storage.NewSessionRedisStorage(redisClient)assert.Equal(t, nil, sessionStorage.SetVisibility(sessionID, state))}func TestSetVisibilityErr(t *testing.T) {sessionID, state, err := "test", true, errors.New("ERROR")redisClient, mock := redismock.NewClientMock()mock.ExpectSet(fmt.Sprintf(storage.SESSION_VOTES_HIDDEN_TPL, sessionID),strconv.FormatBool(state),-1,).SetErr(err)sessionStorage := storage.NewSessionRedisStorage(redisClient)assert.Equal(t, err, sessionStorage.SetVisibility(sessionID, state))}

Отлично! Осталось изменить main.go и server.go:

server.go
package serverimport ("context""go-scrum-poker-bot/storage""go-scrum-poker-bot/ui""go-scrum-poker-bot/web/clients""go-scrum-poker-bot/web/server/handlers""log""net/http""os""os/signal""sync/atomic""time")// Новый тип для middlewaretype Middleware func(next http.Handler) http.Handler// Все зависимости здесьtype Server struct {healthy        int32middleware     []Middlewarelogger         *log.LoggerwebClient      clients.ClientuiBuilder      *ui.BuilderuserStorage    storage.UserStoragesessionStorage storage.SessionStorage}// Добавляем их при инициализации сервераfunc NewServer(logger *log.Logger,webClient clients.Client,uiBuilder *ui.Builder,userStorage storage.UserStorage,sessionStorage storage.SessionStorage,middleware []Middleware,) *Server {return &Server{logger:         logger,webClient:      webClient,uiBuilder:      uiBuilder,userStorage:    userStorage,sessionStorage: sessionStorage,middleware:     middleware,}}func (s *Server) setupRouter() http.Handler {router := http.NewServeMux()router.Handle("/healthcheck",handlers.Healthcheck(),)router.Handle("/play-poker",handlers.PlayPokerCommand(s.webClient, s.uiBuilder),)router.Handle("/interactivity",handlers.InteractionCallback(s.userStorage, s.sessionStorage, s.uiBuilder, s.webClient),)return router}func (s *Server) setupMiddleware(router http.Handler) http.Handler {handler := routerfor _, middleware := range s.middleware {handler = middleware(handler)}return handler}func (s *Server) Serve(address string) {server := &http.Server{Addr:         address,Handler:      s.setupMiddleware(s.setupRouter()),ErrorLog:     s.logger,ReadTimeout:  5 * time.Second,WriteTimeout: 10 * time.Second,IdleTimeout:  15 * time.Second,}done := make(chan bool)quit := make(chan os.Signal, 1)signal.Notify(quit, os.Interrupt)go func() {<-quits.logger.Println("Server is shutting down...")atomic.StoreInt32(&s.healthy, 0)ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)defer cancel()server.SetKeepAlivesEnabled(false)if err := server.Shutdown(ctx); err != nil {s.logger.Fatalf("Could not gracefully shutdown the server: %v\n", err)}close(done)}()s.logger.Println("Server is ready to handle requests at", address)atomic.StoreInt32(&s.healthy, 1)if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {s.logger.Fatalf("Could not listen on %s: %v\n", address, err)}<-dones.logger.Println("Server stopped")}
main.go
package mainimport ("fmt""go-scrum-poker-bot/config""go-scrum-poker-bot/storage""go-scrum-poker-bot/ui""go-scrum-poker-bot/web/clients"clients_middleware "go-scrum-poker-bot/web/clients/middleware""go-scrum-poker-bot/web/server"server_middleware "go-scrum-poker-bot/web/server/middleware""log""net/http""os""time""github.com/go-redis/redis/v8")func main() {logger := log.New(os.Stdout, "INFO: ", log.LstdFlags)config := config.NewConfig()  // Объявляем Redis клиентredisCLI := redis.NewClient(&redis.Options{Addr: fmt.Sprintf("%s:%d", config.Redis.Host, config.Redis.Port),DB:   config.Redis.DB,})  // Наш users storageuserStorage := storage.NewUserRedisStorage(redisCLI)  // Наш sessions storagesessionStorage := storage.NewSessionRedisStorage(redisCLI)builder := ui.NewBuilder(config)webClient := clients.NewBasicClient(&http.Client{Timeout: 5 * time.Second,},[]clients.Middleware{clients_middleware.Auth(config.Slack.Token),clients_middleware.JsonContentType,clients_middleware.Log(logger),},)  // В Server теперь есть middlewareapp := server.NewServer(logger,webClient,builder,userStorage,sessionStorage,[]server.Middleware{server_middleware.Recover(logger), server_middleware.Log(logger), server_middleware.Json},)app.Serve(config.App.ServerAddress)}

Запустим тесты:

go test ./... -race -coverpkg=./... -coverprofile=coverage.txt -covermode=atomic

Результат:

go tool cover -func coverage.txt
$ go tool cover -func coverage.txtgo-scrum-poker-bot/config/config.go:9:                                  NewConfig               100.0%go-scrum-poker-bot/config/helpers.go:10:                                getStrEnv               100.0%go-scrum-poker-bot/config/helpers.go:17:                                getIntEnv               100.0%go-scrum-poker-bot/config/helpers.go:26:                                getListStrEnv           100.0%go-scrum-poker-bot/main.go:22:                                          main                    0.0%go-scrum-poker-bot/storage/sessions.go:18:                              NewSessionRedisStorage  100.0%go-scrum-poker-bot/storage/sessions.go:25:                              GetVisibility           100.0%go-scrum-poker-bot/storage/sessions.go:33:                              SetVisibility           100.0%go-scrum-poker-bot/storage/users.go:18:                                 NewUserRedisStorage     100.0%go-scrum-poker-bot/storage/users.go:25:                                 All                     100.0%go-scrum-poker-bot/storage/users.go:34:                                 Save                    100.0%go-scrum-poker-bot/ui/blocks/action.go:9:                               BlockType               100.0%go-scrum-poker-bot/ui/blocks/button.go:11:                              BlockType               100.0%go-scrum-poker-bot/ui/blocks/context.go:9:                              BlockType               100.0%go-scrum-poker-bot/ui/blocks/section.go:9:                              BlockType               100.0%go-scrum-poker-bot/ui/blocks/select.go:10:                              BlockType               100.0%go-scrum-poker-bot/ui/builder.go:14:                                    NewBuilder              100.0%go-scrum-poker-bot/ui/builder.go:18:                                    getGetResultsText       100.0%go-scrum-poker-bot/ui/builder.go:26:                                    getResults              100.0%go-scrum-poker-bot/ui/builder.go:41:                                    getOptions              100.0%go-scrum-poker-bot/ui/builder.go:50:                                    BuildBlocks             100.0%go-scrum-poker-bot/ui/builder.go:100:                                   Build                   100.0%go-scrum-poker-bot/web/clients/client.go:22:                            NewBasicClient          100.0%go-scrum-poker-bot/web/clients/client.go:26:                            makeRequest             78.9%go-scrum-poker-bot/web/clients/client.go:65:                            Make                    66.7%go-scrum-poker-bot/web/clients/middleware/auth.go:8:                    Auth                    100.0%go-scrum-poker-bot/web/clients/middleware/json.go:5:                    JsonContentType         100.0%go-scrum-poker-bot/web/clients/middleware/log.go:8:                     Log                     87.5%go-scrum-poker-bot/web/clients/request.go:12:                           ToBytes                 100.0%go-scrum-poker-bot/web/clients/response.go:12:                          Json                    100.0%go-scrum-poker-bot/web/server/handlers/healthcheck.go:10:               Healthcheck             66.7%go-scrum-poker-bot/web/server/handlers/interaction_callback.go:12:      InteractionCallback     71.4%go-scrum-poker-bot/web/server/handlers/play_poker.go:13:                PlayPokerCommand        100.0%go-scrum-poker-bot/web/server/middleware/json.go:5:                     Json                    100.0%go-scrum-poker-bot/web/server/middleware/log.go:8:                      Log                     100.0%go-scrum-poker-bot/web/server/middleware/recover.go:9:                  Recover                 100.0%go-scrum-poker-bot/web/server/models/callback.go:52:                    getSessionID            100.0%go-scrum-poker-bot/web/server/models/callback.go:62:                    getSubject              100.0%go-scrum-poker-bot/web/server/models/callback.go:72:                    getAction               100.0%go-scrum-poker-bot/web/server/models/callback.go:82:                    SerializedData          92.3%go-scrum-poker-bot/web/server/models/errors.go:13:                      ResponseError           75.0%go-scrum-poker-bot/web/server/server.go:31:                             NewServer               0.0%go-scrum-poker-bot/web/server/server.go:49:                             setupRouter             0.0%go-scrum-poker-bot/web/server/server.go:67:                             setupMiddleware         0.0%go-scrum-poker-bot/web/server/server.go:76:                             Serve                   0.0%total:                                                                  (statements)            75.1%

Неплохо, но нам не нужно учитывать в coverage main.go (мое мнение) и server.go (здесь можно поспорить), поэтому есть хак :). Нужно добавить в начало файлов, которые мы хотим исключить из оценки следующую строчку с тегами:

//+build !test

Перезапустим с тегом:

go test ./... -race -coverpkg=./... -coverprofile=coverage.txt -covermode=atomic -tags=test

Результат:

go tool cover -func coverage.txt
$ go tool cover -func coverage.txtgo-scrum-poker-bot/config/config.go:9:                                  NewConfig               100.0%go-scrum-poker-bot/config/helpers.go:10:                                getStrEnv               100.0%go-scrum-poker-bot/config/helpers.go:17:                                getIntEnv               100.0%go-scrum-poker-bot/config/helpers.go:26:                                getListStrEnv           100.0%go-scrum-poker-bot/storage/sessions.go:18:                              NewSessionRedisStorage  100.0%go-scrum-poker-bot/storage/sessions.go:25:                              GetVisibility           100.0%go-scrum-poker-bot/storage/sessions.go:33:                              SetVisibility           100.0%go-scrum-poker-bot/storage/users.go:18:                                 NewUserRedisStorage     100.0%go-scrum-poker-bot/storage/users.go:25:                                 All                     100.0%go-scrum-poker-bot/storage/users.go:34:                                 Save                    100.0%go-scrum-poker-bot/ui/blocks/action.go:9:                               BlockType               100.0%go-scrum-poker-bot/ui/blocks/button.go:11:                              BlockType               100.0%go-scrum-poker-bot/ui/blocks/context.go:9:                              BlockType               100.0%go-scrum-poker-bot/ui/blocks/section.go:9:                              BlockType               100.0%go-scrum-poker-bot/ui/blocks/select.go:10:                              BlockType               100.0%go-scrum-poker-bot/ui/builder.go:14:                                    NewBuilder              100.0%go-scrum-poker-bot/ui/builder.go:18:                                    getGetResultsText       100.0%go-scrum-poker-bot/ui/builder.go:26:                                    getResults              100.0%go-scrum-poker-bot/ui/builder.go:41:                                    getOptions              100.0%go-scrum-poker-bot/ui/builder.go:50:                                    BuildBlocks             100.0%go-scrum-poker-bot/ui/builder.go:100:                                   Build                   100.0%go-scrum-poker-bot/web/clients/client.go:22:                            NewBasicClient          100.0%go-scrum-poker-bot/web/clients/client.go:26:                            makeRequest             78.9%go-scrum-poker-bot/web/clients/client.go:65:                            Make                    66.7%go-scrum-poker-bot/web/clients/middleware/auth.go:8:                    Auth                    100.0%go-scrum-poker-bot/web/clients/middleware/json.go:5:                    JsonContentType         100.0%go-scrum-poker-bot/web/clients/middleware/log.go:8:                     Log                     87.5%go-scrum-poker-bot/web/clients/request.go:12:                           ToBytes                 100.0%go-scrum-poker-bot/web/clients/response.go:12:                          Json                    100.0%go-scrum-poker-bot/web/server/handlers/healthcheck.go:10:               Healthcheck             66.7%go-scrum-poker-bot/web/server/handlers/interaction_callback.go:12:      InteractionCallback     71.4%go-scrum-poker-bot/web/server/handlers/play_poker.go:13:                PlayPokerCommand        100.0%go-scrum-poker-bot/web/server/middleware/json.go:5:                     Json                    100.0%go-scrum-poker-bot/web/server/middleware/log.go:8:                      Log                     100.0%go-scrum-poker-bot/web/server/middleware/recover.go:9:                  Recover                 100.0%go-scrum-poker-bot/web/server/models/callback.go:52:                    getSessionID            100.0%go-scrum-poker-bot/web/server/models/callback.go:62:                    getSubject              100.0%go-scrum-poker-bot/web/server/models/callback.go:72:                    getAction               100.0%go-scrum-poker-bot/web/server/models/callback.go:82:                    SerializedData          92.3%go-scrum-poker-bot/web/server/models/errors.go:13:                      ResponseError           75.0%total:                                                                  (statements)            90.9%

Такой результат мне нравится больше :)

На этом пожалуй остановлюсь. Весь код можете найти здесь. Спасибо за внимание!

Подробнее..

Если у вас нашли SCRUM

03.06.2021 00:16:55 | Автор: admin

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

Шутки шутками, а широкий опыт внедрения данной методологии в России насчитывает (на моей памяти) около 10 лет. Может даже больше. Но до сих пор не стихают споры об опасности SCRUM.

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

Почему SCRUM так заразен?

Большинство внедрений SCRUM начинаются с того, что кто-то по нему где-то работал. Чуть меньше потому, что он слышал о нем что-то. Далее следует экспресс-анализ, в ходе которого человек узнает о спринтах. Смысл видится примерно таким:

  • Берется кучка фич из бэклога и пилится неделю.

  • Программиста никто не дергает.

  • Релиз.

Собственно все. SCRUM продан! Куда уж проще и понятнее?

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

Таким образом, крайняя простота базовой механики SCRUM настолько понятна, что практически очевидна. Уже через час появляется тимлид, он же SCRUM-мастер. Тут же нарушая принцип SCRUM о разделении ролей. Но сейчас не об этом.

Именно эта простота проникновения в сознание и есть секрет высокой заразности SCRUM.

Острый SCRUM

Фаза острого SCRUM это первые спринты. Обычно первые три-четыре. Течение болезни можно разделить на два сценария:

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

  • Инфекция поразила группу лиц. Они объединяются в команду и болеют палатой.

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

Осложнения возникают при инфицировании кого-то из руководства. В этом случае поражается центральная нервная система компании. Социальный иммунитет уже не может справиться с инфекцией.

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

Второй вариант обречен на успех. Острый SCRUM переходит в хронический. Все испытывают эйфорию. Болеть приятно. Родственники приносят апельсины, которыми больные в палате делятся.

Обратите внимание, что успешная пандемия SCRUM в компании начинается при наличии критической массы носителей инфекции. Это крайне важный фактор для профилактики SCRUM.

Хронический SCRUM

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

Обычно, за этим следует лечение народными средствами. Ставится Jira, confluence, gitlab. В периоды помутнения, внезапно завозится Kanban Кто-то начинает гуглить в Ответы mail.ru и оттуда узнает о покер-планировании. Покер но планирование! Игра увлекает всю палату на следующие пару спринтов.

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

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

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

Системный SCRUM

Особый класс прогрессирующего заболевания. Прогноз крайне неутешительный. Пациенты обречены на счастье.

Системный SCRUM, это внедрение концепции в культуру компании. Все процессы компании оказываются поражены. Руководство не просто тоже болеет, а еще и утверждает, что оно самое больное на свете существо!

Симптомы системного SCRUM:

  1. Вы знаете ради чего болеете;

  2. Не отделяете себя от команды;

  3. Вы читали методологию. Неожиданно, да? И регулярно к ней возвращаетесь;

  4. HR при собеседованиях проводит анализ совместимости ценностей компании с ценностями кандидата, где команда - ключевая ценность;

  5. Компания акцентирует внимание на командообразование;

  6. Есть методология интеграции новых сотрудников в команды.

  7. У вас все получается и вас прет от этого.

Заключение врача

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

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

И прикладывать холодное.

Подробнее..

Epic Scrum Fails предновогодний скрам-стендап

11.12.2020 16:14:18 | Автор: admin
Встретимся 15 декабря и вместе посмеёмся над историями скрам-мастеров, помня, что в каждой шутке есть своя мораль. В программе вредные советы от Сбера, МТС, Альфа-Банка, ОТП и Райффайзенбанка.

Присоединяйтесь к нам!



О чем будем говорить


Что бывает, когда 8 шапок скрам-мастеравстречаются с реальной жизнью!

Наташа Епейкина, Райффайзенбанк

От создателей это не на нашей стороне и в Jira этого не было.

Фейлы скрам-команд, и что можно с этим сделать

Росянок Виталий, МТС

Фейлы, с которыми встречаются все скрам-мастера. Обсудим тривиальные косяки скрам-команд в комичной форме, увидим себя и разберём варианты решений.

Молотки, гвозди и парное программирование

Арсений Кельдышев, Райффайзенбанк

История о нанесении добра и несусветной пользы.

Как перестать волноваться и начать жить СМу?

Екатерина Шевченко, ОТП Банк

На что похожи взаимоотношения СМ и команды? Два кейса из реальной практики.

Сейчас смешно, а раньше было поучительно

Никита Щербаков, Сбер

Важные истории из жизни СМа и команды, над которыми сейчас можно посмеяться.

Самые Большие Ошибки Скрам-мастера

Сергей Макаркин, Альфа-Банк

Как гарантировать провал Agile и привить сотрудникам отвращение к Scrum.

>>> Начнем митап в 19:00 (МСК).
Регистрируйтесь, чтобы получить ссылку на трансляцию: письмо придет вам на почту.

До встречи онлайн!
Подробнее..

Разбор полётов. Уроки и выводы начинающего Scrum-мастера

18.03.2021 12:07:58 | Автор: admin

Источник фото

Уже третий год я внедряю ценности и принципы Agile в жизни команд разработчиков. За плечами работа Scrum-мастером в двух крупных компаниях, опыт удаленного внедрения гибких методологий в совершенно разных отраслях, бесчисленное количество прочитанных книг и посещенных митапов.

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

Итак, какие уроки я извлекла и выводы сделала в первый год работы в роли Scrum-мастера (о которых кратко пунктами изложила в самом конце):

Розовые очки





После двухдневного тренинга по Scrum я была готова сворачивать горы, изменять мир на пути компании к лучшему. Ничто так не вдохновляет, как грамотный коуч и команда единомышленников! Но стоит только начать, как вдруг ты остаёшься один на один со своим фреймворком Scrum. Есть ребята, загруженные собственными задачами, есть привычки и ценности, которые уже сложились в работе команды, есть менеджмент, который по-своему видит процессы, и это не всегда идёт параллельно с ценностями и представлениями Agile. В общем, добро пожаловать в реальный мир.

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

Сопротивление


Безусловно, нововведениям и очевидным грядущим изменениям не очень обрадовались. В моем случае скорее это было смирение с тем, что пришёл ещё кто-то, чтобы управлять и учить: ну ведь и так всё хорошо. Делать нечего пришлось доказывать, что я пришла помогать, и на практике это демонстрировать.

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

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

Задайте себе вопрос: какова цель моего присутствия в этой роли и как я могу помочь своей команде улучшить существующие процессы работы?. Если ответ нашёлся отлично, вперёд к изменениям! Если нет, то стоит понаблюдать ещё.

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

Спешка худший помощник





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

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

Понимание среды


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

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

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

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

Присутствие стратегии


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

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

Чаще всего, приходя в команду, я видела, как ребята проводят ежедневные совещания по 1,5-2 часа, на которых пытаются проработать все вопросы. А это, между прочим, колоссальное количество времени, которое вычитается из рабочих часов и снижает эффективность работ команд. Да и Scrum Guide предполагает на это событие только 15 минут и ни минутой больше.
Как быть: самым правильным подходом, на мой взгляд, является разделение таких активностей и фокусировка на поставленных задачах в рамках целей Sprint.

Отталкиваясь от болей и наиболее частых вопросов, помимо основных событий Scrum (планирование, daily, demo, retro) может формироваться, например, еженедельная исследовательская встреча, обсуждение бэклога идей или же мозговые штурмы для обсуждения углубленных вопросов, как происходит сегодня у нас в ICL Services. Мы видим боль, знаем, как исправить ситуацию и что нужно сделать остаётся лишь обсудить изменение формата работ с менеджментом и командой для достижения наилучшего эффекта.

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

Нехватка технических знаний





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

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

Краткие итоги


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

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

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

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

5. Задайте себе вопрос что мы хотим изменить и почему?, и ответом на него станет четкая цель. А в ответ на вопрос как мы будем это делать? составьте план, который будет понятен и известен руководству еще до начала изменений, т. к. в него могут внестись весомые правки в зависимости от верхнеуровневых целей компании.

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

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

Мой МТС. Продуктовая трансформация

12.04.2021 18:13:34 | Автор: admin
Всем привет! Мы продуктовая команда Мой МТС, занимаемся разработкой основного мобильного приложения компании МТС (iOS/Android) и сайта mts.ru. Месячная аудитория активных пользователей (MAU) на всех платформах свыше 23 млн. пользователей.

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

До трансформации

Погрузимся немного в исторический контекст. Изначально приложение Мой МТС разрабатывала команда внешнего поставщика. В 2016 году мы перевели продукт в In House разработку и начали планомерные работы по совершенствованию кодовой базы, команды и процессов.

На начало 2020 года команда продукта Мой МТС состояла из 63 человек, которые были организованы следующим образом:



Разработка велась по зачаточному Scrum'у с двухнедельными итерациями и основными командными ритуалами. Однако, как заметит внимательный читатель, на схеме отсутствуют scrum master'а у нас это роль, которую выполнял и продолжает выполнять кто-то из членов feature team. Также была в наличии строгая изолированность Владельцев продукта и разработчиков. Мостиком между двумя мирами служили системные аналитики и технический лидер команды. Веб-разработкой полностью занимался подрядчик. Так совпало, что начало активной фазы избавления от внешних зависимостей началось одновременно с трансформацией.

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

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

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


С технической точки зрения у нас имелись следующие вводные, которые хотелось бы обозначить в контексте трансформации:

  • Монолитные решения на всех платформах (iOS, Android, Web)
  • Полное отсутствие UI тестирования
  • Хаотичный процесс проверки pull request'ов без SLA


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

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


Цели трансформации

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

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

  • Общая прозрачность работы команды на всех уровнях понимание процессов и артефактов команды, в широком смысле этого слова, всеми сотрудниками, которым это может быть нужно, начиная с самих членов команды и заканчивая Советом директоров компании.
  • Уменьшение показателя Time-to-Market путем поиска и устранения узких мест в рабочем процессе и изменения подхода к работе в целом.


Достаточно быстро мы поняли, что для себя нам так же нужно определить и понять цели. То есть сократить T2M, чтобы что? повысить прозрачность зачем? и другие подобные вопросы. Начали обсуждать это с CPO, Владельцами продуктов и к тому времени уже прошло несколько месяцев работы в новой парадигме. Так как получилось собрать достаточно много интересной фактуры, мы собрали всю большую команду Мой МТС и рассказали, как же на самом деле команда управления продуктом видит цели и ожидаемые результаты трансформации, какие небольшие победы уже можно отпраздновать, а так же где наоборот стало хуже и что потерялось из фокуса. Вот некоторые выводы, к которым мы пришли после первого такого подхода:

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


С точки зрения целей трансформации, для себя мы определили, что самое главное не цифры и T2M (на начальном этапе так точно), а изменение нашего подхода к работе, мышления, и, как сказал CPO, раскачивание лодки, чтобы понимать, где она протекает. То есть сокращение Time2Market на этот период времени стало для нас не самоцелью, а процессом раскачивания устоявшейся системы с целью поиска узких мест и их разрешения. Звучит странно, но нам это помогло расставить все на свои места. Мы поняли, что:

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


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

Трансформация

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

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

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

Все задачи следующего квартала предварительно обсуждаются, верхнеуровнево декомпозируются, а также оцениваются командами разработки. Одним из открытий наведения порядка в планировании для нас стало понимание, что в квартале 6 Спринтов, один из которых () уходит на тех. долг (сумма 20-ти % в Спринт), второй для тестировщиков команды на релиз (сейчас релиз делается по всему приложению, релизное знамя переходит от команды к команде, но это временное явление, мы почти от этого избавились).

По итогам Квартального планирования мы получаем перечень задач, которые:

  • Обсуждены и согласованы со всеми участниками вне наших команд, например, с другими продуктами, по которым есть зависимости в реализации фичей
  • Обсуждены и предварительно проработаны командой разработки
  • Распределены по Спринтам внутри квартала
  • Презентованы всем заинтересованным лицам. В конце квартального планирования мы рассказываем о своих планах, зависимостях и рисках на встрече, где помимо остальных продуктов и команд присутствуют топ-менеджеры. Синхронизация очень масштабная в последний раз только на B2C направление было 44 продукта/платформы.

После окончания процесса Квартального планирования мы продолжаем регулярную синхронизацию по задачам на PO sync (еженедельная встреча Product Owner'ов и Chief Product Owner'а, технических лидеров, скрам-мастеров). Там же обсуждаем прогресс в достижении целей: если есть новые вводные или вскрылись не найденные ранее риски у нас есть возможность узнать об этом и повлиять как можно раньше.

Помимо Квартального планирования и PO sync, у нас в Мой МТС прижилась традиция проведения ежедневных чек-инов команды трансформации. В эту команду входят: CPO, технические лидеры, скрам-мастера. Иногда туда приглашаем и других участников, если того требует задача. Как уже говорилось, мы встречаемся этим составом ежедневно в конце рабочего дня, на 15-45 минут, обсуждаем и решаем вопросы, связанные с кадровыми изменениями, отзывами пользователей, новыми инициативами (например, перезапуск Discovery процесса, но об этом в следующих статьях), инициативами от членов команды и т.д. Крайне редко на чек-инах рассматриваются проблемы какой-то конкретной фичи, так как это более низкоуровневая повестка.

В силу размера компании нам не удалось внедрить новый подход везде и сразу, что привело к рассинхронизации при запуске нового механизма планирования у разных направления B2C, B2B и IT платформы.

Если говорить о структуре команды, то после трансформации продуктовая команда Мой МТС стала выглядеть следующим образом:



Разумеется, переход к новой структуре был поэтапным, нужно было нанять большое количество сотрудников и постепенно формировать новые команды. К сожалению, бурный рост не мог не сказаться на текучке кадров, и отток в 2020 году был самым большим за последние 4 года. Однако если рассмотреть последние месяцы 2020, когда найм по большей части был уже завершен, то ситуация заметно выправилась. Если говорить о цифрах, то в 2020 году текучка составила 30%, а в предыдущие годы (2018-2019) держалась на уровне 18%.

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

  • Основным изменением стал переход на юниты обособленные scrum команды, состоящие из технических специалистов, дизайнера и владельца продукта.
    Юниты собираются вокруг направлений бизнеса (например, фиксированная связь, финтех и так далее). В теории, подобная трансформация должна была привести к большей вовлеченности всех участников команды в специфику своих направлений и более качественной проработке продуктовых гипотез.
  • В команде продукта появились выделенные scrum-мастера. Они выполняют важные функции:
    • коррекция процесса трансформации
    • консультирование по вопросам Agile
    • связующую функцию с корпоративным центром продуктовой культуры.
  • Выделенная команда автоматизации UI тестирования.
    Значительный рост количества команд привел быстрому развитию приложения, вместе с которым также стремительно увеличивается количество тест-кейсов в регрессе. На данный момент автоматизировано 25% основных сценариев.
  • Мы начали активно работать в направлении перехода на In House разработку WEB.
    Процесс оказался значительно сложнее, чем в случае с мобильным приложением, в силу исторического и юридического наследия. Также ожидания бизнеса не позволили замедлить или остановить разработку нового функционала.
  • В 2021 году планируем провести эксперимент по созданию гибридных команд app+web.


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

Результаты

Если формально подводить итоги трансформации, то поставленные цели были достигнуты:
1. Процесс стал прозрачным для всех
2. Time-to-market сокращен в 1,5 раза

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

  • Излишняя прозрачность может быть вредной
    Применимо в случае, например, когда у стейкхолдеров есть некий технический бэкграунд (или они так думают) и они пытаются, экстраполируя свой старый опыт, активно влиять на рабочие процессы команды.Стоит отметить, что прозрачность планирования в полной мере не была достигнута. Квартальное планирование сейчас запущено параллельно на различных срезах (B2C, B2B, платформы), хотя остро стоит потребность в синхронизации.
  • Абсолютные значения показателей в вакууме
    Нам, конечно, удалось уменьшить time-to-market, но параллельно с трансформацией активно улучшались и подходы к работе владельцев продукта. Это привело к уменьшению среднего размера задачи и ускорило скорость доставки инкремента до пользователя. Даже не смотря на оговорки, подобный результат для нас очень ценен: отказ от больших и толстых задач, которые становятся неактуальными за время доставки до пользователей, является огромным плюсом. Также за прошедший год был сделан очень мощный рывок в работе с техническим долгом. Изолированные команды требуют по возможности изолированных песочниц в коде, поэтому модульность приложения стала основным техническим вектором для нас наравне с автоматизацией тестирования.


Новые проблемы

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

Также раньше мы очень большое внимание уделяли детальной проработке всех требований к фиче до старта разработки. Основные недостатки такого подхода это сужение пропускной способности всей команды и слишком тепличные условия для разработчиков и тестировщиков. В юнитах уже на первых порах стало видно, что старый подход к ТЗ не работает и нужно что-то менять аналитик не успевал готовить проработанные задачи. Для решения этой проблемы мы разделили ТЗ на две части must have для старта разработки и всё остальное. Этот подход несколько снял напряжение, но не закрыл все вопросы, поэтому дальнейшие проверки различных гипотез дело времени.

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

Планы

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

  • Вся разработка должна быть In House. На наш взгляд, это аксиома, аутсорсинг всегда непрозрачно и почти всегда неуправляемо.
  • Техническое развитие продукта
    • автоматические UI тесты для снятия лишней нагрузки с unit'ов при подготовке релизов
    • единый интеграционный backend для снижения затрат на подключения к другим системам ландшафта компании
    • дальнейшее развитие модульности приложения для упрощения работы структуры в целом. Для ускорения и стабилизации этого процесса мы планируем создать выделенную команду развития платформ.
  • Автоматизация сбора различных метрик работы unit'ов и продуктовой команды целиком.
  • Создание кросс-команды, в которую будет входить полный спектр специалистов для реализации функционала в app и web части нашего продукта.


Авторы Артем Андреев, Наталья Егорова, Алексей Кретов
Подробнее..

Встречи планирования разработки в пандемию, или Как устроить электро PIP

15.04.2021 14:13:15 | Автор: admin
Сегодня мне хотелось бы с помощью моих коллег Agile-коучей Ани Родионовой, Макса Зотова и владельца продукта в Трайбе Розничное взыскание и урегулирование Свята Божухина рассказать о практике применения интересного инструмента. Итак, речь пойдёт о Program Increment Planning Meeting aka PI Planning.

Это метод планирования из SAFe (Scaled Agile Framework) гибкого фреймворка для крупных компаний. Ну, знаете, это когда люди стоят у стены, оклеенной стикерами, лепят всякие ниточки от одного стикера к другому, но при этом в городе не орудует маньяк.

Ниже пример места встречи одной из команд для PI в Сбере (обратите внимание на ту самую стену на заднем плане):

image

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

С чего началось


В марте 2020 года бОльшая часть команд перешла на дистанционный формат работы. Со встречами по планированию нужно было что-то делать. С технической точки зрения у нас были Zoom и Confluence, но организационно нужно было немного докрутить.

Вот так выглядит SAFe, и скромную часть в нём занимает PI:

image

Вот что должны сделать разные участники, чтобы планирование прошло успешно:

image

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

Scrum-мастерам поручили подготовить все шаблоны флипов (флипчартов). В онлайне они трансформировались в таблички на Confluence в специальном пространстве для совместной работы.

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

Группа фасилитаторов следила за тем, чтобы все шаблоны в Confluence были подготовлены и всё логистически готово.

Мы фокусировались на основных задачах и по возможности распределяли их. Must have-задачи это задачи, например, по изменению законодательства, которое в пандемию достаточно часто менялось, и к этому никак нельзя быть готовыми, но их точно надо сделать. У нас как у банка нет ни малейшей возможности не сделать этого в принципе.

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

Сама история почти не поменялась: если раньше были физические флипчарты, то теперь они стали виртуальными.

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

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

image

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

Потом риски. Если команда видит, что у неё, возможно, будут проблемы при реализации какой-то задачи, то она его обозначает, и потом уже мы решали, кто с этим работает и как.

image

И дальше распределение по спринтам. Мы смотрели на оптимистичность, пессимистичность и реалистичность команд и приводили их к чему-то единому, равному. Кто был не нагружен нагружали, а кто был перегружен чуть помогали освободить их бэклог.

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

Процесс


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

Дальше идёт работа команд:

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

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

В электронном виде стало удобнее: появилась чёткая структура, добавилась лучшая сохранность артефактов. Каждая задача ставится в Confluence.

В среднем из запланированного делается по факту 7080 %. Это очень качественный показатель.

Инвестиция в будущее


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

Вот так, если вкратце про PI Planning. Если хотите больше подробностей, то можно посмотреть выступление коллег тут.
Подробнее..

Проводим ретроспективы для распределенных команд (и как Trello в этом помогает)

19.04.2021 10:09:21 | Автор: admin

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

Почему Trello

Я пользовался большим количеством инструментов, из которых можно выделить основные: Miro - как интерактивный флипчарт, с которым может взаимодействовать вся командa; Google Docs с секциями помапанными на стадии ретроспектив; Confluence (так как все мои проекты пронзены Atlassian-стеком); а также, порой, Jira (вау, это была достаточно плохая идея)!

Я думаю что все пытались нащупать тот самый инструмент, который можно применить фактически в любой области!

И вот я бы выделил основными критериями для проведения Ретро и собирания фидбека о Демо в подобных инструментах:

1. Насколько хорошо оно работает на уровне объектов (во время обсуждений). -> в идеале тут хотелось бы видеть карточки (все таки мы в физическом мире работаем со стикерами) :)

2. Быстрая и эффективная работа с карточками / объектами

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

4. Перетасовка / изменение порядка карточек / объектов / айтемов

5. Как можно меньшее время, затраченное на следующую последовательность действий: создание секции (списка) -> добавление в него объектов / карточек -> тегирование / подсветка айтемов (членами команды) -> добавление комментария к айтему.

Miro

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

Google Docs

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

В этом плане, знаете, даже google sheets казалось бы удобно использовать, как инструмент более подходящий для нашей аналогии двухмерной-классической-ретро-доски (ну как двухмерной, скорее именно с точки зрения того, что у нас есть некие секции с контентом для хорошо/не оч/ улучшить). Но и тут нас поджидает неудобство - drag-n-drop для айтемов, и их линкование друг с другом работает ужасно. Я еще пробовал в свое время google slides, с подходом слайд-для-секции (например перечислить все те великие свершения, в которые мы шмогли с прошлого спринта) - но в итоге менеджить это было сложно, ввиду тяжеловесности решения, ну и на одном таком канвасе могло одновременно ну человека два работать может, не больше. Ну и подсвечивать айтемы там конечно можно, но оно для того не очень приспособлено.

Confluence

Ну вот же confluence, там же целый шаблон для ретро есть! Скажете вы. И будете правы!

Но хорош этот шаблон для документирования/стенографирования, для журнала принятия решений. А нам это в ретро не нужно! Нам нужна живая дискуссия где народ таскает карточки по колонкам, клонирует, обсуждает, помечает!

Более того, Atlassian обычно старается сделать confluence неким легковестным решением, если вас кормят всем их стеком. Но по простоте коллаборации там до gDocs как до луны. Возвращаясь к нашему подходу (ищем блочную структуру для карточек) - confluence неудобен. А еще - нестабилен: с потерей контента и его перезатиранием в режиме коллаборации, отвалом соединения и последующими невозможностями сохранить.

Trello

Ну вот а когда мы подходим к Trello - оно просто поддерживает карточки. И голосовалку для этих карточек с помощью power-up'ов (очень просто). Или через тегирование этого дела цветами (что работает просто и быстро).

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

Короче говоря: trello это самый простой в использовании аналог флипчарта со стикерами :)

Подготовка к самой ретроспективе, и ее начало

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

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

- Общего понимания того, что своё лицо шарить нужно. Поэтому ретро без включенных камер - это как ретро без включения в процесс

- Соединение должно быть отличное! Мы не хотим страдать из-за непонимания (особенно в мультиязычных командах :), и нам не нужны лаги

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

Сама Ретроспектива

В зависимости от зрелости и атмосферы в команде можно использовать Ice Breakers (чтобы настроить на легкое взаимодействие и убрать ощущение обязаловки). Ну и не забудьте проверить как команда чувствует себя после спринта (проверка температуры) - не ждите высокой оценки как данности.

Запланированные улучшения с прошлого спринта

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

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

Это позволяет команде добавить прозрачности в её процессах, а также задать тон саморефлексии для самого события ретроспективы.

Иногда эта стадия может затянуться (планировали улучшение - не смогли достичь - начинаем погружаться слишком сильно в детали почему). Как фасилитатор, ваша задача помочь команде найти продуктивный путь для выявления настоящей причины в достаточно короткий срок (у нас ведь есть таймбокс). Поэтому мы с вами планируем один обязательный пункт улучшения, два уже имеют риск затянуть начало ретроспективы. Также старайтесь просто запарковать это обсуждение на полее поздние части ретроспективы - если нужно действительно разобраться. А возможно это даже не относится к ретроспективе как к событию, а надо проводить RCA / Post-Mortem?

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

Цели спринта и метрики

Цели Спринта

Цели спринта это ваш индикатор прозрачности. Достигли ли вы их или нет. При правильном использовании, команда постоянно ориентируется на цели спринта во время каждого события, и поэтому сама должна отлично понимать как она с этой целью справилась. Я считаю что даже если цель обсуждена на Sprint Review, все равно хорошо бы еще раз подсветить причины удачи или неудачи достижения (а это уже непосредственно относится к процессу работы, а значит и к ретроспективе).

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

Метрики

Метрики спринта важны и как внутренний-SLA для команды, и как общий индикатор, который в комплексе помогает команде понять динамику.

Обычно команда навскидку придумает с десяток факторов, которые для неё препятствия чтоб быть более эффективной. Если поддерживать ведение такой дискуссии в правильном русле (читай, фасилитировать), и помогать команде наводящими вопросами (читай, коучить), ребята сами соорудят путь к улучшению и как его измерять. Главное чтобы был запрос на улучшение, и была понята сама проблема (нафига оно нам вообще). Еще нюансик: не рассматривайте метрики отдельно друг от друга, и стройте связи между опережающими индикаторами (гипотезами) и запаздывающими индикаторами (результатом). Например, действительно ли увеличение покрытия кода тестами увеличивает уверенность в том, что на проде качество улучшается?

Стандарные метрики, которые я стараюсь использовать:

- Lead Time (время от запроса клиента до поставки)

- Cycle Time (время от начала работы над задачей до поставки). Когда объяснишь на примере донесения ценности до пользователя - как устроен весь пайплайн и где затыки, ребята сами будут мотивированы следить за этими метриками (если, конечно, они у вас общаются с клиентами постоянно),

- Время в Code Review (атож, сколько задача висит и сколько ее проверяют),

- Количество раз тикет был переоткрыт (помогает вместе с определением Definition of Ready),

- Mean Time to Recovery (инцидент-метрика для понимания среднего времени на устранение),

- Bug Escape Rate (сколько багов мы не поймали на тестовых стендах, но поймали после релиза на прод).

В целом все зависит от ситуации, но я считаю Cycle Time и Lead Time тем самым минимумом для всех. Cycle Time в целом дает вам понимание прозрачности и предсказуемости.

Активность на выявление дельты улучшения ~ 'Хорошо-Плохо-Улучшения

Единственное, что как и в локализованных командах, люди в распределенных командах должны "вешать стикеры" с рефлексией заранее, чтоб у всех был контекст. Если таких "стикеров" много - можно организовать голосование, дабы сузить круг обсуждаемого. Не нужно ждать начала самого ретро для сбора обратной связи. Опять же, роль фасилитатора заключается в подсветке конфликтов и проблем когда команда непосредственно с проблемами этими сталкивается. Можно и нужно помогать команде корректно и ёмко отражать саму суть проблемы. Подсвечивать можно по-разному, например отражая что слышишь от команды (я правильно понимаю, что ты имеешь ввиду ....), или беря на себя роль человека, не знакомого с контекстом задачи/проблемы, как-то еще. Самое главное, чтобы команда была вовлечена в процесс инспекции во время самого спринта или каденции, а не только во время ретро.

Собираем фидбек с команды о том, как прошла ретроспектива

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

Референсы и полезности

У Бена Линдерса (Ben Linders) есть хорошая трелло-доска, в которой люди краудсорсят ретроспективные техники для распределенных команд в трелло.

  • https://www.benlinders.com/news/trello-board-retrospective-techniques/ Это, наверное, и разговоры с самим Беном, были огромным подспорьем, чтобы написать этот пост.


Подробнее..

Гайд по сертификациям. Часть 1. Agile

24.05.2021 08:13:54 | Автор: admin

По Agile доступно огромное количество курсов. Кроме специализированных курсов по проектному управлению есть ещё сертификации.

Зачем получать сертификаты по проектному управлению? Существуют несколько причин:

  • Систематизировать ранее полученные знания.

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

  • Проверить свои силы. Сертификация даст ответ насколько ты хорош.

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

  • Повышение. Сертификаты повышают вашу стоимость в глазах работодателя.

Сертификаты можно разделить на три типа:

Перед подготовкой к сертификации вам нужно ответить для себя на несколько вопросов:

  1. Для чего вам нужен сертификат?

  2. Какую методологию/фреймворк вы используете или хотите использовать?

  3. Какая у вас текущая или желаемая роль в компании?

ICAgile

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

Карта треков
Agile DeliveryAgile DeliveryBusiness AgilityBusiness Agility

Agile Delivery и Business Agility.

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

В каждом треке есть 2 уровня. Прошёл обучение по каждому уровню получаешь статус по всему треку.

Обучение на каждом уровне длится в течение 3-х дней, много практики.

Сертификат

Сертификат пришлют в течение 4 недель после курса. Сертификат выдаётся бессрочно, продлевать не нужно.

Пример сертификата

Проверить сертификат на действительность можно по ссылке.

Стоимость обучения варьируется в зависимости от трека от 35 до 90 тысяч рублей. Стоимость курса включает выдачу сертификата. Ничего доплачивать не нужно.

Из плюсов:

  • Международный сертификат.

  • Разнообразие, можно прослушать курсы по нескольким направлениям: Agile, DevOps, опер блок.

  • Сертификат выдаётся бессрочно.

Из минусов:

  • Отсутствует экзамен. Человек, который старался, слушал курс, и человек, который просто присутствовал, равны.

PMI

PMI. Одна из самых сложных сертификаций. На экзамене понадобятся знания широкого круга методологий и фреймворков.

Треков нет.

Сертификат

Это одна из немногих сертификаций, до которой ещё необходимо допуститься.

Для получения доступа к экзамену потребуется:

  • Не менее 12 месяцев опыта управления проектами за последние 5 лет;

  • Не менее 8 месяцев управления Agile проектами за последние 3 года;

  • 21 час обучения на любом курсе Agile (не обязательно аккредитованом).

Описание требований для доступа к экзамену. Курсов по подготовке к экзамену не так много.

Нужно быть готовым подтвердить информацию в анкете. Ваша заявка может попасть под аудит.

Сам экзамен состоит из 120 вопросов, большая часть вопросов ситуационные, основаны на практических кейсах. На экзамен отводится 3 часа. Критерий успешной сдачи не раскрывается, но, по слухам, составляет примерно 70 правильных ответов. Русский язык на экзамене пока ещё недоступен придётся сдавать на английском.

Пример сертификата

Проверить сертификат на действительность можно по ссылке.

Сертификат необходимо продлевать каждые 3 года. Для этого достаточно пройти 30 часов обучения на сертифицированных курсах. Подробная информация по ссылке.

Стоимость аккредитованных курсов от 1 до 200 тысяч рублей. Зависит от количества часов, страны и жадности провайдера курсов.

Из плюсов:

  • Одна из самых именитых компаний.

  • Необходимо сдать экзамен.

Из минусов:

  • Одна из самых сложных сертификаций.

  • Необходимо допуститься до экзамена.

  • Высокая стоимость экзамена (495 USD).

  • Экзамен доступен только на английском языке.

  • Нужно продлевать сертификат.

IAPM

IAPM. Малоизвестный провайдер IAMP. Сертификация основана на стандарте AgilePM Guide 2.0. Стандарт включает инструменты и техники из нескольких фреймворков: Agile, Scrum, Kanban и других.

Ссылка на сам стандарт.

Карта треков

К сертификации доступно 4 уровня: Certified Junior Agile Project Manager, Certified Agile Project Manager, Certified Senior Agile Project Manager, и Certified International Project Manager.

Сертификат

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

Пример сертификата

Проверить сертификат на действительность можно только отправив запрос на почту support@iapm.net.

Экзамен состоит из 120 вопросов, на которые будет отведено 80 минут. Для успешной сдачи необходимо правильно ответить на 78 вопросов. Более подробно по ссылке.

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

Из плюсов:

  • Международный сертификат.

  • Необходимо сдать экзамен.

  • Не нужно продлевать сертификат.

Из минусов:

  • Малоизвестный провайдер в РФ.

  • Экзамен доступен только на английском языке.

Scrum Alliance

Scrum Alliance. Компания была основана в 2002 году авторами The Scrum guide Джеффом Сазерлендом и Кеном Швабером. Сертификат от Scrum Alliance один из двух самых известных в мире сертифицирующих организаций по Scrum. О второй позже.

Карта треков

В Scrum Alliance есть три трека для сертификации по ролям: Scrum master, Product owner, Developer. У всех трёх ролей есть три ступени Certified, Advanced и Professional.

Также Scrum Alliance предлагает еще 4 дополнительных трека Agile Leadership, Team Coach, Enterprise Coach и Trainer.

Сертификат

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

Курс длится 2 дня. После прохождения обучения у вас будет несколько попыток сдать экзамен на официальном сайте Scrum Alliance.

Пример сертификата

Проверить сертификат на действительность можно по ссылке.

Экзамен состоит из 50 вопросов, на решение которых будет отведён 1 час. Критерий прохождения - 37 правильных ответов.

После прохождения обучения вам будет доступно несколько бесплатных попыток для сдачи экзамена. Экзамен доступен на официальном сайте scrum alliance и только на английском языке.

Стоимость обучения составляет порядка 65 тысяч рублей за 1 ступень, включая взнос за экзамен и 2 попытки, далее $25 за каждую попытку.

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

Сертификацию нужно продлевать каждые 2 года. Для продления необходимо набрать достаточное количество баллов SEUs на аккредитованных курсах плюс заплатить взнос. К примеру, для продления самой популярной сертификации Product owner и Scrum Master потребуется 30 часов курсов и оплата взноса в размере 175 долларов.

Подробная информация о продлении по ссылке.

Из плюсов:

  • Всемирно известная компания.

  • Необходимо сдать экзамен.

Из минусов:

  • Экзамен доступен только на английском языке.

  • Нужно продлевать сертификат.

Scrum.org

Scrum.org. Вторая всемирноизвестная сертификация по Scrum. Компания Scrum.org была основана в 2009 году Кеном Швабером.

Карта треков

Для сертификации доступно8 треков, 3 из которых организованны по ролям: Scrum Master, Product Owner и Developer. Остальные пять Scaled Professional Scrum, Professional Scrum with Kanban, Professional Agile Leadership, Professional Agile Leadership-EBM, Professional Scrum with User experience.

Сертификат

После прохождения обучения вам будет доступно несколько бесплатных попыток для сдачи экзамена. Экзамен можно сдать на официальном сайте scrum.org и только на английском языке.

Пример сертификата

Проверить сертификат можно по ссылке.

Количество вопросов и стоимость сертификации отличается от трека к треку.

На примере сертификации Scrum Master.

Количество вопросов

Критерий сдачи

Продолжительность экзамена

Стоимость

PSM1

80 вопросов

85%

60 минут

150 USD

PSM2

30 вопросов

85%

90 минут

250 USD

PSM3

30 вопросов + эссе

85%

150 минут

500 USD

Сдать экзамен и получить сертификат можно и без прохождения курсов.

Для получения любой ступени не требуется наличие предыдущей. Вы можете сразу получить сертификацию PSM3, минуя предыдущие ступени.

Стоимость обучения составляет порядка 50-80 тысяч рублей за 1 ступень, включая взнос за экзамен и 2 попытки.

На сайте scrum.org доступно бесплатное тестирование, которое может пройти любой желающий. Сертификата не дадут, но можно понять уровень подготовки.

Из плюсов:

  • Всемирно известная компания.

  • Необходимо сдать экзамен.

  • Сертификат не нужно продлевать.

Из минусов:

  • Экзамен доступен только на английском языке.

Kanban University

Kanban University. Сертификация проходит аналогично ICAgile, прослушал курс получи сертификат. Для сертификации доступно 5 треков.

Карта треков

Team Kanban Practitioner это однодневный курс для тех, кто хочет познакомиться с Kanban.

Чтобы получить Kanban Management Professionalнеобходимо пройти обе ступени KMP1 и KMP2.

Треки Management, Coaching, Consultant и Trainer подойдут для тех, кто планирует стать тренером или коучем по Kanban.

Сертификат

Пример сертификата

Проверить сертификат можно по ссылке.

Обучение проходит в течении 1-2 дней, зависит от трека. Стоимость составляет порядка 25-50 тысяч рублей за одну ступень.

Из плюсов:

  • Международный сертификат.

  • Сертификат выдаётся бессрочно.

Из минусов:

  • Отсутствует экзамен.

Перечень провайдеров

Таблица с гиперссылками

Фреймворки/

методологии/ итд

Основные роли

Сертифицированные тренинги

Стоимость, руб

Нужно ли продлять сертификат

Язык сертификации

ICAgile

Agile

DevOps

Product manager

Project manager

Team role

Coach

OnAgileAcademy

AgileLab

ScrumTrek

ProductLab

35-90 тыс руб

нет

Рус

PMI

Agile

Project manager

Udemy

PMI

От 1 тыс руб

+ 475 USD за экзамен

175 USD

30 PDUs

Англ

IAPM

Agile

Project manager

IAPM

По запросу

нет

Англ

Scrum Alliance

Scrum

Scrum master

Product owner

Developer

Trainer

Coach

Skillbox

ScrumTrek

ThinkAgile

65 тыс руб

50-250 USD

10-40 SEUs

Англ

Scrum.org

Scrum

Kanban

Scrum master

Product owner

Developer

Coach

Agile.live

50-80 тыс руб (включая плату за экзамен)

Нет

Англ

kanban.university

Kanban

Team member

Manager

Consultant

Trainer

Coach

ScrumTrek

25-50 тыс руб

нет

Рус


Нет плохих или хороших сертификаций по проектному управлению. Сертификаты востребованы у работодателей т.к. позволяют отсеять людей при найме.

Кроме наличия необходимых знаний международный сертификат показывает работодателю что:

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

  • Ты стремишься развиваться и получать новые знания.

  • Ты знаешь теорию достаточно, чтобы пройти все испытания.

Если есть опыт в получении сертификаций и желание поделиться им, напишите, пожалуйста, в ЛС.

А если я упустил какую-либо информацию, напиши в комментарии. Я обязательно её добавлю.

Подробнее..

Recovery mode PSM I от Scrum.org. Личный опыт получения сертификата

24.05.2021 20:06:11 | Автор: admin

Итак, я получил сертификат Professional Scrum Master I от Scrum.org. По сути, это демонстрация того, что за Скрам я знаю, и могу с ним работать. И даже немного других учить.

Выдается онлайн, после оплаты 150 долларов США и прохождения теста из 80 вопросов. Положительным результатом считаются 85% правильных ответов или в абсолютном количестве 68. Есть право на 12 ошибок. Время 60 минут.

В целом, по Скраму есть две популярные международные сертификации: PSM и CSM. Вторая расшифровывается как Certified Scrum Master и выдается Scrum Alliance.

PSM считается сложнее - вопросов больше, проходной балл выше, есть лимит по времени - в общем нормальный тест. При этом для CSM обязательно нужно посетить курс под 1к долларов стоимостью. Отличный бизнес. Зато тест на 35 вопросов, можно прерваться, да и никто не гонит - хоть весь день его делай. Проходной балл 68%. Подробнее можно найти погуглив, есть отличные статьи от тех кто обладает обеими сертификатами.

Прелесть PSM I же в том что курсов не нужно - оплатил, и тебе дают одну попытку. Технически это так:
1) Регистрируешься на Scrum.org.
2) Заказываешь и оплачиваешь сертификацию - в моем случае молдавская карта отлично сработала(правда потом её временно заблокировали за странную операцию, но разблочили в итоге).
3) Получаешь на почту пароль.
4) Вводишь на сайте и можешь проходить тест. Пароль бессрочный, но одноразовый.

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

Вопрос как правило на выбор одного, двух или трех правильных или наоборот ложных утверждений. Есть еще True/False.

У меня ушло чуть более получаса на это всё, и в итоге я сделал 9 ошибок, 88.8% верных ответов. И красивый серт.

Подготовка

К тесту подошел я уже практикуя Скрам (или пытаясь) - несколько лет. Основы знал хорошо, гайд читал, а когда вышел новый - был повод еще раз подробно изучить.С 9 января 2021 все тесты основаны уже на новой версии. Сразу скажу что были каверзные вопросы основаные на разнице с предыдущей редакцией

Скрам гайд в итоге и был моим ключевым материалом - 13 страниц при должной усидчивости можно и наизусть заучить.Мое личное мнение - он проще и понятней чем был в старой версии.
Спойлер: но вызубрить не поможет )

Ключевой момент - понять схему и философию. И это несложно - документ структурирован, логичен, и объясняет всё что предлагает.

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

В качестве тренировки я проходил открытые тесты на том же Scrum.org - 30 вопросов рандомно выбранные из пула, в конце показывают где ошибся и объясняют - что полезно.

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

Отмечу, что ни одной книги по Cкраму я так и не прочел.

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

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

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

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

Тест

И вот этот день настал - я сел за тест. Судя по скорости прохождения тренировочных (рекорд 6 минут на 30 вопросов) - я рассчитывал закончить менее чем за час.

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

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

Наблюдение номер раз.Скрам это во многом про разработку софта, но не только. И если вы видите что-то актуальное только для софта - это неверные варианты. В гайде если внимательно читать - нет ни слова про программирование, тестирование, девопс. А раз нету - то и не трогайте их.

Наблюдение два.Роли в Скраме три - Скрам Мастер, Продакт Оунер и Разработчики, про остальных там положений нет. Максимум упоминаются стейкхолдеры. То есть сразу когда встречаются тестеры, деливери менеджеры, прожект менеджеры, СЕО - это намек на ошибочные варианты. Потому как Скрам универсален, а роли в каждой компании распределены и именуются по своему. Исходите из тех, что четко описаны в гайде - не ошибетесь.

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

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

Пример: может/должен. Продакт Оунер должен присутствовать на дэйли скраме. Верно или нет? Ответ в P.S.

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

Тест занял чуть более получаса. Вопросы - от 2 секунд до минуты на каждый. Самые сложные на мой взгляд были из разряда "Тебя назначили Скрам Мастером.." и дальше ряд условий - что ты сделаешь? Надо применять философию на практике.

В заключениипро важность сертификации: на рынке труда зачастую работает презумпция незнания. То есть вы можете (и многие так и делают) - рассказывать о себе все что угодно. Что вы знаете Скрам, Канбан, Лин и Экстремальную разработку. Но пока не покажете доказательства - всё это лишь слова. Сертификат это как раз бумажка с которой вы человек, даже в чем-то мастер )

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

В общем такой был мой опыт. Если у кого есть еще вопросы - приглашаю в комменты.

P.S. Не должен. Это ивент для разработчиков, для ПО - опционально. Хотя у нас по моему у всех всегда присутствует вся честная компания включая СМ и ПО. Никто не верит что разработчики сами справятся )

Подробнее..

Scrum Community Meetup 1102

09.02.2021 16:13:11 | Автор: admin

Нельзя просто так взять и взрастить своих скрам-мастеровесть очень много нюансов, которые стоит учесть. Об этом поговорим на онлайн-митапе со спикерами QIWI, Газпромбанка и Райффайзенбанка.

О чем поговорим

2 провала, 1 успех

Антон Бевзюк, Райффайзенбанк

Как мы запускали Scrum Bootcamp и ProScrum в 2020. Я расскажу, как мы дважды НЕ запустили Scrum Bootcamp в 2020, какие уроки из этого извлекли и почему сменили фокус на внутреннее обучение и запустили курс ProScrum.

Наталья Стрельникова, Райффайзенбанк
Адженда скоро появится, ждем подробностей :)

Путь Scrum-джедая

Максим Гапонов, QIWI

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

какие стадии развития Scrum-мастера мы выделили;

какие есть супер-способности и ловушки у каждой стадии;

как понимание этого пути помогает нам подбирать способы и форматы поддержки развития Scrum-мастера.

Scrum master customs

Андрей Редин, Газпромбанк

Я расскажу про развитие скрам-мастера на уровне ШУ, ХА и РИ. Как найти баланс между массовым и индивидуальным подходом.

>>> Активничаем с сообществом в Telegram: присоединяйтесь к Scrum Community @ Raiffeisenbank!

Начнем митап в 19:00 (мск).
Регистрируйтесь, чтобы получить ссылку на трансляцию: письмо придет вам на почту.

До встречи онлайн!

Подробнее..

Start Up Опыт и предпосылки заморозки в крупной IT-компании

18.03.2021 18:13:59 | Автор: admin

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

Итоги стартапа

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

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

  • Продуктовые команды успешно выпустили 20 версий на продуктивную среду клиенту;

  • Продуктовые команды успешно выпустили 240 новых фич клиенту;

  • Продуктовые команды эффективно использовали SCRUM в контексте ценностей, ролей, артефактов и ритуалов;

  • Продуктовые команды вышли на свое стабильное значение velocity равное 35 стори поинтов для двухнедельного спринта;

  • Текучка кадров составила 5%, и то это были два разработчика, которых перехантили обратно компании из которых они пришли;

  • Обработали 600 обращений непосредственно от пользователей продуктов;

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

В разрезе добавочной стоимости запуск стартапа обеспечил следующее:

  • вывод конкурентного решения на рынок умной поддержки;

  • инновационность продуктового решения;

  • создание производственной бизнес единицы;

  • создание и развитие трех продуктовых команд с 0;

  • увеличение капитализации материнской компании на стоимость созданного производства;

Предпосылки заморозки стартапа

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

Клиентская база

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

  • расширение своей клиентской базы в разрезе рынков b2b, b2c;

  • распределение функции управления клиентом в продуктовые команды;

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

Маркетинговые каналы

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

  • участие в профильных семинар и конференциях;

  • ведение продуктовых страничек на популярных IT ресурсах;

  • создание и развитие бренда;

  • создание вебсайта продуктов;

  • SMM оптимизация;

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

Отсутствие фокуса на продуктовой цели

Первые 8 спринтов отсутствовал фокус на целях, которые должны быть достигнуты в рамках доставки продукта. В основном клиент фокусировался на UX/UI элементах и на мелочах, которые приходилось переделывать из раза в раз. Потом получилось сдвинуть фокус восприятия в сторону цели продукта, при достижении которой, бизнес клиента трансформируется, добавляя новые возможности для пользователей. Можно выделить следующие точки роста для компании с позиции формирования фокуса у клиента на продуктовых целях:

  • создание культуры продуктовых целей;

  • обучение и тренинг клиента;

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

Контрактная модель

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

  • переход на модель выпуска лицензий;

  • переход на модель подписки (PaaS);

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

Добавочная ценность продуктовой команды

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

  • присутствуют все необходимые компетенции для выпуска инкремента продукта;

  • есть понимание своих слабых и сильных стороны, а также их влияния на достижение цели;

  • наличие микроклимата бизнес внутри бизнеса;

  • ясная и понятная зона ответственности в разрезе продуктового портфолио;

  • простота в планировании выпуска инкремента продукта;

  • непрерывное развитие коллективного разума, который находит отображение в продукте;

Для трансформации группы людей в настоящую команду, необходимо время, которое в свою очередь выражается в затратах. Данные затраты являются частью инвестиций для запуска разработки продукта и вывода его в качестве MVP на рынок. Затрачиваемое время на выпуск MVP можно принять в первом приближении за критерий окончательного формирования команды. Соответственно, рассмотрим следующие гипотезы в части распределение затрат на запуск стартапа:

  1. 70% на формирование команды, 30% на создание продукта при условии, что члены команды не знают, как работать по SCRUM и до этого не работали друг с другом; При данной гипотезе, материнская компания несет повышенные затраты на запуск стартапа, так необходимо запускать с 0 все необходимые механизмы. Данная гипотеза наиболее распространена для компаний с матричной структурой функциональных подразделений.

  2. 40% на формирование команды, 60% на создание продукта при условии, что члены команды знают, как работать по SCRUM, но до этого не работали друг с другом; Здесь достигается определенный паритет затрат между формирование команды и разработки непосредственно продуктов. Данная гипотеза может более апробирована в компаниях, где развита производственная культура гибкой разработки ПО;

  3. 20% на формирование команды, 80% на создание продукта при условии, что члены команды знают, как работать по SCRUM, и большая часть участников работали друг с другом в команде. Данная модель свойственна компаниям с ярко выраженным продуктовым подходом, где ротация происходим целыми командами.

Соответственно, возвращаясь к теме статьи о специфике процесса заморозки стартапа, заморозка должна происходить безболезненно как для сотрудника, так и для бизнеса. Фрустрация сотрудника должны быть сведена к минимуму, и компания должна помогать адаптироваться к новой реальности за рамками стартапа. Бизнес в свою очередь, потенциально может сократить затраты на запуск нового стартапа на 50 60% от стоимости MVP за счет сформированной продуктовой команды.

Инспекция и адаптация

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

Подробнее..

Recovery mode SCRUM Понимание и применение фреймворка

21.04.2021 22:10:18 | Автор: admin

После заморозки стартапа (более подробно можно ознакомиться в статье) компания заинтересовалась возможностью трансформации существующего производства включающего 400 сотрудников, работающих в 6 продуктовых направлениях. Данной публикацией, я запускаю цикл статей, в которых попытаюсь предложить формализованный подход для оценки степени зрелости аспектов разработки для внедрения SCRUM.

Для решения данной сложной задачи, была предложена программа, которая включает в себя 4 этапа:

  1. Оценка готовности производственных подразделений к трансформации

  2. Разработка этапов трансформации

  3. Разработка механизмов трансформации

  4. Разработка ценностной модели обоснования трансформации

Для реализации первого этапа, я разработал программу оценки готовности, которая состоит из следующих частей:

  1. Понимание и применение фреймворка SCRUM

  2. Разработка и поставка продукта

  3. Гибкое управление продуктовыми направлениями

  4. Развитие продуктовых команд

В данной статье будет идти речь об атрибутах и их характеристиках в разрезе понимания и применения фреймворка SCRUM. Остальные части будут раскрыты в следующих публикациях.

Философия эмпиризма

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

Характеристика

Метод исследования

Метрика

Декомпозиция

Наблюдение за инструментами фиксации проблем (JIRA)

отсутствует декомпозиция - 0 баллов

1 уровень декомпозиции - 1 балл

2 уровня декомпозиции - 3 балла

3 уровня декомпозиции - 5 баллов

Проблема

Опрос респондентов: Как Вы относитесь к проблеме?

Проблема - негативное событие и его нельзя допускать - 0 баллов

Проблема - явление к которому я уже привык - 3 балла

Проблема - возможность для роста и изучения нового - 5 баллов

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

Негативная реакция со стороны руководителя - 0

Позитивная реакция со стороны руководителя - 5

Наблюдение за реакцией сотрудников при возникновении проблемы

Негативная реакция со стороны сотрудника - 0

Позитивная реакция со стороны руководителя - 5

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


Культурные ценности

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

Характеристика

Метод исследования

Метрика

Фокус

Наблюдение за тем, что вся работа выполняется в контексте спринта для достижения своей цели

работа появляется спонтанно вне определенного контекста - 0 баллов

вся работа запланирована и выполняется в контексте спринта - 5 баллов

Открытость

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

стейкхолдеры практикуют неконструктивную обратную связь (обвинение, унижение) - 0 баллов

стейкхолдеры проявляют лояльность по отношению работ и дают обратную связь в конструктивном ключе - 5 баллов

Уважение

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

у частников ярко выражена модель ассоциации проблемы с индивидуальными способностями сотрудников - 0 баллов

участники с пониманием относятся к ограниченности как своих знаний, так и окружающих их людей; с желанием делятся опытом с коллегами- 5 баллов

Смелость

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

участники настороженно относятся к сложным задачам, которые вызывают отторжение - 0 баллов

участники с вызовом относятся к сложным проблемам и расценивают их как возможность сделать очередную запись успеха - 5 баллов

Приверженность

Наблюдение за персональной приверженностью сотрудников в части достижения целей спринта

сотрудники не ощущают зоны ответственности, нет понимания собственного вклада - 0 баллов

сотрудники ощущают персональную ответственность перед командой и продукта; есть также понимание собственного вклада - 5 баллов

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


Команда как функциональная единица

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

Характеристика

Метод исследования

Метрика

Команда

Наблюдение за принципами организации групп и наличие существования сущности команда

отсутствует понятие команды - 0 баллов

команда образована по функциональному признаку - 1 балл

самоорганизация команды по предметному признаку - 3 балла

команда образована по предметному признаку (направление) - 5 баллов

Скрам мастер

Наблюдение за наличием функций:

- Развитие продуктовой команды
- Поддержка среды с культурными ценностям
- Поддержка среды в рамках фреймворка SCRUM
- Мотивация продуктовой команды
- Применение модели "Менеджер - слуга"
- Организация производства
- Решение внутренних и внешних конфликтов

роль отсутствует, функции роли отсутствуют - 0 баллов

роль отсутствует, функции роли присутствуют - 1 балл

роль присутствует, функции роли отсутствуют - 3 балла

роль присутствует, функции роли присутствуют - 5 баллов

Владелец продукта

Наблюдение за наличием функций:

- Разработка дорожной карты продукта
- Управление продуктовым бэклогом
- Планирование и развитие продукта
- Проведение демонстрации продукта
- Проведение ежедневных стендапов
- Разработка бизнес гипотез

роль отсутствует, функции роли отсутствуют - 0 баллов

роль отсутствует, функции роли присутствуют - 1 балл

роль присутствует, функции роли отсутствуют - 3 балла

роль присутствует, функции роли присутствуют - 5 баллов

Разработчик

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

роль включает в себя только компетенции программирования - 0 баллов

роль включает в себя все необходимые компетенции для поставки версии продукта - 5 баллов

[ 0 - 13] - низкий результат, характеризующий отсутствие команды в качестве производственной единицы признанной на уровне организации. Необходимо разработать комплексную программу мероприятий для выделения и формирования команды в контексте организационных уровней компании. Не допускается проводить мероприятия для отдельно взятых характеристик за рамками комплексной программы.

[14 - 20] - средний результат, характеризующий наличие команды как класса, но существуют определенные ограничения для полного раскрытия потенциала. Необходимо определить проблемные характеристики для улучшения и разработать мероприятия. Допускается применение мероприятий без общей программы.

[17 - 20] - высокий результат, характеризующий наличие самодостаточной организационной единицы производства инкремента продукта, признанной на уровне организации. При данном результате, рекомендуется сделать акцент на мероприятиях направленные на управление продуктом, непрерывное обеспечение качества и CI/CD, как вектор роста команды


События

События представляют из себя правила коммуникаций в разрезе следующих вопросов:

  • кто должен коммуницировать?

  • когда должен коммуницировать?

  • с какой целью должен коммуницировать?

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

Характеристика

Метод исследования

Метрика

Спринт

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

событие отсутствует - 0 баллов

присутствует событие с фиксированной периодичностью (2-4 недели) - 5 баллов

Ежедневный стендап

Наблюдение за событиями ежедневных коммуникаций где происходит синхронизация.

событие отсутствует - 0 баллов

событие проходит каждый день и несколько раз - 1 балл

событие фиксировано по времени, проходит каждый день и больше 15 минут - 3 балла

событие фиксировано по времени, проходит каждый день и ограничено 15 минутам - 5 баллов

Планирование спринта

Наблюдение за событием на котором происходит планирование содержания инкремента продукта

событие отсутствует - 0 баллов

событие не имеет ритмичности и происходит хаотично - 1 балл

событие имеет ритмичность, но не ограничено по времени - 3 балла

событие имеет ритмичность и ограничено по времени (4 часа - 2х недельный спринт) - 5 баллов

Ревью спринта

Наблюдение за событием на котором происходит демонстрация работоспособного инкремента стейкхолдерам

событие отсутствует - 0 баллов

событие не имеет ритмичности и происходит хаотично - 1 балл

событие имеет ритмичность, но не ограничено по времени - 3 балла

событие имеет ритмичность и ограничено по времени (2 часа - 2х недельный спринт) - 5 баллов

Ретроспектива

Наблюдение за событием на котором команда анализирует результаты спринта для планирования мероприятий роста и развития

событие отсутствует - 0 баллов

событие не имеет ритмичности и происходит хаотично - 1 балл

событие имеет ритмичность, но не ограничено по времени - 3 балла

событие имеет ритмичность и ограничено по времени (2 часа - 2х недельный спринт) - 5 баллов

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

[18 - 20] - средний результат, характеризующий наличие событий с ограничением их эффективного использования. Ограничения выражены безосновательной продолжительностью, а также хаотичностью возникновения. При данном результате необходимо разработать мероприятия для проблемных характеристик с точки зрения сокращения времени и внедрения ритмичности. Допускается проведение мероприятий отдельно от общей программы в случае, если существующие события семантически соответствуют описанным выше. В том случае, если существуют дополнительные события, необходимо проанализировать эти события на предмет ценности и целесообразности.

[21 - 25] - высокий результат, характеризующий наличие эффективно выстроенных коммуникаций и ритмичные процессы производства продукта. При данном результате, рекомендуется сделать акцент на характеристике критерии завершенности в качестве точки роста компетенций команды и качества выпускаемого инкремента.


Артефакты

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

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

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

  3. Инкремент - протестированная и работоспособная версия с добавочной ценностью для клиента, которая соответствует критериям завершенности.

Характеристика

Метод исследования

Метрика

Бэклог продукта

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

бэклог продукта отсутствует - 0 баллов

бэклог продукта имеет вид разбросанных задач - 1 балл

бэклог имеет вид отфильтрованного списка по предмету - 3 балла

бэклог единое место хранения всех задач по продукту - 5 баллов

Бэклог спринта

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

бэклог спринта отсутствует - 0 баллов

бэклог спринта имеет вид разбросанных задач - 1 балл

бэклог имеет вид отфильтрованного списка по предмету - 3 балла

бэклог единое место хранения всех задач по спринту - 5 баллов

Инкремент

Наблюдение за фактом выпуска протестированной и работоспособной версии продукта

понятие инкремента отсутствует - 0 баллов

понятие инкремента присутствует, но выпуск работоспособной версии не происходит по факту окончания спринта - 1 балла

понятие инкремента отсутствует, но выпуск работоспособной версии происходит по факту окончания спринта - 3 балла

понятие инкремента присутствует, триггером появления служит спринт - 5 баллов

[ 0 - 9 ] - низкий результат, характеризующий сложность существующих подходов в части управления и планирования содержанием работ. Данная сложность может быть причиной увеличения времени ожидания ответа на запрос внутри команды, а также причиной низкой концентрацией на актуальных задачах.

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

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


Критерии завершенности

Список критериев завершенности (далее DoD, от английского definition of done) является формальным чек-листом для принятия решения о выпуске инкремента. Критерии определяются стандартами организации или в случае если они отсутствуют, то команда сама должна определить список DoD. По мере развития команды, список критериев завершенности будет развиваться параллельно улучшению качества выпускаемого инкремента.

Характеристика

Метод исследования

Метрика

Наличие списка DoD

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

DoD отсутствует - 0 баллов

DoD отсутствует, существуют разбросанные критерии - 1 балл

DoD присутствует, инкремент выпускается соответствия критериям - 3 балла

DoD присутствует, инкремент выпускается при соответствии критериям - 5 баллов

Проверка уязвимостей

Наблюдение за наличием критерия , который характеризует отсутствие уязвимостей в исходном коде

критерий отсутствует - 0 баллов

критерий есть, не участвует в принятии решения - 1 балл

критерий есть, участвует в принятии решения, не используется специализированное ПО (sonarqube) - 3 баллов

критерий есть, участвует в принятии решения, используется специализированное ПО (sonarqube) - 5 баллов

Покрытие исходного кода

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

критерий отсутствует - 0 баллов

критерий есть, не участвует в принятии решения - 1 балл

критерий есть, участвует в принятии решения, не используется специализированное ПО (sonarqube) - 3 баллов

критерий есть, участвует в принятии решения, используется специализированное ПО (sonarqube) - 5 баллов

Инженерные стандарты

Наблюдение за наличием критерия , который характеризует применение инженерных стандартов (методы, тесты, переменные и т.д.)

критерий отсутствует - 0 баллов

критерий есть, не участвует в принятии решения - 1 балл

критерий есть, участвует в принятии решения, нет общей wiki страницы с описанием стандартов - 3 баллов

критерий есть, участвует в принятии решения, есть wiki страница с описанием стандартов - 5 баллов

Критерии приемки

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

критерий отсутствует - 0 баллов

критерий есть, не участвует в принятии решения - 1 балл

критерий есть, участвует в принятии решения, нет общей wiki страницы с описанием критериев - 3 баллов

критерий есть, участвует в принятии решения, есть wiki страница с описанием критериев - 5 баллов

Автотесты

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

критерий отсутствует - 0 баллов

30 - 50 % покрытие - 1 балл

50 - 80 % покрытие - 3 балла

80 - 100% покрытие - 5 баллов

Проверка безопасности

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

критерий отсутствует - 0 баллов

критерий есть, не участвует в принятии решения - 1 балл

критерий есть, участвует в принятии решения, не используется специализированное ПО - 3 баллов

критерий есть, участвует в принятии решения, используется специализированное ПО - 5 баллов

UI/UX стандарты

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

критерий отсутствует - 0 баллов

критерий есть, не участвует в принятии решения - 1 балл

критерий есть, участвует в принятии решения, нет общей wiki страницы с описанием стандартов - 3 баллов

критерий есть, участвует в принятии решения, есть wiki страница с описанием стандартов - 5 баллов

Архитектурные принципы

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

критерий отсутствует - 0 баллов

критерий есть, не участвует в принятии решения - 1 балл

критерий есть, участвует в принятии решения, нет общей wiki страницы с описанием принципов - 3 баллов

критерий есть, участвует в принятии решения, есть wiki страница с описанием принципов - 5 баллов

[ 0 - 31] - низкий результат, характеризующий отсутствие системы критериев завершенности, как механизма принятия решения о выпуске инкремента продукта. Для данного кейса свойственен иррациональный критерий - наступление даты релиза. Рекомендуется разработать комплексную программу внедрения критериев завершенности в минимальном составе. По мере того, как критерии будут приобретать рутинный характер, можно рассмотреть внедрение новых для улучшения качества выпускаемого инкремента.

[32 - 37] - средний результат, характеризующий ограниченное использование системы критериев завершенности. Ограничение может быть обусловлено отсутствием полноты критериев, а так же их игнорированием при принятии решении о выпуске инкремента. Рекомендуется предусмотреть отдельные мероприятия для улучшения критериев с низкой оценкой.

[38 - 45] - высокий результат, характеризующий устоявшуюся и применяемую систему критериев завершенности , которая гарантирует выпуск работоспособного инкремента за спринт. При данном результате, команда по умолчанию выполняет действия, направленные на удовлетворение критериям завершенности и это становится рутинной операцией. Рекомендуется зафиксировать подход как эталонный и разработать стандарт на уровне организации.


Масштабирование

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

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

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

  • Новые клиенты - механизм при котором происходит внедрение существующих продуктов для нового клиента. Первый способ - для каждого клиента отдельная ветка и свой вектор развития продукта; второй способ - выделяется общее ядро и собственная ветка разработки для каждого клиента в рамках слоя кастомизации; третий способ - единственная ветка разработки с общими архитектурными механизмами.

  • Архитектура - механизм, который регулирует способ управления и развития архитектуры. Первый способ - монолитная архитектура, второй способ - микросервисный монолит, третий способ - микросервисная архитектура, четвертый способ - оркестратор бизнес процессов.

Характеристика

Метод исследования

Метрика

Кадровое обеспечение

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

запрос функциональных подразделений - 1 балл

запрос продуктовых команд - 5 баллов

Новый продукт

Наблюдение за способом мобилизации ресурсов на новые продуктовые направления

привлечение отдельно взятого сотрудника - 1 балл

привлечение устоявшихся команд - 5 баллов

Новые клиенты

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

своя ветка для каждого клиента - 1 балл

общее ядро и собственная ветка разработки для каждого клиента - 3 баллов

единственная ветка разработки с общими архитектурными механизмами - 5 баллов

Архитектура

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

монолитная архитектура - 0 баллов

микросервисный монолит - 1 балл

микросервисная архитектура - 3 балла

оркестратор - бизнес процессов - 5 баллов

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


Подробнее..

SCRUM Развитие сотрудников и продуктовых команд

27.05.2021 12:14:32 | Автор: admin

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

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

Остальные части программы оценки готовности к трансформации:
SCRUM: Понимание и применение фреймворка
SCRUM: Разработка и поставка продукта
SCRUM: Гибкое управление продуктовыми направлениями

Фасилитация встреч и мероприятий

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

Характеристика

Метод исследования

Метрика

Роль фасилитатора

Наблюдение за выделением роли фасилитатора в компании

отсутствует выделение и признание роли на уровне компании - 0 баллов

роль фасилитатора проявляется у сотрудников с не руководящими функциями - 1 балл

сотрудники с руководящими функциями выполняют роль фасилитатора - 3 балла

присутствует выделение и признание роли на уровне компании - 5 баллов

Знания фасилитатора

Наблюдение за проявлением знаний фасилитатора в рамках:

- Цель события
- Составные части темы для трансляции
- Бэкграунд и степень синхронизации участников
- Поведение участников в группах
- Набор используемых техник фасилитации

слабо развития система знаний фасилитатора - 0 баллов

сильно развития система знаний фасилитатора - 5 баллов

Навыки фасилитатора

Наблюдение за проявлением навыков фасилитатора:

- Ясное выражение мыслей
- Умение слушать, понимать быстро и фокусировать внимание на важном;
- Структурирование и ведение темы;
- Парафраз вклада участников
- Суммирование и визуализация основных моментов дискуссии
- Мотивация и подогрев участников
- Предоставление правил и инструкций события для участников
- Интеграция результатов смежных групп в общий процесс
- Управление таймингом
- Идентификация динамики группы и соответственная реакция
- Фиксация общего обзора события

слабо развития система навыков фасилитатора - 0 баллов

сильно развития система навыков фасилитатора - 5 баллов

Правила организации

Наблюдение за проявлением правил организации и проведения событий:

- Цель события и ожидаемый результат;
- Содержание и программа события;
- Участники и их роли;
- Время проведения, длительность и место;

Правила фасилитации не устанавливаются - 0 баллов

Правила фасилитации устанавливаются для событий - 3 балла

Для периодических событий , правила зафиксированы в едином месте (например confluence) - 5 баллов

Техники фасилитации

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

- Брейншторминг
- Консенсус
- Дискуссия
- Интервенция
- Фокус на повестку события
- Основные правила события

техники фасилитации не выделяются и не используются - 0 баллов

ограниченное использование техник фасилитации - 3 балла

проявление гибкости в использовании техник фасилитации в зависимости от ситуации - 5 баллов

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

[20 - 25] - высокий результат, характеризующий устоявшуюся культуру фасилитации событий внутри компании, целью которой является создание удобных механизмов для владельцев содержания. Данный способ организации событий предоставляет модель встреча-развлечение, на которой у участников формируются доверительные отношения, целеполагание и вовлеченность в ожидаемый результат. При данном результате рекомендуется сделать акцент на развитие личностных характеристик сотрудника с функциями фасилитатора.


Методы развития продуктовых команд

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

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

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

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

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

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

Характеристика

Метод исследования

Метрика

Коучинг

Наблюдение за принципом целеполагания команд продуктовых направлений

отсутствует роль, которая помогает команде ставить и достигать цели - 0 баллов

команда проявляет принцип самоорганизации для установки цели - 1 балл

выделяется роль коуча, которая помогает команде ставить и достигать цели - 3 балла

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

Менторcтво

Наблюдение за проявлением данного метода при адаптации нового сотрудника или горизонтальном карьерном росте

отсутствует роль, которая помогает адаптироваться сотрудникам - 0 баллов

проявление принципа самоорганизации при адаптации - 1 балл

выделяется роль ментора, которая помогает сотруднику с адаптацией - 3 балла

выделяется роль ментора, признанная на уровне компании, которая помогает сотруднику с адаптацией - 5 баллов

Терапия

Наблюдение за существованием механизмов психологической разгрузки

сотрудники не привыкли делиться переживаниями - 0 баллов

у сотрудников есть неофициальные каналы, где они могут поделиться переживаниями - 1 балл

у сотрудников есть официальные каналы, где они могут поделиться переживаниями с возможностью быть услышанными компанией - 3 балла

выделяется роль сотрудника к которому можно обратиться за поддержкой и психологической разгрузкой - 5 баллов

Тренинг

Наблюдение за подходами обмена знаниями и опытом внутри компании

внутри компании тренинги не проводятся - 0 баллов

тренинги имеют несистемный характер проведения - 1 балл

существует комьюнити экспертов для проведения тренингов - 3 баллов

существует комьюнити экспертов, поддерживаемого компанией, для проведения тренингов - 5 баллов

Консультация

Наблюдение за подходами обмена знаниями и опытом снаружи компании

компания замкнулась в себе и ограничивает общение с внешним миром в части развития собственных подходов - 0 баллов

компания принимает активное участие в семинарах и воркшопах - 3 балла

компания принимает активное участие в семинарах, существуют партнерские отношения с проверенными консультантами - 5 баллов

[ 0 - 10] - низкий результат, характеризующий отсутствие у компании осмысленного подхода к развитию и адаптации кадров. В случае динамической среды стартапа, может наблюдаться эмоциональное выгорание сотрудников на горизонте испытательного срока; в случае умеренной корпоративной среды, наблюдается проявление низкой культуры развития сотрудников, как осознанный выбор компании для снижения затрат рынка низкотехнологичной продукции. При данном результате, целесообразность разработки программы обусловлена видением инвесторов в части долгосрочности нахождения компании на рынке, а также высокотехнологичностью продукции.

[11 - 20] - средний результат, характеризующий ограниченный набор методов развития продуктовых команд или не системность их использования. В случае динамической среды стартапа, может наблюдаться эмоциональное выгорание сотрудников на горизонте одного года; в случае умеренной корпоративной среды, может проявляться фрустрация и стагнация в развитии профессиональных навыков и знаний у сотрудников. В первую очередь, рекомендуется сделать акцент на развитие менторства и системы тренингов для сотрудников.

[21 - 25] - высокий результат, характеризующий зрелую систему развития и поддержки продуктовых команд. В арсенале компании имеются все доступные методы для формирования у сотрудников необходимого проактивного паттерна отношения к труду, новых навыков и знаний. При данном результате, компания осознаёт необходимость инвестицией в человеческий ресурс, так как он является потенциалом роста продуктовых направлений. Рекомендуется рассмотреть создание образовательного комплекса (аналоги GeekBrains, SkillFactory и т.д.) в периметре компании в целях становления и развития кадрового резерва.


Стили управления

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

Характеристика

Метод исследования

Стиль коуча

Наблюдение за проявлением следующих особенностей у сотрудников с руководящей функцией:

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

Стиль идеолога

Наблюдение за проявлением следующих особенностей у сотрудников с руководящей функцией:

- настойчивый
- стратегическое мышление
- склонный к риску
- воодушевляющий
- оптимистичный
- инновационный
- харизматичный

Стиль слуги

Наблюдение за проявлением следующих особенностей у сотрудников с руководящей функцией:

- мотивация команды
- развитые навыки коммуникации
- персональная забота о команде
- стимулирует коллаборацию и вовлеченность
- привержен профессиональному росту команды

Стиль автократа

Наблюдение за проявлением следующих особенностей у сотрудников с руководящей функцией:

- самоуверенность
- целеустремленность
- речь чистая и последовательная
- следует правилам
- ценит стабильность
- ценит иерархичную среду
- ценит контролируемую рабочую среду

Стиль невмешательства

Наблюдение за проявлением следующих особенностей у сотрудников с руководящей функцией:

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

Стиль демократа

Наблюдение за проявлением следующих особенностей у сотрудников с руководящей функцией:

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

Стиль темпа

Наблюдение за проявлением следующих особенностей у сотрудников с руководящей функцией:

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

Стиль трансформатора

Наблюдение за проявлением следующих особенностей у сотрудников с руководящей функцией:

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

Cтиль операционный

Наблюдение за проявлением следующих особенностей у сотрудников с руководящей функцией:

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

Cтиль бюрократа

Наблюдение за проявлением следующих особенностей у сотрудников с руководящей функцией:

- ориентированный на детали и задачи
- ценит правила и системность
- имеет высокие стандарты корпоративной этики
- проявляет упрямство
- проявляет высокую преданность компании
- собранный и дисциплинированный

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

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

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

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

Подробнее..

Эволюция работы с техническим долгом

24.11.2020 10:23:43 | Автор: admin

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

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

Немного теории

Технический долг справа внизуТехнический долг справа внизу

Что такое технический долг?Технический долг - работы, если их не сделать, несут ущерб невидимый для пользователя (ручная настройка фичи, нечитаемые/отсутствие логов).

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

Каждый берет, то, что ему ближе

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

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

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

Из-за отсутствия механизма ранжирования задач, каждый брал то, что интересно ему. А из-за отсутствия процесса, который позволял бы задачам дойти до боевых серверов, такие задачи часто застревали где-то в районе code-review или тестирования (ведь основные задачи всегда более приоритетны!)

Собственный велосипед для ранжирования

Мы не стали брать какую-то готовую систему оценки, которую кроме того, что применить, нужно еще и подстроить для себя, а сделали собственную.

Каждую из задач технического долга мы оценивали по 4 критериям:

  • Повторяемость - как часто мы сталкиваемся с этой проблемой. (0 - очень редко, раз в полгода, 5 - каждый день)

  • Скорость доставки - как данная задача повлияет на скорость доставки других фичей. (скорость разработки, время тестирования, время деплоймента, предсказуемость разработки) (0 - не влияет, 5 - экономит очень много времени)

  • Влияние на время оперирования (расходы на эксплуатацию, нагрузка на сервер, безопасность) (0 - не влияет, 5 серьезно снижает расходы и риски оперирования)

  • Уровень технической инвестиции (0 - это не инвестиция, 5 - технический энейблер для большого ряда задач)

Каждую задачу мы оценили в привычных для нас story points, чтобы оценить сложность.

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

В формуле можно заметить коэффициенты X, Y и Z. Они нужны для того, чтобы в каждый момент времени мы могли повлиять на наш скоринг - если для текущего состояния продукта нам больше важна скорость доставки, то сделать X больше чем Y и Z и всё в таком духе.

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

Самое сложное в этом процессе - собрать команду и вместе оценить все задачи тех. долга по каждому критерию.

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

Упрощаем процесс

Поняв, что текущая оценка достаточно сложная и долгая, мы решили отказаться от неё.

Но чем заменить?

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

Раз в квартал оцениваем все задачи - учитывая, количество технического долга и количество разработчиков, за час каждый может оценить 10-15 задач. Если кто-то не согласен с оценкой, обсуждаем.

Процесс погашения тоже претерпел изменения.

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

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

А дальше?

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

Подробнее..

Сертификации в Agile. Пара слов для HR и для коллег-разработчиков

19.12.2020 10:19:16 | Автор: admin
Я хочу сразу оговориться что не преследую цели ни пропагандировать сертификации для IT, ни предавать их анафеме. Этот выбор каждый должен сделать для себя. Но как бы то оно ни было сертификации существуют, сертификации придается значение за рубежом, и в резюме сотрудников и РФ, Украины и Белоруссии я уже начал встречать упоминания о сертификациях, а значит они есть как реальность уже и в РФ. И неплохо бы понимать что все эти буковки означают. В этой статье я расскажу какие есть популярные сертификации в мире Agile и Scrum и что на самом деле за ними стоит.

Scrum.org

Компания, которой руководит Кен Швайбер, один из авторов Scrum Guide. Предлагают более десятка сертификаций по разным направлениям применения Scrum, от основных ролей до применения Scrum и Agile для организации бизнеса. Экзамен сдается online. Никаких проверок удостоверения личности или контроля за сдачей экзамена нет, однако временные ограничения довольно жесткие (минута на вопрос), а проходной балл достаточно высокий (85%), так что для сдачи и правда надо знать, нагуглить не получиться.

Самый популярный экзамен Scrum Master имеет 3 уровня.

Первый уровень это просто вопросы в которых предлагается выбрать один или несколько вариантов ответа (традиционная форма для экзаменов), причем вопросы касаются исключительно содержимого Scrum Guide. Другими словами сертифицированный PSM 1 продемонстрировал свою способность прочитать и понять Scrum Guide, не более того. Хотя, посмотрев за последние годы множество более чем странных вариаций под лозунгом мы тут строим свой Scrum может быть это уже и не мало.

Уровень вопросов пожалуйста выберите из списка ниже что является ценностями Scrum

Второй уровень тоже вопросы, но уже в формате вот ситуация, как следует поступить. Ситуации сложные, варианты неоднозначные. Что бы сдать надо действительно понимать как следует применять Scrum guide. Как я уже писал в предыдущей статье его сдали всего 8000 человек, почти 1 из 50 кто сдал первый уровень. Наверное это как-то коррелирует с уровнем реализации Scrum.

Уровень вопросов На review стейкхолдеры высказали недовольство производительностью продукта и частотой релизов. Что может быть причиной и 5-6 вариантов из которых надо выбрать 2-3 наиболее подходящих.

Скажем вариант типа Velocity команды не соответствует требованиям ситуации манит, но не верен. А вот вариант подобный Команда не использовала review и retrospective для пересмотра и адаптации DoD неочевиден, но нужен.

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

Scrum Alliance

Вторая (а может и первая все-таки) по популярности сертификация.

Тоже имеет три уровня сложности, но подход у них немного другой.

Во-первых, для того, чтобы сдать экзамен надо обязательно посетить их курс. Курс не то чтобы исчерпывающий, подготовить за 2-3 дня мало-мальски соображающего Scrum Master невозможно, но все таки курс дает надежду что человек хотя бы направлен в нужном направлении. Последующий экзамен намного мягче чем у Scrum, проходной балл всего 60%.

Первый два уровня CSM и A-CSM аналогичны PSMI и PSMII выше, а вот третий CSP можно получить только после интервью с их экзаменационной комиссией. Именно у них я не проходил, но подобные интервью в моей карьере были они довольно серьезные и умышленно ставят тестируемого в стрессовое состояние, чтобы увидеть не просто знания, но и способность их применять в сложной ситуации. Тоже сложно и тоже стрессово как и PSM III, но с упором не на чистые знания, а на личную способность общаться. Условно говоря, если вам нужен мыслитель смотрите PSM, а если умелый коммуникатор CSM может быть предпочтительней. Опять-таки не гарантия, выбор мог быть и случайным, но если человек уперся в какую-то ветку сертификации это кое-что о нем тоже говорит.

PMI

Project Management Institute подключился к Agile сертификациям всего несколько лет назад. Мне кажется про них должны знать все, но на всякий случай это именно так организация которая создала понимание проектной работы в классическом ее виде. То, что даже такой динозавр в вопросах управления серьезно взялся за Agile говорит о многом. Они точно не нуждаются ни в дешевой популярности, ни в легких деньгах от доверчивых адептов Agile.

У PMI один-единственный экзамен ACP (Agile Certified Professional), близкий по сложности к PSMII и A-CSM, но посвященный не только Scrum, а Agile в целом, и, что немаловажно, затрагивающий вопросы взаимодействия Agile-команд с бизнес-процессами построенным по классической модели.

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

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

У меня лично есть и Scrum.org и ACP экзамены, и я не возьмусь сказать какой из них лучше подтверждает знания. PSMII глубже копает в Scrum, но PMI-ACP куда шире рассматривает Agile в целом. Что важно знать что в пуристских и молодых компаниях Scrum сертификации ценятся больше, а вот в устоявшихся и крупных бизнесах традиционно больше доверяют PMI.

ICAgile

Как я заметил самая популярная в РФ сертификация Которая сертификацией не является. ICAgile это достаточно авторитетная организация утверждающая учебные программы и выдающая сертификат установленного образца тем кто эти программы прослушал.

Увы, никаких экзаменов не предполагается и никакой независимой проверки знаний не происходит. Опять-таки не поймите меня неправильно. У преподавателей от ICAgile замечательные курсы (в конце концов я сам иногда с удовольствием читаю их ICP начинающим аджилистам), но прослушал не означает понял

Поэтому воспринимайте эти сертификации как именно то, чем они являются всего лишь бумагой о посещении курса.

Ну и в качестве заключения

Если говорить о сертификация про Agile в целом то пожалуй этот список исчерпывающий. Есть более узкие сертификации, такие как SAFe (Agile at Scale framework) или DA (Disciplined Agile от PMI, про него я уже рассказывал), но что касается действительно уважаемых и ценимых в забугорном мире Agile это пожалуй все.

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

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

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

Ну а если вам попался человек который получал сертификаты сам хватайте, человек который готов поставить свои деньги на кон, чтобы проверить собственные знания (а все эти экзамены отнюдь не дешевы, от 200 до 1000 долларов за попытку) обладает той самой смелостью, сосредоточенностью и открытостью мышления которую столь ценят адепты Scrum.

Спасибо что дочитали до конца. Как обычно с удовольствием отвечу на все вопросы, как про сертификации, так и про Scrum и Agile в целом.

p.s. Надеюсь что вторая попытка звучит менее рекламно, чем предыдущая статья, такой цели не было, видимо случайно попал в тональность используемую рекламщиками русскоязычными, вот она оторванность от языковой среды.
Подробнее..
Категории: Agile , Scrum , Certification

Перевод Кристиан Вервейс О сложности или зачем вам Скрам?

10.01.2021 20:13:06 | Автор: admin

Кристиан Вервейс: О сложности или зачем вам Скрам?

Предисловие переводчика

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

Оригинал статьи находится тут:

https://medium.com/the-liberators/on-complexity-why-your-software-project-needs-scrum-13c36305c866. Статья входит в список scrum.org рекомендованного к изучению для подготовки к экзамену PSM III.

Важность таких статей сложно переоценить. Судя по ошибкам, которыми делятся команды, и по некоторым комментариям, немалое число людей, пытающихся применить Agile, на самом деле не пошло дальше материалов типа строим Скрам за 5 дней, которые больше сосредоточены на элементарных практиках, а не на причинах и не на основополагающих принципах Скрам и Эджайл. Я сам, как руководитель, изначально столкнулся именно с такой, от сохи, реализацией Скрама, но, к счастью для себя, не сделал обоснованный вывод что весь этот ваш Скрам - это очередная подделка и модная глупость, а полез разбираться откуда и зачем есть пошел Эджайл и прочие Скрамы. Честно скажу - объем открытий чудных был намного больше ожидаемого, несмотря на годы опыта в управлении проектами, накопленные к тому моменту. Так что, надеюсь, что перевод достаточно важной для понимания Скрам статьи будет полезен почтенной публике, и, конечно же, я сам, как сертифицированный Скрам-мастер и человек преподающий Скрам и Эджайл (я помню, коач слово ругательное :-)), буду рад ответить на все вопросы.

Предисловие

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

Выкинь свои планы?

Большинство людей понимают сложность исключительно в контексте насколько сложно то, что мы создаем. Недавно я общался с руководителем, который считал что его проект простой, потому, что речь идет о переписывании огромной, но уже существующей системы. Но ведь это всего лишь один из факторов! На курсах для профессиональных скрам-мастеров мы всегда просим участников найти можно больше факторов, которые влияют на успех проекта (примечание переводчика: имеются в виду курсы Professional Scrum Master и Professional Scrum Master Advanced от scrum.org). Мы даем всего несколько минут, но этого хватает, чтобы участники полностью заполнили лист формата A1. Если бы мы давали целый день, я точно знаю - им бы не хватило стен в классе чтобы записать все факторы.

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

  • Стили и опыт общения в команде

  • Правомочия команды и поддержка проекта внутри организации

  • Профессиональный уровень вовлеченных специалистов

  • Насколько у проекта ясная цель

  • Количество вовлеченных в проект

  • Техническая и организационная культура

  • Обмен знаниями

  • Используемый процесс

  • Насколько доступны представители заказчика

  • Насколько заинтересованы и вовлечены пользователи

  • Выбранный инструментарий

  • Нестабильность рынка

  • Умение планирования и управления временем

  • Мотивация

  • Время исполнения проекта

  • Качество и размер унаследованного кода

  • Отношения с поставщиками ключевых компонент

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

Я собираюсь описать два хорошо известных способа преодоления сложности - матрицу Стейси (Staceys matrix) и модель Кеневин (Cynefin).

Примечание переводчика: Позволю себе немного дополнить. Западные источники тоже часто стараются оградить читателя от излишне сложных знаний, но мы-то не такие, да? Сложность в данном случае не модная выдумка и не околонаучное словоблудие. Это отрасль науки, входящее в общую теорию систем, называемая теорией сложных систем. Теория получила активное развитие с середины 70-х годов прошлого века, и известный ученый и популяризатор науки Хоукинг даже предсказал что 21-й век будет веком познания сложных систем. Итак, что такое сложность, и, самое главное, то самое непонятное слово часто встречающееся в контексте Аджайла - эмерджентность? Система считается сложной, если её поведение невозможно предсказать, зная поведение каждого отдельного элемента системы. Поведение, которое свойственно только системе как единому целому, но не свойственно ни одному её компоненту как раз и называется эмерджентным.

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

Матрица Стейси

Один из способов понимания сложности - это матрица Ральфа Стейси. За годы её использования было выработано несколько классических способов представления, но все они говорят о сложности как о функции от согласованности понимания что надо делать и уверенности в знании о том как надо делать. Ниже показана матрица в виде, адаптированном для процессов разработки ПО.

Матрица Стейси создана, чтобы помочь руководителям понять степень сложности, с которой они столкнулись, и выбрать адекватную модель принятия решений. Для разработки ПО матрицу организуют по координатам Требования (Что делать?) и Технологии (Как делать?). Первая определяет насколько хорошо нам известно какой именно продукт следует создать, вторая - насколько хорошо нам известно как именно следует создавать продукт. Матрица как она представлена на рисунке не совсем совпадает с оригинальной матрицей в работах Стейси, но использует те же самые концепции. Матрица определяет четыре типа ситуаций:

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

Усложненная: Проект усложнен, если нам не очень хорошо понятно что мы будем делать или как мы будем делать. Я часто привожу пример инструментария для Web. Реализация достаточно понятна, достаточно взглянуть на схожие решения, типа Magneto или WooCommerce, но вот в чем именно нуждается рынок и как именно представить рынку новый продукт уже не так очевидно. Другой пример - стыковка интерфейсов двух разных систем. Что делать вполне понятно - вот хорошо задокументированный интерфейс одной системы, вот хорошо задокументированный интерфейс другой системы. Но вопрос как уже не так однозначен, начиная прямо с вопроса какие данные в одной системе соответствуют конкретным данным в другой системе? Часто ответить на все эти вопросы заранее просто невозможно. Кто-то может сказать что анализ, проектирование и разработка вполне решает такие задачи, но по моему опыту - не очень. Именно итеративная разработка может помочь здесь.

Примечание переводчика: По моему мнению в выводах автор зря уходит от теории сложности, предлагая доверять его всего лишь его опыту. Предсказательный подход (чаще известный как водопад) весь построен на одной посылке - систему можно полностью изучить разобрав её на части и изучив каждую часть. Именно на этом построен хорошо известный механизм упрощения сложных и больших задач - декомпозиция. Мы разбираем требования на части (OOA), мы разбираем дизайн на части (OOD/OOP), мы разделяем работу на маленькие кусочки (WBS) и рассчитываем что в итоге у нас получиться именно то что нам надо. Каждый кусочек-то правильный, так? Теперь вернемся в вопросу а что такое сложная система и что такое эмерджентное поведение. А ведь это система, поведение которой не объясняется поведением отдельных частей! То есть, весь предсказательный подход в принципе не может работать для сложной системы - методы которые там применяются просто не предназначены для понимания и создания сложных систем, они не учитывают поведения возникающего только у системы в целом.

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

Примечание переводчика: В русском языке эмпирический подход еще называют научным подходом - способом познания неизвестного путем высказывания теоретически обоснованной гипотезы и проведении эксперимента по ее проверке, объективного и повторяемого. Скрам использует эту же самую терминологию когда мы говорим об управлении. Цель спринта, как и спринт бэклог являются не более чем гипотезами о том, что реализация выбранной функциональности создаст ожидаемую заказчиком ценность, а команда способна эту функциональность реализовать. Спринт является, по сути, экспериментом по проверке этих гипотез, ревью - валидацией результата эксперимента, а ретроспектива - адаптацией процесса на основе новых знаний, полученных в результате проведенного эксперимента. Предиктивный процесс совершенно некорректно сравнивает разработку ПО с массовым производством и пытается применить методы массового производства к работам, которые по сути являются НИОКР (научно-исследовательские и опытно-конструкторские работы). Ни на одном заводе и ни в одном КБ такой глупостью, как внедрением методов массового производства в конструкторскую работу никогда не занимались. А вот если посмотреть как работают в результативном КБ - то внезапно окажется что это очень похоже на все тот же Аджайл. Такие дела.

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

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

Итеративный подход может быть эффективен и тут, но с двумя условиями. Во-первых итерация должна быть очень короткой, во-вторых объем работы в итерации должен быть жестко ограничен.

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

Ограничения матрицы Стейси

Интересно, что сам Стейси отказался в итоге от использования матрицы, объясняя это тем, что все работы - сложные. Даже самая простая работа внезапно может оказаться сложной, если что-то пошло не так.

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

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

Модель Кеневин (Cynefin framework)

Модель Кеневин была разработана в 1999 Дейвом Сноуденом (Dave Snowden) из АйБиЭм, чтобы помочь лидерам и управленцам лучше понять ситуацию, в которой они оказались и выбрать правильную стратегию действий. Позже модель была доработана Синтей Курц (Cynthia Kurtz). Модель активно используется Эджайл-сообществом и помогает объяснить почему Эджайл вообще и Скрам в частности хорошо подходят для разработки ПО. Модель выглядит сложнее матрицы Стейси, но дает более четкое объяснение.

Говоря простыми словами, Кеневин определяет пять видов сложности, которые принципиально различаются между собой. Соответственно, модель утверждает что есть четыре способа познания неизвестного. Каждому виду сложности соответствует свой способ познания и свой подход к управлению. Хотя модель выглядит как квадрат 2x2, на самом деле в ней нет осей абсцисс и ординат.

Виды сложности:

Простое. В простой ситуации очевидно что делать, так как проблема понятна, а путь решения хорошо известен и проверен. Диагностика проблемы и выбор решения не требует экспертных знаний. Такие задачи хорошо решаются выбором лучших практик (best practices). Управление строится на диагностике ситуации (осознай), понимании к какой уже известной категории относится проблема (упорядочь) и к выбору и применению известного и устоявшегося метода решения (реагируй). Примером такой ситуации может быть колл-центр, использующий готовые сценарии для звонков. Для управления в простой ситуации достаточно убедиться что люди понимают что надо сделать и как надо сделать.

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

Сложное. В сложной ситуации и проблема и способы решения по большей части неизвестны. В такой ситуации даже найти правильного эксперта или задать правильный вопрос - уже сложно (мы имеем дело с неизвестными нам неизвестным). И понимание проблемы и поиск её решения требуют активного экспериментирования, до тех пор пока не начнет проявляться подходящий способ решения. И если общее направление еще может быть известно заранее, окончательное решение остается неясным до тех пор, пока оно не будет найдено. Подход к управлению строится на планировании и проведении эксперимента (попробуй), на анализе результатов эксперимента (осознай) и выборе нового эксперимента на основе полученных ранее знаний (реагируй). (примечание переводчика: коллеги, применяющие методы Деминга и их производные, такие как Kaizen или SixSigma без труда узнают цикл PDCA - plan, do, check, act). Наиболее эффективный стиль управления в такой ситуации - сотрудничество.

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

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

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

Знания, границы и где тут Скрам

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

Представьте что мы находимся в хаосе, скажем, обычный наш пример массового отказа систем. У нас нет времени сидеть и думать, мы сортируем проблемы по важности и решаем то что можем решить здесь и сейчас. Принцип: важное - вперед, жестко ограниченное количество незаконченный работы (work in progress). Рано или поздно, все эти действия приведут систему в более упорядоченное состояние и дадут нам время на более продуманные решения.

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

Таким образом, изменяя наше поведение, мы способствуем лучшему пониманию ситуации. Это помогает двигаться по модели по часовой стрелке - от хаоса - к сложному, от сложного - к усложненному, и, наконец, - от усложненного к простому. Между простым и хаосом находится перевал (иногда обрыв) показывающий возможность падения из простоты обратно в хаос. Такое случается, например, когда устоявшиеся лучшие практики устаревают, но их упорно продолжают применять. Или, например, когда человек, обладающий критически важными для продукта знаниями, покидает компанию, не передав знания и опыт кому-то еще. При первой же возникшей проблеме оставшимся придется иметь дело с хаосом и собирать головоломку утерянных знаний заново.

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

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

Так что там про Скрам?

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

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

  • Если команда осознает недостаток своих знаний о проблеме и способах её решения.

  • Если команда организует свою работу признавая и учитывая этот недостаток знаний

  • Если команда стремиться к получению дополнительных знаний о проблемах и способах решения путем эксперимента

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

Вот тогда и только тогда команда действительно делала Эджайл. А не тогда, когда команда разбрелась как подружки по парам делая типа XP, и не когда они собираются на формальный митинг для пляски с бубнами в течении 15 минут ежедневно, называя их точно также, как в скрам-гайде. Такие дела.

Подробнее..
Категории: Agile , Scrum

Take a bite и Команда Тигров опыт применения Agile-методов для решения непонятных задач и создания больших фич

25.03.2021 10:19:47 | Автор: admin

Привет, Хабр! Где-то года три назад мы начали переходить с обычного вотерфольного процесса, присущего большинству продуктов энтерпрайз-сегмента, на гибкие подходы. Стартовали с одной команды и одного подпродукта. На данный момент у нас шесть полноценных Scrum-команд. О том, почему это было необходимо, как проходила agile-трансформация, какие подходы мы тестировали, чтобы научиться делать по-настоящему большие и малопонятные на старте фичи, читайте подробнее в посте.

Одним из основных продуктов, который разрабатывает наша компания, является Solar Dozor. Это DLP для корпоративных и государственных заказчиков. Команда разработки состоит из примерно 80-ти человек, включая аналитиков, разработчиков, тестировщиков и технических писателей.

Продукту около 20 лет, за спиной как большой багаж знаний и уникальных технологий, так и того, что хотелось бы исправить :)

Три года назад мы начали смотреть в сторону гибких подходов. Протестировав их на одной команде и одном модуле DLP, поняли, что надо масштабировать. Сегодня у нас шесть полноценных Scrum-команд, а также отдельная команда Product Owner. Последняя живет в чем-то ближе к Kanban, в так называемом процессе Discovery, предшествующем этапу Delivery. В Delivery наши команды реализуют их задумки уже в полноценном Scrum-процессе.

Мы продолжаем серию материалов Как мы создаем продукт (#1, #2). В этой статье мы хотим поделиться историей, как проходила наша agile-трансформация. Подробнее остановимся на том, как мы научились делать по-настоящему большие и малопонятные на старте фичи. Расскажем про два новых подхода, которые мы для этого опробовали. Для тех, кто знаком с терминологией, речь пойдет о Take a bite и Команде Тигров.

1. MultiDozor

1.1 Короткая предыстория

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

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

1.2 У нас проблема

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

Для так называемого подготовительного процесса мы собрали специальную исследовательскую команду из бизнес-аналитиков, архитекторов и специалистов по UI /UX. Их основной задачей было собрать с рынка ожидания клиентов от распределенных DLP и как-то приземлить их на реалии Solar Dozor. Начался процесс, который в Agile называется Discovery: исследуем потребности клиента, выдвигаем гипотезы, как закрыть их с помощью нашего продукта, получаем по ним обратную связь. В процессе мы выкидываем большую часть гипотез, оставляя в сухом остатке процентов 20. Где-то через два-три месяца такой работы туман стал рассеиваться. Начали вырисовываться очертания конечного решения. Фича выглядела все объемней и объемней, а ведь мы даже не начали ее детальную проработку. Ничего столь грандиозного по масштабу изменений в продукте мы никогда не делали. Проблема создания модуля MultiDozor была в том, что он технически очень сложный. Помимо проработки аспектов для решения бизнес-задач заказчиков, перед нами вставало много технических вопросов, принять однозначное решение по ряду которых не могла даже наша команда опытных архитекторов.

1.3 Решение есть по частям

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

Поэтому мы решили пойти другим путем. Воспользовались подходом, который в Agile рекомендуют в таких случаях Take a Bite.

Рисунок: принцип Take a Bite (источник: https://less.works/)Рисунок: принцип Take a Bite (источник: https://less.works/)

Согласно концепции Take a Bite, лучше отказаться от сильного дробления большой и малопонятной на начальном этапе Истории. Вместо этого взять небольшую и относительно понятную ее часть и реализовать за спринт. Логика в том, что во время этой работы мы больше узнаем о сопутствующих и связанных проблемах и их решении. После окончания работы можем показывать результаты стейкхолдерам и получать раннюю обратную связь. Наш горизонт как технических, так и бизнес-знаний за этот спринт расширится, и в следующий мы сможем взять еще один кусочек небольшой и понятной работы. Таким образом мы ориентируемся на как можно более раннее снижение технических рисков (мы технически не можем сделать то, что от нас хотят) и бизнес-рисков (мы сделаем то, что клиенту реально не надо). Мы можем совершать корректировки движения относительно дешево потенциальные потери окажутся не больше работы, проделанной за один двухнедельный спринт.

Собственно, в истории с MultiDozor мы пошли таким путем. После того, как аналитики сформулировали базовую концепцию нового модуля и первый пул основных потребностей заказчиков (для начала мы выбрали трех самых крупных и активных с точки зрения получения обратной связи), мы стартанули первые спринты.

1.4 Ура, мы были правы

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

И остановили спринт

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

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

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

1.5 Что еще нам помогло?

Коротко отмечу, что помимо изменения работы с требованиями системных аналитиков в рамках работы над MultiDozor мы изменили также способ организации нашего труда. Перешли к многокомандному Scrum. Для масштабирования выбрали фреймфорк Less (подробнее о нем можно почитать по ссылке). Если коротко, то у нас появилось Общее Планирование, Общие PBR (встречи, где мы вместе прорабатываем истории для будущих спринтов), Общий Обзор Спринта и, конечно, Общая Ретроспектива. Подробно останавливаться на всем этом не буду, отмечу, что, например, без Общих PBR мы не смогли бы так эффективно делиться знаниями и брейнштормить, а без Общих Ретроспектив оперативно решать вопросы коммуникации.

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

2. UBA

2.1 Короткая предыстория

Вторая наша история про Dozor UBA. Про эту систему мы уже несколько раз вам рассказывали тут и тут. Если коротко, то наши коллеги-математики придумали крутую модель, как автоматизировать обнаружение отличий в поведении людей от своих собственных паттернов и от паттернов отдела или всей организации. Коллеги построили прототип на питоне, доказавший корректность их гипотез. А дальше нам надо было все это интегрировать в работающий продукт Solar Dozor с его многочисленными сервисами, потоками данных и устоявшимся UI. Причем сделать так, чтобы понятные только математикам концепции были визуализированы доступно и прозрачно для наших основных пользователей специалистов по безопасности.

2.2 У нас проблема

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

2.3 Решение Команда тигров

Мы пошли путем создания Команды Тигров (Tiger team). Это временная scrum-команда, которая собирается для решения нерешаемых задач.

Нам этот термин попался на глаза в книжке по Less, но появился изначально, кажется, из космонавтики если перевести примерно определение, данное в 1964-м году, это команда технических специалистов, отобранных за их опыт, энергию и воображение, которым поручено выявить и устранить все возможные источники сбоев в подсистемах космического корабля (источник).

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

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

Итак, команда собрана, пора стартовать

2.4 И снова едим по кусочку

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

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

На первом Sprint Review мы могли показать в интерфейсе только пару цифр, полученных как результат предварительных расчетов для показателей (как и на чем мы считали, подробнее описано в статье про СlickHouse). Но это уже лучше, чем в начале, когда не было ничего. Это уже был успех! Во внутрянке для показа этой цифры уже крутились нужные шестереночки-сервисы. И это многого стоило.

К концу двух недель появились мысли, что еще можно сделать. Процесс разработки начал набирать обороты.

Расчеты и внутренние сервисы это хорошо, но пришло время задуматься и о UI.

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

А вот и несколько этапов его эволюции:

Рисунок: первый эскиз интерфейсаРисунок: первый эскиз интерфейсаРисунок: прототип интерфейса на питонеРисунок: прототип интерфейса на питонеРисунок: интерфейс в prodРисунок: интерфейс в prod

Со второго спринта начались уже более бурные обсуждения ожиданий бизнеса, на Sprint Review появилась обратная связь совершенно другого уровня а это очень важно для адаптации.

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

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

2.5 Куда делись тигры?

Примерно через квартал мы успешно выпустили модуль на рынок.

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

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

Рисунок: настоящая схватка Scrum :)Рисунок: настоящая схватка Scrum :)

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

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

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

Выводы

  1. Agile и большие фичи/истории совместимы и даже очень хорошо.

  2. Описанный подход Take a bite позволяет экономить кучу времени и денег.

  3. Чем малопонятней фича на входе, тем Take a bite эффективнее по сравнению с традиционным водопадом.

  4. Этот подход позволяет готовить к релизу именно то, что нужно клиенту, а не то, что получилось и уже тяжело исправить.

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

  6. Ну, и, наверное, самое главное это эмпирический процесс (Scrum является только одним из подходов, использующих этот процесс), а не жесткий регламент или методология. Не бойтесь проводить различные эксперименты, пробовать разные подходы и оставляйте то, что сработало, выкидывая, то, что не оправдало ожиданий. И то, и другое успех! У вас в любом случае остается багаж накопленного опыта и знаний.

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

Подробнее..

Самодиагностика команды разработки

20.05.2021 08:20:21 | Автор: admin

Как любая скрам-команда каждый день, мы стараемся быть лучше чем вчера. Мы делаем лучше наш продукт, мы вместе развиваемся как команда и, конечно же, мы растём личностно и профессионально. Очевидно, что одной лишь веры в то, что завтра мы станем быстрее/выше/сильнее не достаточно. Нужно понимание своих слабых и сильных сторон, а так же осознание того, что нам нужно здесь и сейчас, а что нам понадобится через неделю/месяц/год.

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

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

Опросы

Да, это очередные опросы, но в нашем случае они приносят пользу и каждую ретроспективу поднимаем вопрос, нужны ли нам они или уже нет. У нас спринты длятся 2 недели, поэтому у нас есть еженедельный опрос и опрос в конце спринта.

Еженедельный опрос

В конце каждой недели мы получаем опросник на 30 секунд с вопросами: как часто у вас не было сил выполнять работу? Получал ли удовольствие от задачи? Сколько часов переработал? На выходе мы строим график для всей команды в динамике за последние 6 недель и обсуждаем на ретроспективе.

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

Опрос в конце спринта

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

Опросы раздражают

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

Мотивация

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

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

Как минимум, воодушевление пришло когда люди узнали кастомеров, например, "О, это мой банк", "У этих 3-х компаний больше миллиона сотрудников", "У меня машина этой компании" или "Я читаю финансовые новости от них". Думаю, в компаниях, названия которых встречаются хотя бы раз в месяц дела обстоят лучше.

Боли (от выполнения ручной/неудобной работы)

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

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

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

  • Опять же посмотреть в Jira и рассмотреть что мы можем делать лишнего, или что уже не актуально и можно упразднить. Например, мы рассматривали релиз-тикеты и пытались понять какие моменты мы можем делать быстрее. Так мы обнаружили, что security scan кода занимал по 20-30 минут, мы подумали, что можно делать всё проще и в итоге сейчас это занимает около 5-10 минут.

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

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

  • Изучение будет происходить в паре/тройке. Так и интересней, и если кто-то уйдёт в отпуск - работа не встанет.

  • Пары/тройки будут меняться в будущем. Чтобы команда не дробилась на небольшие "кружки по интересам" и оставалась одной командой.

  • Внутри пары/тройки нет ограничений на источник обучения. Кому-то могут нравиться курсы с LinkedIn, кому-то с Udemy, а кто-то вообще нашёл крутой разбор темы на YouTube на своём родном языке.

Больше болтовни

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

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

Также мы заметили, что когда люди включают web-камеру - они более искренне и более разговорчивы. Если вся команда не разговорчива, мы просто используем Wheel Of Names и там уже рандомом выбираем кто будет говорить.

Фидбеки

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

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

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

  • Кастомеры задавали вопросы на одни и те же сообщения в логе. Суть в том, что в логе мы печатали что-то вроде "Module: service XXX call, RC = Y, RSN = ZZ". Т.к. это вообще не понятно никому, L2 выстраивали у себя сводную таблицу таких сообщений, чтобы отвечать кастомерам. Если какая-то новая комбинация - то это шло дальше в L3 (к разработчикам). Решением было простым: мы просто написали функцию которая по кодам печатает user-friendly сообщения с полным описанием причины проблемы.

  • Кастомеры находили уже пофикшенные баги. С каждым релизом мы не так много внимания уделяли описанию проблем. В итоге, когда пользователь встречал баг, он открывал описания выпущенных релизов и искал там свою проблему - разумеется он там ничего не находил и писал в саппорт. Ребятам из L2 приходилось лезть в нашу Jira и они пытались найти баги, похожие на кастомерские. Решение банально - мы стали лучше описывать баги с их симптомами в релизах. Кастомеры стали меньше писать в саппорт, т.к. находили свои баги в описаниях релизов, а если уж и открывалось, L2 на них почти всегда могли ответить самостоятельно и быстро.

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

Ежедневный отчёт

У нас каждый день скрам-мастер, в конце рабочего дня, в канале команды в слаке публикует суточный отчёт, который описывает текущие горящие темы, блоки команд, проблемы в команде/продукте и т.п. Этот отчёт полезен как для команды, так и для менеджмента. Во-первых, если кто-то из команды имеет проблемы и видит, что его проблема там не описана - он идёт к скрам-мастеру и отчёт обновляется. Во-вторых, все видят что происходит сейчас в команде, у менеджмента есть актуальный, обобщённый отчёт, и им не нужно дёргать людей, чтобы получать ответы на свои вопросы. С помощью этого отчёта мы пытаемся добиться прозрачности и выявлять блоки как можно раньше, чтобы избегать случаев "У нас уже месяц всё хорошо, но 4 недели назад случилась проблема и мы не успеваем".

Я хочу ещё раз подчеркнуть, что этот "отчёт" - был создан внутри команды для нас самих же и не занимает больше 5 минут в день для его поддержания.

Свои метрики

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

Например, кастомерские проблемы идут в приоритет и нам, как команде, очень важно, чтобы оно в L3 находилось как можно меньше времени. Поэтому мы стараемся отвечать на проблему, либо находить реальную причину (например, баг) как можно быстрее. Менеджмент всего лишь следит, чтобы ответ был не дольше чем за 2/7 дней (в зависимости от важности проблемы - у них свои метрики).

Частота "незапланированных" задач. Каждый спринт у нас случаются не запланированные таски, возникающие после старта спринта, которые откладывать на 1-2 недели нет возможности. Мы пытаемся отслеживать такие вещи, смотреть сколько в среднем мы тратим на них время и каждый спринт откусывать кусок пирога для этой активности. Тем самым, нам проще выполнять наши собственные коммитменты и тогда команда становится более предсказуемой.

Мы используем и другие метрики, включая самые очевидные: процент покрытия кода юнит-тестами, покрытие QA тестами функционала продукта, время жизни пулл-ревквеста или velocity команды.

Больше правил

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

Можно долго спорить и ругаться, например, что лучше: табы или пробелы, можно назначать митинги для их обсуждения, создавать новые чаты, ругаться в пулл-реквестах, а можно просто написать правило "только пробелы" и просто следовать ему. Кто-то будет недоволен, но теперь это правило, и его не обсуждают, ему просто следуют. Поэтому, рекомендую задокументировать всё, что связано с правилами написания кода. А ещё лучше, посоветовать команде почитать какой-нибудь Code Complete, чтобы разработчики (особенно начинающие) имели представление откуда эти правила берутся.

Правила помогают разделять белое и чёрное, избегать конфликтов и иногда упрощать жизнь. А иногда, наоборот, усложняют жизнь. Ввод любого нового правила означает снижение доверия к индивидуумам, снижение доверия означает рост неэффективности, рост неэффективности приводит к увеличению времени разработки.

Также, правила должны подвергаться пересмотру. Например, в какой-то момент времени у нас случилось несколько кастомерских проблем из-за релиза, баги в котором могли быть замечены аж на трёх этапах: Разработка (code review), Просмотр билда разработчиками, и уже QA. На всех трёх этапах можно было предотвратить ошибку. Разумеется, после этого инцидента все этапы были ужесточены. В итоге то, что раньше могло занимать до 5 дней, стало занимать до 10 дней. Со временем все ужесточения были пересмотрены. Некоторые до сих пор остались, просто был изменён процесс чтобы действие занимало меньше времени, что-то было упразднено, а что-то наоборот добавилось.

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

Ответственность на всех

В нашей команде мы стараемся играть в "трёх мушкетёров", т.е. ответственность за всё лежит на ВСЕЙ команде, никто не будет осуждать члена команды вне команды. Если кто-то один облажался и это привело к каким-то последствиям, то всё равно виноваты все, потому что:

  • Плохие вещи случаются. Нельзя запланировать и предвидеть всё.

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

  • Очень просто спихнуть всю ответственность на кого-то одного и осудить его. Если такое происходит часто, то все понимают, что рано или поздно это случится с ними и уходит доверие, что приводит к росту издержек, снижению эффективности ... ну вы поняли.

  • Обвинения не решают проблем. Вообще никаких.

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

  • Женщину, которая в полной темноте переходила дорогу в неположенном месте?

  • Водителя автомобиля с автопилотом, который вряд ли сам среагировал бы?

  • Компанию, которая разрабатывает автопилот?

  • Разработчиков, кто писал код для автопилота?

  • QA кто выпустил этот код в прод?

Субъективно, тут виноваты все, либо никто. Но, очевидно, что виновные есть, т.к. в итоге женщина скончалась. Значит виноваты все.

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

Team Building

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

Заключение

Выбрав фреймворк как Scrum, Kanban, Lean и т.д. глупо надеяться что все проблемы разрешатся, все будут мотивированы, счастливы и довольны. Внутри команды не стоит надеяться, что кто-то другой решит ваши проблемы, особенно, если вы о них не говорите.

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

Подробнее..

Как масштабировать разработку при 400 000 RPM и не надорваться

04.06.2021 16:20:58 | Автор: admin
Если бизнес идет вверх, тозапросы инагрузка наразработку увеличиваются вразы. Рано или поздно каждый управленец сталкивается свыбором издвух крайностей: встать насторону бизнеса, двигать продукт идемотивировать разработчиков бесконечным техдолгом или дать свободу разработке ипотерять контроль над задачами бизнеса.

Mindbox 15лет развивает B2B-продукт ивырос с3до70человек вразработке. Мытестировали разные подходы кмасштабированию иготовы поделиться опытом, чтобы вам непришлось наступать натеже грабли. Ниже расскажу, как попробовали полную автономию команд ицентрализацию, роняли надежность, демотивировали команды, как врезультате сэтим справились ивыработали свою систему масштабирования.

По материалам выступления на Agile Days 2021:



Надежность как ядро разработки


Чтобы оценить, окаких масштабах разработки инагрузке пойдет речь, расскажу оразмере компании.

ВMindbox одна изсамых нагруженных разработок вРоссии, нопри этом она сохраняет высокую надежность. Когда покупатель пробивает чек накассе вБургер Кинге или аптеке Ригла, транзакция идет кнам. За200 миллисекунд мырассчитываем суммы иотвечаем кассе. Если сервис упал, томного людей повсей стране 24/7 становятся несчастны.

Запоследние 34 года бизнес растет по4050% вгод инагрузка удваивается ежегодно. Внешне всё отлично, ноуMindbox был длинный период становления, который влиял намасштабирование разработки.

Масштаб бизнеса и разработки




Эволюция разработки




Как работает автономия ицентрализация разработки


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

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

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

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

Как внедрили автономию


С2007 по2013 год было мало клиентов ибизнес рос медленно, потому что писали большой исложный продукт. При этом управление разработкой было простым: один главный бизнес-эксперт иглавный архитектор это я и34команды. Делал статусы раз внеделю, потом раз вдве недели ходил покомандам эффективно илегко.

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

Бирюзовая компания вРоссии: открытые зарплаты, самоуправление, прозрачность иошибки
Фредерик Лалу: Открывая организации будущего

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

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

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

Как внедрили централизацию


Централизовали управление. Прочитали книгу оLeSS (Large Scale Scrum), сходили натренинг ирешили централизовать разработку: внедрить общий roadmap, единое управление иразгрумить эпик надежности.

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

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

Так мысоздали роль CTO (chief technical officer), хотя доэтого небыло менеджмента, отвели30% ресурса натехдолг ивнедрили LeSS. Это значит, что70% разработчиков занимались roadmap бизнеса, а30% техническим roadmap, который определяет CTO. Врезультате техдолг начал сокращаться, имыувидели положительные изменения.

LeSS Scrum набольших масштабах

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

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

Главное, что год мыпрожили врежиме LeSS изаметили негативные эффекты для компании. Инженеры именеджеры попродукту были демотивированы. Уинженеров небыло домена ичувства собственности, как увавтономных команд: три месяца они работали над одним продуктом, потом три месяца над другим. Менеджеры попродукту загрустили, потому что roadmap планируется централизованно иtime tomarket стал огромным. Нельзя было взять ивнедрить небольшую доработку для клиента, потому что roadmap управляют централизованно.

Как нашли баланс между автономией ицентрализацией


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

Вернули команду инфраструктурной платформы. Фактически инфраструктура это тоже внутренний продукт, аCTO выполняет роль менеджера попродукту, поэтому выделили отдельную команду под инфраструктуру.

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

Оставили30% ресурса команды налокальный техдолг. Мыдоговорились одвухуровневом разделении. Наверхнем уровне30% всего ресурса разработки отдали CTO наинфраструктурную команду итехнический roadmap. Ещё30% отдали натехдолг, который приоритезирует команда. Фактически смомента, когда начались проблемы снадежностью имасштабированием, почти50% всего ресурса это технические задачи.

Техдолг ~30% платформы и 30% команды


около 50% в целом



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

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


Из LeSS оставили кросс-командный рефайнмент, чтобы снять риск монолита и управлять roadmap

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

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

Нарушения SLA среднего клиента вмесяц надежность повышается




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

Создали роль Scrum-мастера. После того как разобрались срисками вдецентрализованном roadmap, справились стехдолгом инадежностью, решили повышать эффективность разработки. Для этого создали роль Scrum-мастера, который собирает весь опыт разработки (developer experience) изаносит вспециальную форму все препятствия ипричины, мешающие разработке. Потом поаналогии состатусами понадежности Scrum-мастера централизованно обсуждают сCTO задачи замесяц, приоритезируют ихичасть добавляют втехдолг.

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

Виртуальная команда (круг) управления




Ритуалы управления



Круг управления помогает аккумулировать кросс-командные аспекты: надежность, стоимость железа, найм, developer experience. Для этого проводятся встречи ритуалы управления


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

Мызнали, что скорость иroadmap нельзя измерять, потому что есть проблемы стехдолгом иэто только демотивирует разработчиков. Науровне стратегии разработки мысформулировали, что цель разработки оптимизировать непрерывный запуск продуктов (time tomarket) врамках ограничений надежности, стоимости железа ибез увеличения технического долга. Ировно такиеже ожидания сформировали для команды. Команда должна непрерывно поставлять фичи, увеличивать time tomarket, нопри этом поддерживать определенные обязательства понадежности, SLA истоимости.

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

Показатель эффективности


врамках SLA, стоимости железа ибез увеличения техдолга
Разработка Команда
Непрерывный запуск и оптимизация time to market новых продуктов, которыми можно гордиться Непрерывный релиз и оптимизация time to market инкрементов, которые принял клиент на продакшене


Какую выработали систему масштабирования разработки


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

Разумное регулирование общего. Как ядро оставили общие задачи, над которыми должны работать централизованно: roadmap монолита, надежность иинфраструктура, стоимость железа иdeveloper experience. Если нет общих знаний отом, как создаются базовые вещи, топеремещение разработчиков между командами будет затруднено, код будет дублироваться иесть риск потерять эффект масштабной разработки, когда каждая команда существует изолированно отвсех.
Подробнее..

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

18.06.2021 14:19:30 | Автор: admin

Часть 1. Вводная зачемная.

Привет. Я Лена, скрам-мастер в Ренессанс страхование. Мы с коллегами в командах реализуем классные фичи в страховании и рады, когда наш функционал действительно получается востребован. Стараемся еще, конечно, чтобы получался он не только качественно, но и быстро, как это обычно требуется в современном мире.

Однако в прошлом году мы столкнулись с разработкой довольно сложного продукта по автокаско частных лиц, в реализацию которого оказались вовлечены 4 фиче-команды, множество разных групп пользователей внутри компании и внешние пользователи.

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

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

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

  • собрать все произошедшие за год события на одном борде;

  • получить мнения всех участников процесса: и ребят из фиче-команд, и заказчиков, и пользователей продукта;

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

  • определить те проблемы / достижения, которые важны для всех команд в целом;

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

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

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

Часть 2. Как это было.

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

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

План на ретроспективу у нас был такой:

1. Небольшая разминка

2. Определение хороших сторон работы над продуктом и моментов, которые нужно улучшать / менять

3. Голосование

4. Поиск корневых причин выбранных карточек методом "5 почему"

5. Определение идей по работе с выявленными причинами

6. Сбор обратной связи по итогам ретро

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

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

Теперь чуть подробнее про каждый из этапов:

1. Небольшая разминка.

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

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

* Выбрать тему

* В каждую команду добавить фасилитатора

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

При делении на группы - в нашем случае отдельные комнаты в зуме - в каждой комнате был фасилитатор.

Несколько минут на обсуждение - и далее кто-то от группы рассказывает итог дискуссии.

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

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

2. Определение хороших сторон работы над продуктом и моментов, которые нужно улучшать / менять.

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

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

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

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

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

3. Голосование.

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

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

4. Поиск корневых причин выбранных карточек методом "5 почему".

Обсуждать выигравшие карточки мы решили с помощью метода "5 почему". Про сам метод можно почитать здесь: http://personeltest.ru/aways/habr.com/ru/company/renins/blog/554896/

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

Изначально выигравшие в голосовании карточки были размещены в 4 блока в отдельной зоне на доске. Далее мы вновь поделили участников ретро на 4 группы. Правило "по одному фасилитатору в каждой группе" осталось неизменным.

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

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

5. Определение идей по работе с выявленными причинами.

Итак, получили причины. Что же дальше?

А дальше для каждой причины нужно было выработать идеи, как в будущем работать при возникновении подобного поинта, и, самое главное, кто, что и когда должен сделать, чтобы идея была реализована. Для работы с описанием идей и дальнейших шагов по ним выбрали самый простой метод 4 вопросов: Зачем мы что-то делаем, Кто что-то сделает, Как это нужно сделать, Что именно нужно сделать.

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

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

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

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

6. Сбор обратной связи по итогам ретро.

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

Данная итерация - финал большой сложной проведенной работы.

ПЕРЕРВ

Были. Не упоминала по тексту, так как перерывы стоит регулировать в зависимости от длительности каждого блока. У нас они были запланированы изначально по 10 минут каждые 1 - 1,5 часа.

Часть 3. Результативное "что дальше-то".

Вот мы собрали список проблем, определили их причины, накидали идеи по улучшению процесса, а что дальше?

На самом деле дальше самое интересное - воплощение озвученных поинтов в жизнь.

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

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

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

Кроме трека прогресса по идеям с ретро в экшн-поинтах у нас проведение кросс-командных ретро чаще, чем раз в год. Коллеги позитивно отозвались именно о таком формате ретроспективы. Это одна из причин, почему таким форматом было решено поделиться здесь.

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

1. Не затягивать с ретро на несколько команд.

2. Делать такого формата ретро долгими, на весь день.

3. При делении на группы не определять всех специалистов одной роли в одну группу.

4. Давать больше времени на поиск причин проблем и на генерацию идей.

5. Звать всех, кто может быть ответственными за реализацию идей, на такие встречи.

Это несколько поинтов для улучшения на будущее и нам в том числе.

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


Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru