Скромная дискуссия по мотивам моей вчерашней публикации на тему прогнозирования времени на разработку, в очередной раз пробудила во мне ощущение некоей неправильности на тему использования чисто умозрительного подхода к разбиению истории на задачи. На мой взгляд, когда мы пишем задачи в списке, даже когда мы используем объектную или функциональную терминологию, мы не вполне представляем себе все модули с кодом, которые нам потребуется разработать или доработать.
Тогда мне пришла в голову идея, после разбиения пользовательской истории на задачи, попробовать набросать черновики модульных тестов, для классов или методов, которые я упоминаю в задачах. Мне даже не нужно выдумывать пользовательскую историю, я могу взять одну из моей текущей работы. Например:
Как система, я хочу отправить на проверку KYC сервису персональные данные пользователя
И список задач к ней:
Реализовать получение персональных данных пользователя из локальной базы- Реализовать создание папки в KYC сервисе с указанием в метаданных папки персональных данных пользователя
- Реализовать создание запроса на проверку данных папки в KYC сервисе
- Реализовать сохранение информации о запросе на проверку персональных данных в локальной базе
Если за продолжительность одной итерации команды считать две недели, то один-два дня вполне можно потратить на ее планирование, но не в виде совещания с умозрительными рассуждениями и покером, а в основном в виде обычной программистской деятельности в виде написания тестов в некоем минимальном виде. С последующей оценкой времени на реализацию функциональности уже в полном масштабе.
В первом приближении выглядит как со всех сторон профит. Пишем код и не теряем времени на коллективные рассуждения. И строим оценки на основе хотя бы минимального количества кода, пощупав так сказать требования заказчика руками.
Поскольку для первой задачи из вышеозначенного списка у меня есть уже оттестированная рабочая реализация, то перехожу ко второй задаче и начинаю делать черновик теста для метода, выгружающего данные в KYC сервис:
describe('upload personal info', () => {
const HttpFake = require('HttpFake');
const http = new HttpFake();
const store = require('../../src/store');
const handler = require('../../src/kyc/createFolder');
const rules = require('../../src/importRules');
const httpOptions = {
hostname: 'http://kycservice',
port: 80,
path: '/api/folder',
body: {
meta_data: {
firstName: 'Jack',
lastName: 'Sparrow',
birthDate: '06/01/1740'
}
},
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
const httpResponse = {
statusCode: 200,
body: {
folder_id: '0x382974',
meta_data: {
firstName: 'Jack',
lastName: 'Sparrow',
birthDate: '06/01/1740'
}
},
headers: {
'Content-Type': 'application/json'
}
};
let context = null,
handle = null;
beforeEach(() => {
context = {
http,
store,
rules
};
handle = handler.bind(context, ['folder']);
const person = {
firstName: 'Jack',
lastName: 'Sparrow',
birthDate: '06/01/1740'
};
store.dispatch({ type: 'PERSON', person });
});
it('should assign store folder state value', () => {
http.expect(httpOptions);
http.returns(httpResponse);
const assert = checkExportResult.bind(context, [done]);
store.subscribe(assert);
handle();
});
function checkExportResult(args){
const folder = store.getState().folder;
if(folder === null)
return;
expect(folder.folder_id).toEqual('0x382974');
expect(folder.meta_data.firstName).toEqual('Jack');
expect(folder.meta_data.lastName).toEqual('Sparrow');
expect(folder.meta_data.birthDate).toEqual('06/01/1740');
const checkIsCompleted = args[0];
checkIsCompleted();
}
});
Модульный тест второй задачи разложился аж в 100 строчек кода, и на его реализацию у меня ушло около часа времени. При этом первые пять строчек на некоторое время погрузили меня в размышления на тему "как бы мне реализовать имитацию отправки http запросов?", пока я не вспомнил что у меня уже есть некая псевдо-http
реализация, имитирующая как раз отправку нужных мне POST
запросов. Хорошо. Вот у меня есть тест. Стало ли мне понятнее сколько может потребоваться времени на реализацию нужной функциональности?
На самом деле да. Эта задача на мой взгляд очень похожа на задачу с запросом данных из базы, и я уже принял решение что одного рабочего дня мне вполне хватит чтобы реализовать в таком же подходе отправку POST
запроса с сохранением результатов в контейнер состояния. А поскольку у меня уже есть успешный опыт с отдельной реализацией правил обработки данных в рамках выполнения запроса, то я решил что реализую новый набор правил, которые я буду использовать при отправке POST
запросов.
Две последующие задачи из списка кажутся мне очень похожими, так что писать тесты для них прямо сейчас я не вижу особого смысла, потому что мозг уже принял в качестве оценки:
Реализовать получение персональных данных пользователя из локальной базы- Реализовать создание папки в KYC сервисе с указанием в метаданных папки персональных данных пользователя — 8ч
- Реализовать создание запроса на проверку данных папки в KYC сервисе — 8ч
- Реализовать сохранение информации о запросе на проверку персональных данных в локальной базе — 8ч
Ну и поскольку следующие пользовательские истории в списке у меня из этой же оперы, просто в POST
запросах будет не JSON
, а бинарные данные, то я автоматически принимаю что могу за двухнедельную итерацию реализовать три пользовательских истории.
funca
"- Какие стадии проходят задачи на вашем проекте? — Отрицание, гнев, торг, депрессия и принятие." ?
Оценки как и цену надо называть в конце, когда вы уверены в сделке. Для начала определите две штуки: definition of ready — что вам нужно, чтобы взять задачу в работу и definition of done — что должно быть, чтобы считать её завершенной. Пока, вы не уверены, не давайте ни каких эстимаций. Запросите время на spike для согласований, исследований, прототипирования и самообразования. Для эстимаций существует куча техник, разной степени замороченности www.tutorialspoint.com/estimation_techniques/index.htm. TDD может помочь найти недостающие требования (чисто по дедукции). Но вообще говоря TDD это инструмент кодинга и поэтому на эстимации влияет лишь косвенно.