2018年有寫(xiě)過(guò)一篇文章提到IT部門的業(yè)務(wù)和開(kāi)發(fā)之爭(zhēng):Who am I?,居于當(dāng)時(shí)的情況我想了一些解決方案,一年過(guò)去了,今天補(bǔ)上后續(xù)事件的發(fā)展。
上文說(shuō)到,我們公司有一個(gè)讓項(xiàng)目中的各個(gè)角色“搞不清自己是誰(shuí)”的關(guān)鍵問(wèn)題,其實(shí)追根溯源會(huì)發(fā)現(xiàn)在招聘的根源上這個(gè)問(wèn)題必然會(huì)產(chǎn)生。公司喜歡招BAT、華為、SAP、IBM等大廠出來(lái)的解決方案架構(gòu)師和開(kāi)發(fā)工程師,但招進(jìn)來(lái)后往往又沒(méi)有對(duì)應(yīng)的崗位,于是很多招進(jìn)來(lái)的人不得不學(xué)習(xí)其他類似甚至不相關(guān)的業(yè)務(wù)或開(kāi)發(fā)方向。如我,是以Android移動(dòng)端開(kāi)發(fā)工程師的定位招進(jìn)公司的,但進(jìn)公司到現(xiàn)在過(guò)了2年半的時(shí)間,我可以“自豪”的說(shuō)“我從來(lái)沒(méi)有為公司提交過(guò)一句Android代碼”。
其實(shí)就算招進(jìn)來(lái)的人有對(duì)口的崗位,但如果整個(gè)業(yè)務(wù)流程或開(kāi)發(fā)流程沒(méi)有成套的崗位,那么零散的幾個(gè)“有模有樣”的崗位,并不一樣能發(fā)揮應(yīng)用的作用,最容易的結(jié)局往往就是東施效顰、畫(huà)虎不成反類犬。
也許成長(zhǎng)型的公司必須經(jīng)歷這樣的陣痛。
敏捷其實(shí)還不夠
針對(duì)成長(zhǎng)型的公司,面對(duì)快速變化的需求,大家最容易想到的解決方案往往就是拋棄傳統(tǒng)的瀑布式開(kāi)發(fā),轉(zhuǎn)而擁抱敏捷。我在很多公司(包括大廠)實(shí)施過(guò)敏捷,敏捷從來(lái)都不是隨隨便便就能成功。
用敏捷來(lái)解決公司里IT項(xiàng)目開(kāi)發(fā),并不能解決問(wèn)題。我們的問(wèn)題不是需求變化快,而是缺上很多重要環(huán)節(jié),搞不清自己是什么需求是什么。很多公司搞敏捷開(kāi)發(fā)都是從開(kāi)發(fā)和測(cè)試團(tuán)隊(duì)搞起的,這注定了搞出來(lái)的是先天發(fā)育不良的敏捷,大概率結(jié)局是除了有幾個(gè)“站會(huì)”、“回顧”等會(huì)議形式外一切照舊。
如果我們從開(kāi)發(fā)的角色不能搞定各方“利益人”參與進(jìn)來(lái),敏捷無(wú)從談起。我曾經(jīng)讓業(yè)務(wù)在軟件開(kāi)發(fā)開(kāi)始階段就參與使用每日迭代發(fā)布的產(chǎn)品,卻遭到對(duì)方的質(zhì)疑:“你沒(méi)有經(jīng)過(guò)測(cè)試驗(yàn)證過(guò)沒(méi)有達(dá)到交付要求的產(chǎn)品為什么讓我用?”
也許,我實(shí)施敏捷的能力和手段太差,但現(xiàn)實(shí)中沒(méi)有足夠的利益代表方支持,敏捷很難名副其實(shí)。開(kāi)發(fā)這類角色在敏捷過(guò)程中真的沒(méi)有你想象的那么重要。
我實(shí)踐的兩個(gè)解決方案
但總要做一些自己能做且能發(fā)揮一定影響的事情來(lái)讓項(xiàng)目的開(kāi)發(fā)過(guò)程和結(jié)果變的更好。我努力的方向是讓溝通更有效!既然大家之間有明顯的裂痕(gap),而又無(wú)法推動(dòng)對(duì)方去修補(bǔ)好,那就用技術(shù)解決些裂痕。而爭(zhēng)吵是我首要解決的問(wèn)題。
我其實(shí)很不喜歡爭(zhēng)吵,因?yàn)槲伊私庹Z(yǔ)言的特性,大家有各自的過(guò)濾器,你聽(tīng)到的不一定是你理解對(duì)方要表達(dá)的意思,同理對(duì)方也很難從話語(yǔ)(哪怕是文字)上聽(tīng)懂你要表達(dá)的意思。很多爭(zhēng)吵完全都不能算是真正的爭(zhēng)吵,說(shuō)大家在“各抒己見(jiàn)”、“雞同鴨講”更加合適。
我的解決方式就是讓爭(zhēng)吵的東西所見(jiàn)即所得!
第一:項(xiàng)目管理實(shí)現(xiàn)業(yè)務(wù)需求和代碼“同步”
既然公司沒(méi)有專業(yè)的業(yè)務(wù)和需求分析,寫(xiě)出來(lái)的需求文檔也不規(guī)范,那就讓他們連需求文檔都不用寫(xiě)(其實(shí)是剝奪了他們的某項(xiàng)權(quán)利,但一定要說(shuō)成:幫助你生成需求文檔)。
我們Team自己做了一個(gè)項(xiàng)目管理的平臺(tái),和業(yè)務(wù)談需求的時(shí)候直接按DDD(領(lǐng)域驅(qū)動(dòng)開(kāi)發(fā))的方式將他們的需求分解成對(duì)應(yīng)的問(wèn)題和規(guī)則描述。然后用Python編寫(xiě)的腳手架工具將這些問(wèn)題、業(yè)務(wù)事件等生成模版代碼,而且是可直接部署上線的工程項(xiàng)目代碼。以此彌補(bǔ)業(yè)務(wù)和開(kāi)發(fā)人員之間的裂痕。
而且,當(dāng)對(duì)方需求或問(wèn)題發(fā)生變化時(shí),我們?cè)谶@個(gè)系統(tǒng)上做修改就好,然后開(kāi)發(fā)的模版代碼會(huì)發(fā)生改變,業(yè)務(wù)也可以直接獲得這個(gè)工具實(shí)時(shí)生成的需求文檔(doc格式)。最終,通過(guò)這個(gè)項(xiàng)目管理工具實(shí)現(xiàn)了需求和代碼的同步。
做到這一步有一個(gè)重要的前提:你的項(xiàng)目實(shí)現(xiàn)了自動(dòng)化部署和測(cè)試驅(qū)動(dòng)開(kāi)發(fā)。
為此,我花了很多時(shí)間改進(jìn)公司的項(xiàng)目部署流水線,并通過(guò)引進(jìn)DDD模式讓業(yè)務(wù)代碼和平臺(tái)特性(數(shù)據(jù)庫(kù)、網(wǎng)絡(luò)等)分離,實(shí)現(xiàn)管理平臺(tái)根據(jù)業(yè)務(wù)需求規(guī)則自動(dòng)生成單元測(cè)試代碼,由測(cè)試驅(qū)動(dòng)開(kāi)發(fā)。不要試圖讓沒(méi)有做好代碼高內(nèi)聚低耦合的項(xiàng)目開(kāi)發(fā)人員去寫(xiě)好單元測(cè)試代碼,那樣的單元測(cè)試基本上只有滿足代碼測(cè)試覆蓋率的功能。
也不要試圖讓一般的開(kāi)發(fā)工程師理解代碼分離,直接用模版代碼“強(qiáng)制”隔離,否則累積到后面的意大利面式的代碼能直接讓你崩潰。
第二:開(kāi)發(fā)和業(yè)務(wù)的共同語(yǔ)言:圖
代碼的維護(hù)是一件很讓人頭疼的事情,而“成長(zhǎng)型”的公司肯定喜歡頻繁修改上線后的應(yīng)用,而且“理所當(dāng)然”的認(rèn)為修改、添加個(gè)小功能比原來(lái)的開(kāi)發(fā)不要太容易!但看別人的代碼進(jìn)行項(xiàng)目維護(hù)或二次開(kāi)發(fā)往往比讓自己重寫(xiě)一遍還要痛苦萬(wàn)分。項(xiàng)目是否能成功,除了按時(shí)交付外,是否能有效控制維護(hù)成本、能靈活升級(jí)也很重要。
從業(yè)務(wù)和開(kāi)發(fā)理解的角度,降低項(xiàng)目的業(yè)務(wù)理解認(rèn)知負(fù)荷都很有必要。如果能有效的降低業(yè)務(wù)和對(duì)應(yīng)的業(yè)務(wù)代碼的認(rèn)知負(fù)荷,那么代碼的維護(hù)和改動(dòng)也將變得更容易和更可控。
我做的第二件事情,就是解決認(rèn)知負(fù)荷的問(wèn)題。
我的目標(biāo)是讓新的人員接觸這個(gè)項(xiàng)目時(shí),不管是新的業(yè)務(wù)或是新的開(kāi)發(fā)、測(cè)試人員都能很快就了解這個(gè)業(yè)務(wù)的流程和規(guī)則。我不想讓他們?nèi)プx一遍需求文檔,不想讓他們必須通過(guò)需求文檔的文字了解業(yè)務(wù)規(guī)則。
回到我前面說(shuō)的“讓爭(zhēng)吵的東西所見(jiàn)即所得”,我的第二個(gè)技術(shù)彌補(bǔ)裂痕的方式就是讓業(yè)務(wù)規(guī)則實(shí)時(shí)化、圖形化!
只讓人看到最終的結(jié)果,只按某個(gè)最終的結(jié)果來(lái)討論和理解業(yè)務(wù)都是很片面的。很難對(duì)業(yè)務(wù)有全局的理解,最容易的就是維護(hù)時(shí)顧此失彼,改一個(gè)BUG產(chǎn)生一兩個(gè)新的的BUG,BUG永遠(yuǎn)生生不息。所以,我們的理解的過(guò)程應(yīng)該是可以交互的,不同的輸入應(yīng)該要向我們展示不同的業(yè)務(wù)流程分支,并要把邊界異常標(biāo)明清楚。
如下圖,一個(gè)實(shí)際中生成項(xiàng)目預(yù)測(cè)的業(yè)務(wù)流程,界面除了展示最終的結(jié)果數(shù)據(jù),還根據(jù)不同的項(xiàng)目編號(hào)向用戶展示不同的數(shù)據(jù)獲取和解析流程。
交互和圖形展示流程的實(shí)現(xiàn)使用了Python的兩個(gè)開(kāi)源庫(kù):
Dash
graphviz
結(jié)局
其實(shí),還在進(jìn)行中。