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