程序員角色分類:團隊里有兩類程序員
程序員的分類
最近幾年,我在多個不同類型的項目上,以不同的角色工作過:有時候會為項目前期做一些預(yù)研、然后為后續(xù)的交付估算工作量;有時候則在項目中期加入團隊,做本職的交付工作(就是寫業(yè)務(wù)代碼);而另外有些時候則會幫助客戶的團隊進行能力建設(shè)等等。
由于要在不同的場景和不同的上下文中頻繁切換,我和很多不同水平、有著不同變成習(xí)慣和思維方式的程序員一起工作過。我覺得對于 程序員這樣一種角色,還可以再細化成兩大類。雖然都是程序員,但是其職責(zé),技能要求,甚至思維方式都可能有很大的不同。
這兩大類程序員分別為:
- 原型類程序員(prototyper)
- 產(chǎn)品類程序員(engineer)
原型類程序員
如果通過敏捷的方式來運作一個項目,在項目開始的時候,開發(fā)往往需要客戶/用戶,BA(業(yè)務(wù)分析師)等角色一起協(xié)作。在有一個對需求的粗略梳理之后,通過技術(shù)手段快速實現(xiàn)應(yīng)用程序的原型,用以快速驗證業(yè)務(wù)場景。由于對需求的梳理是較為粗略的,其中有很多待驗證的假設(shè),如果按照傳統(tǒng)的方式來運作,則會有很多不必要的浪費
- 設(shè)計師通過Photoshop作出頁面
- 開發(fā)根據(jù)PS文件來開發(fā)
- 開發(fā)的同時,業(yè)務(wù)分析可能有了新的發(fā)現(xiàn)
- 設(shè)計師對Photoshop作出修改
- 開發(fā)根據(jù)新的PS來做修改
這種重量級的, 瀑布 方式的工作體驗非常糟糕,不論是設(shè)計師,還是開發(fā),總覺得很多事情都在變化,自己花費了很大力氣做的像素級別的精準(zhǔn)調(diào)整可能在第二天就要被推翻。不過現(xiàn)實世界就是這樣:需求的變化是不可避免的,我們唯一能做的是積極擁抱變化,而不是在最開始就嘗試設(shè)計、實現(xiàn)完美的效果。
與其在一開始就試圖設(shè)計一個完美的、確定的系統(tǒng),不如放棄幻想,每次只做簡陋而可以示意的原型,然后不斷去迭代,最后達到可用的系統(tǒng)。
比如,如果設(shè)計師完全不使用 Photoshop ,也不產(chǎn)出任何的PS文件,而是和開發(fā)坐在一起,開發(fā)一個簡陋,但是易于修改(比如HTML+CSS)的頁面,然后向業(yè)務(wù)分析師或者客戶來確認(rèn),然后根據(jù)反饋來快速調(diào)整。在迭代過程中,每次確認(rèn)之前,只做非常少量的工作,這樣既可以避免返工,又可以讓將來的調(diào)整更容易。
如果用這種方式來運作,我們隊程序員的能力要求是這樣的:
- 手速快(可以在很短時間內(nèi)作出一個可以工作的原型)
- 技術(shù)廣博(前后端)
- 可以與不同角色一起工作(最好是通過結(jié)對的方式)
比如通過 python -m http.server 8080 來運行一個Web服務(wù)器,而不是去考慮負(fù)載均衡或者HTTP緩存等,也無需考慮在為前端代碼加入動態(tài)路由。
很有可能,一個在 <head> 里通過 CDN 引入外部依賴,然后將所有代碼都寫入 main.js 就可以讓我們的想法變成觸手可及的應(yīng)用,在建立起快速反饋的機制之后,就可以和我們的BA,甚至客戶一起來協(xié)作,并快速打磨原型,使之和客戶的期望契合。
原型驅(qū)動
去年我參加了一個非常有意思的項目,在我加入的時候,客戶只有一個非常粗糙的想法:在網(wǎng)絡(luò)(不是計算機網(wǎng)絡(luò))中,如果某個實體被攻擊了,那么對整個系統(tǒng)的影響是什么?比如某個變電站由于氣溫太高爆炸了( 6·18西安變電站爆炸事故 ),那么哪些地鐵站會受到影響?以及收到多大影響?又或者某個運營商的網(wǎng)絡(luò)中斷了,那么它對該城市的各大銀行的轉(zhuǎn)賬業(yè)務(wù)有多大影響?
客戶希望有一個比較直觀的方式來展現(xiàn)網(wǎng)絡(luò)中的節(jié)點,以及當(dāng)故障發(fā)生時會有什么樣的影響。我們從原型開始,沒有設(shè)計師的參加,也沒有專門的業(yè)務(wù)分析師,一開始只有有一個簡單的文檔來描述,然后我根據(jù)文檔畫了一個草圖:
和客戶確認(rèn)了,我用 bootstrap+leaflet 做了一個簡單的頁面:
客戶表示大致是這么個意思。這時候我的代碼是這樣的:
- 一個HTML文件
- 從 CDN 來獲取 jQuery , bootstrap , leaflet
- inline的script中寫了一點微小的代碼
- inline的css
確定了這就是客戶想要的效果之后,我做了一些簡單的調(diào)整:
- 將第三方依賴下載下來,放到本地的一個目錄中
- 將inline的 JavaScript 和 CSS 抽取到文件
- 寫了一個簡單的shell script用來啟停本地的HttpServer
幾周之后,客戶對右側(cè)的兩個panel有一些新的需求,要求有一棵樹,可以點擊,然后要做各種同步:
這時候,我的代碼還是幾個微小的jQuery寫的文件,通過簡單的事件機制來完成交互。很快,客戶有了一個新的需求:中間區(qū)域的圖中的非葉子節(jié)點要可點擊,點擊之后右側(cè)的一個panel顯示該節(jié)點下的所有葉子,同樣,右側(cè)panel中的節(jié)點也需要可點擊。
也就是說,中間的樹需要兩個不同的視圖,而背后的數(shù)據(jù)只有一份(這樣點擊時的展開和收起才會是同步的),這時候用事件機制就很難做到了,而且代碼的復(fù)雜度直線上升,而且可維護性基本沒有。
基本滿足客戶的需求之后,團隊里加入了兩位同事,這時候我做了一個比較大膽的決定,用vue.js將整個應(yīng)用重寫,將大部分功能都抽象為組件,方便以后的擴展。完成的時候,界面看起來是這樣子的:
如果整理一下思路,原型類開發(fā)的流程是這樣的:
- 用 CDN +膠水代碼迅速實現(xiàn)
- 及時與客戶溝通,并根據(jù)反饋修改
- 在需求相對穩(wěn)定,方向確定之后,再做實際的技術(shù)選型
- 重構(gòu) — 甚至重寫(使用靠譜的技術(shù)站進行)
比如上面這個項目,如果現(xiàn)在讓我再來做一次技術(shù)選型,我可能會這樣選擇:
- 前端框架:React + Redux + React-router
- 界面原型:AntDesign
- 地圖:Leaflet
- 可視化:D3
產(chǎn)品類程序員
另一方面,當(dāng) idea 已經(jīng)經(jīng)過驗證,我們需要通過嚴(yán)謹(jǐn)?shù)墓こ虒嵺`將其產(chǎn)品化,那么對開發(fā)的要求卻又有不同:
- 非功能需求(安全/性能/容災(zāi)等)
- 深刻而周全
- 自動化測試
- 軟件架構(gòu)
我在去年的另外一個項目上,負(fù)責(zé)一個具體模塊的開發(fā),一起在項目上有位同事,叫侯曉成。在 kick off 用戶故事(開發(fā)和業(yè)務(wù)分析師,QA等角色一起確認(rèn)需求,進入開發(fā)階段之前的一個敏捷實踐)的時候,他常??梢园袯A問的答不上話來。
我們構(gòu)建的系統(tǒng)需要管理零售中的促銷活動,促銷活動可以被多個不同的門店執(zhí)行,這些門店可能位于全球任何一個地方。這時候就會涉及促銷活動開始和結(jié)束的事件與時區(qū)的問題。比如管理員創(chuàng)建了一個圣誕促銷,所有商品9折。但是由于時區(qū)的存在,各個國家的 圣誕節(jié) 并不是同一天,諸如此類的場景,在編碼是都要考慮到。
侯曉成會非常全面的考慮各種業(yè)務(wù)場景。另一方面,大的系統(tǒng)往往涉及多個集成點,性能、安全,緩存的使用等等,都需要開發(fā)人員在編碼時就考慮到。為了保證軟件的內(nèi)部質(zhì)量,程序員還需要有非常好的測試意識和寫測試的習(xí)慣,不論是比較高層次的集成測試還是更底層單元測試。
除了交付本身,產(chǎn)品型程序員可能還會考慮這樣一些工程實踐,來保證產(chǎn)品從開發(fā)到上線甚至到運維的各個方面:
- 持續(xù)集成、持續(xù)交付
- 自動化測試
- DevOps
小結(jié)
毫無疑問,我們在實際項目中,這兩種程序員都是缺一不可,相互補充的。在需求還沒有完全明朗,需要快速驗證市場,探索業(yè)務(wù)方向的正確性,我們需要原型類程序員。他們通過和業(yè)務(wù)分析師,設(shè)計師等角色一起工作,可以快速且輕量級的迭代出產(chǎn)品的原型。而一旦市場基本確定,我們就需要產(chǎn)品型程序員的幫助,將產(chǎn)品的開發(fā)、測試、部署、運維整個生命周期都規(guī)范化,引入相對重量且長期的工程實踐,這樣產(chǎn)品在后續(xù)的迭代中才可能保持非常高的內(nèi)部質(zhì)量。