什麼是看板方法
看板方法採用了精益的思維範式,將軟件開發視爲一個價值流(Value Stream),並且基於拉模式來驅動其流動。
看板方法的各種設計元素,爲質量和過程中的問題提供了可見性,能夠迅速暴露價值流中影響效能的問題,從而引導團隊專注於解決問題以維護穩定的流動。
通過幫助軟件團隊建立穩定的工作節奏,實現始終如一的可靠交付,看板方法能夠在開發團隊與客戶、相關部門、供應商、價值流下游合作伙伴之間建立信任關係,從而建立具有高度協作、高度信任、高度授權和持續改進特徵的組織文化。
-----摘自《看板方法:科技企業漸進變革成功之道》
上述文字是對看板模式一段比較恰當的描述,使用看板的方式進行開發,確實可以有效控制團隊的開發進度,儘早暴露問題,使軟件的價值流能在可視的狀態下進行流轉。它將任務分解成若干個用戶故事卡片,卡片被認領後就可以進行開發到測試到發佈的流轉,這些過程集中在一張看板中,是不是非常有趣的事情?
產品實踐
需求拆分
- 足夠小:保障持續或迭代的交付
- 端到端:保證交付有意義的價值
- 相對獨立:便於集成,和靈活安排
- 拆分完還能看整體的架構,才能確保整體價值的最大化
核心目標
- 業務規劃層:按業務場景規劃需求;對齊開發進度,迭代快速交付;形成業務閉環
- 產品交付層:開發任務向產品需求對齊,快速高質量的交付有用的需求,持續提升交付效率
業務規劃看板
- 基於產品組織和規劃業務場景,快速交付高價值場景
- 待規劃即需求池概念
- 已規劃使用
版本Tag
快速排期,並提供開發團隊快速認領 - 已發佈階段,展示所有已完成的所有需求
產品交付看板
- 基於看板需求排期,對齊開發進度,即時發現和出現問題,確保高質量和順暢的需求交付
交付閉環流程
- 當團隊成員認領卡片後,可以將其拖拽到對應列,代表這個任務已經完成了上個過程,可以進入到目前的階段了。每天根據進度填寫任務的百分比及簡單的產出物。
- 進入到測試階段的時候,測試過程提交的Bug需要關聯到對應任務,直到所有的缺陷被消除後纔可以將任務卡片拖到 “待發布” 列。
- 所有的卡片經過上述的流轉到達“已發佈”列,即可以講所有的功能進行發佈,並邀請需求人員試用。
- 有時候遇到特殊情況而導致阻塞,這時候需要設置阻塞停靠站,暫時將任務擱置,如果該任務不會影響主體的流程開發,那麼可以先不予處理,待主體流程上線後,總結所有的開發阻塞任務轉到下一個版本進行開發。
- 區分不同的任務優先級,優先解決最高的。
- 以下釘釘通知 @相關人員。分別是:
- 產品人員指派需求(已選擇)
- 開發同學接受任務(待開發)
- 測試同學接受新任務,即研發人員提測(待測試)
附 YouTrack 釘釘通知工作流源碼:
var entities = require('v1/entities');
var http = require('v1/http');
var workflow = require('v1/workflow');
var DINGDING_ROBOT_URL = 'https://oapi.dingtalk.com';
var DINGDING_ROBOT_URL_DIRECTION = '/robot/send?access_token=xxxxxxxxx';
exports.rule = entities.Issue.onChange({
title: 'cpjf-state-changed-notify-dingtalk',
guard: function(ctx) {
var issue = ctx.issue;
return ctx.issue.fields.isChanged(ctx.State) && (ctx.issue.fields.State.name === 'F-已選擇' || ctx.issue.fields.State.name === 'F-待測試' || ctx.issue.fields.State.name === 'F-待開發');
},
action: function(ctx) {
var issue = ctx.issue;
var issueId = issue.id;
var issueName = issue.summary;
var issueDescription = issue.description;
var issueLink = issue.url;
var userName = ctx.currentUser.fullName;
var nowState = issue.fields.State.name;
var contextStr = "";
var payload = "";
var nowStateArr=nowState.split("-");
var result = {
'魏xx': '178xxxx9463',
'沈xx': '136xxxx0845',
};
var atPersons = "";
var atPersonsPhone = "";
var notifyArr = [];
if (issue.fields.指派人 !== null && issue.fields.指派人.size > 0) {
for (var i = 0; i < issue.fields.指派人.size; i++) {
var person = issue.fields.指派人.get(i).fullName;
var phone = result[person];
atPersons += "、 " + person;
atPersonsPhone += "、 @" + phone;
notifyArr.push(phone);
}
}
atPersons = atPersons.substring(1);
atPersonsPhone = atPersonsPhone.substring(1);
contextStr = " #### 產品交付 # " + issueId + " \n" +
" ##### **名稱**:" + issueName + "\n\n" +
" ##### **狀態**:" + nowState + " \n\n" +
" ##### **鏈接**:[查看詳情](" + issueLink + ") \n" +
" ##### **操作**:" +"[" + userName + "] 同學將任務指向" + atPersonsPhone + ",請儘快處理! \n\n" +
" > ###### 技術團隊 \n";
payload = {
"msgtype": "markdown",
"markdown": {
"title": "產品交付通知",
"text": contextStr
},
"at": {
"atMobiles": notifyArr,
"isAtAll": false
}
};
var connection = new http.Connection(DINGDING_ROBOT_URL);
connection.addHeader({
name: "Content-Type",
value: "application/json; charset=utf-8"
});
connection.postSync(DINGDING_ROBOT_URL_DIRECTION, [], JSON.stringify(payload));
},
requirements: {
State: {
type: entities.State.fieldType,
},
指派人: {
type: entities.User.fieldType,
multi: true,
}
}
});
參考資料:
[1] 商城研發POP平臺著.京東系統質量保障技術實戰.北京:電子工業出版社,2017.
[2] 阿里-何勉-從持續交付到業務創新.pdf