上一節(jié):5. 物 - 技術(shù)管理
文 - 文化建設(shè)
核心思想: “八面”玲瓏
團(tuán)隊(duì)文化是指團(tuán)隊(duì)成員在相互合作的過(guò)程中,為實(shí)現(xiàn)各自的人生價(jià)值,并為完成團(tuán)隊(duì)共同目標(biāo)而形成的一些行事態(tài)度、思考方式和行為準(zhǔn)則。在技術(shù)管理方面,我主要是負(fù)責(zé)塑造技術(shù)文化氛圍,并通過(guò)這些思想、準(zhǔn)則來(lái)影響及推行“團(tuán)隊(duì)管理”、“項(xiàng)目管理”及“技術(shù)管理”等方面。
我眼中的工程師文化
所謂“八面”玲瓏,不是指要把人培養(yǎng)成圓滑的人,而是我認(rèn)為在一個(gè)以工程師為伍的技術(shù)團(tuán)隊(duì)中,應(yīng)該建立以下八個(gè)方面的文化:
- 學(xué)習(xí)文化
- 創(chuàng)新文化
- 工程文化
- 工具文化
- 自動(dòng)文化
- 腳本文化
- 開(kāi)源文化
- 流程文化
學(xué)習(xí)文化
- 技術(shù)調(diào)研
- 技術(shù)總結(jié)
前面“技術(shù)管理”中說(shuō)過(guò)要“喜新厭舊”,不斷擴(kuò)寬知識(shí)邊界、填平知識(shí)短板,團(tuán)隊(duì)技術(shù)水平才能不斷提高。對(duì)新出現(xiàn)、不熟悉的技術(shù)點(diǎn)要進(jìn)行調(diào)研,出調(diào)研報(bào)告;對(duì)已經(jīng)熟悉用過(guò)的,要做技術(shù)總結(jié),使得經(jīng)驗(yàn)可以復(fù)用。如何鼓勵(lì)內(nèi)部分享,外部交流、互通有無(wú),在前面“團(tuán)隊(duì)管理”如何“培養(yǎng)”已經(jīng)具體說(shuō)過(guò)就不再展開(kāi)。
創(chuàng)新文化
公司無(wú)創(chuàng)新則無(wú)獨(dú)特的競(jìng)爭(zhēng)力,這點(diǎn)大家都懂不多用解釋。但我認(rèn)為“創(chuàng)新”不止是說(shuō)創(chuàng)造新的工具、組件,勇于使用新技術(shù)、引進(jìn)新框架、打破陳規(guī)做法也是一種創(chuàng)新,能引起“有益的變化”就是創(chuàng)新,應(yīng)該鼓勵(lì)。
例如我看到我們有一個(gè)項(xiàng)目后端是ruby,前端是coffee語(yǔ)言編寫(xiě),都有大量的類(lèi)定義,新加入的開(kāi)發(fā)人員上手會(huì)比較困難,為此我編寫(xiě)了一個(gè)文檔構(gòu)建腳本,能自動(dòng)對(duì)2種語(yǔ)言的代碼分別生成統(tǒng)一的YARD風(fēng)格的文檔,再合并在一份文檔中,以方便開(kāi)發(fā)人員查看熟悉程序結(jié)構(gòu),如「圖6-1」

? 「圖6-1」build app doc
這種有利于提高工作效率的改進(jìn)在我看來(lái)就算是一種微創(chuàng)新。
工程文化
軟件工程開(kāi)發(fā),從來(lái)不是寫(xiě)個(gè)“Hello World”這么簡(jiǎn)單的事情。一個(gè)完整的軟件工程,需要考慮程序語(yǔ)言、數(shù)據(jù)庫(kù)、開(kāi)發(fā)工具、系統(tǒng)平臺(tái)、依賴(lài)包管理、代碼目錄結(jié)構(gòu)、設(shè)計(jì)模式、日志記錄等方面,開(kāi)發(fā)項(xiàng)目交付時(shí),除了代碼,還要功能說(shuō)明文檔、代碼說(shuō)明文檔、單元測(cè)試、壓測(cè)報(bào)告、部署說(shuō)明文檔。所以在我看來(lái),一個(gè)開(kāi)發(fā)框架的工程化成熟度,就是看以上這些方面的覆蓋程度。
前面“技術(shù)管理”中說(shuō)過(guò)了我們的Web 開(kāi)發(fā)框架是用Rails,而Rails是fullstack的、從一開(kāi)始就走工程化的風(fēng)格,從初始化一個(gè)rails項(xiàng)目的第一步的命令: rails new MyProject --database=postgresql --javascript=jquery 看出它會(huì)期待你預(yù)先考慮好后端使用什么數(shù)據(jù)庫(kù),前端使用什么js庫(kù),當(dāng)然這些參數(shù)都是可選,不選擇則使用默認(rèn)配置,Rails遵從CoC(約定優(yōu)于配置) 原則。
再看一下rails 5自動(dòng)生成的項(xiàng)目目錄結(jié)構(gòu):
├── Gemfile # gem依賴(lài)管理(Gem是Ruby領(lǐng)域的apt)
├── README.md # 說(shuō)明文檔
├── Rakefile # 構(gòu)建任務(wù)管理入口(Rake是Ruby領(lǐng)域的Make)
├── app/ # 應(yīng)用代碼
│ ├── assets/ # 靜態(tài)資源文件(js,css,img,font)
│ ├── channels/ # 基于WebSocket 的Pub/Sub實(shí)現(xiàn)
│ ├── controllers/ # 控制器,負(fù)責(zé)處理請(qǐng)求,調(diào)取Model,選擇View渲染
│ ├── helpers/ # view 的輔助模塊
│ ├── jobs/ # 隊(duì)列任務(wù)
│ ├── mailers/ # 郵件內(nèi)容
│ ├── models/ # 業(yè)務(wù)模型
│ └── views/ # 視圖(HTML模板)
├── bin/ # 一些項(xiàng)目CLI命令、自定義腳本
│ ├── bundle*
│ ├── rails* # 主要CLI,提供啟動(dòng)app server、控制臺(tái)、生成器、運(yùn)行測(cè)試
│ ├── rake*
│ ├── setup* # 項(xiàng)目初始化腳本,一步完成安裝依賴(lài)、數(shù)據(jù)庫(kù)初始化、啟動(dòng)rails server
│ ├── spring*
│ └── update* # 開(kāi)發(fā)過(guò)程更新腳本,一步完成安裝依賴(lài)、數(shù)據(jù)庫(kù)遷移、清理臨時(shí)文件、重啟rails server
├── config/ # 各種配置,如啟動(dòng)方式、數(shù)據(jù)庫(kù)配置、路由配置、環(huán)境配置、密鑰配置、i18n配置
├── config.ru # Rack架構(gòu)服務(wù)調(diào)用接口
├── db/ # 數(shù)據(jù)庫(kù)遷移改動(dòng)、種子數(shù)據(jù)
├── lib/ # 獨(dú)立的類(lèi)、模塊、app相關(guān)的rake任務(wù)
├── log/ # 各種日志文件
├── public/ # 不用預(yù)處理、可公開(kāi)訪問(wèn)資源目錄,如404.html,robots.txt
│ ├── 404.html
│ ├── 422.html
│ ├── 500.html
│ ├── favicon.ico
│ └── robots.txt
├── test/ # 單元測(cè)試、集成測(cè)試
│ ├── controllers/
│ ├── fixtures/
│ ├── helpers/
│ ├── integration/
│ ├── mailers/
│ ├── models/
│ └── test_helper.rb
├── tmp/ # 緩存、臨時(shí)文件
│ └── cache/
└── vendor/ # 第三庫(kù)、資源
└── doc/ # 文檔存放目錄,從rails 4不再默認(rèn)生成,但可以通過(guò)`rake doc:app` 來(lái)檢查并生成app代碼文檔
從所生成目錄就能看出在 rails 項(xiàng)目里會(huì)涉及到依賴(lài)包管理、構(gòu)建任務(wù)、靜態(tài)資源處理、消息訂閱處理、消息隊(duì)列處理、MVC架構(gòu)、郵件處理、提供CLI、i18n處理、多環(huán)境適配、Rack架構(gòu)、數(shù)據(jù)庫(kù)連接、數(shù)據(jù)庫(kù)查詢(xún)(ORM)、數(shù)據(jù)結(jié)構(gòu)遷移管理、初始化數(shù)據(jù)管理、日志處理、單元測(cè)試、集成測(cè)試這些概念,幾乎涵蓋了一個(gè)Web項(xiàng)目需要用到的方方面面,可以大方說(shuō)句使用rails的開(kāi)發(fā)者相對(duì)是比較“幸?!钡模?yàn)橛泻芏嗉?xì)枝末節(jié)的地方都已經(jīng)有被考慮到,而且還在不斷的補(bǔ)充引入新的feature。
我們使用的技術(shù)框架不止rails,在前后端分離的架構(gòu)中,前端使用過(guò)Backbone/Angularjs/React & Redux,在移動(dòng)開(kāi)發(fā)中使用Ionic/React Native,但這些技術(shù)框架中有些沒(méi)有很統(tǒng)一、符合要求的工程化規(guī)范,因此我安排整理了一些目錄規(guī)范,例如:
- angularjs 項(xiàng)目目錄結(jié)構(gòu)規(guī)范文檔
- react-redux 項(xiàng)目目錄結(jié)構(gòu)規(guī)范文檔
- React Native項(xiàng)目結(jié)構(gòu)規(guī)范
以便開(kāi)發(fā)項(xiàng)目時(shí)更工程化、結(jié)構(gòu)化,可以在新項(xiàng)目中可以復(fù)用架構(gòu)、組件可以通用
工具文化
“工欲善其事,必先利其器”這句話我非常贊同。如果說(shuō)任務(wù)開(kāi)發(fā)是戰(zhàn)場(chǎng),那么開(kāi)發(fā)者使用的工具就是他們的武器,把“武器”打磨得是否順手就會(huì)成為戰(zhàn)場(chǎng)生存的關(guān)鍵之一。我經(jīng)常在團(tuán)隊(duì)中推薦并鼓勵(lì)每個(gè)人都分享、推薦自己使用過(guò)、認(rèn)為高效的工具,例如:
- Shell: zsh/fish - 交互式shell,提高CLI操作效率
- 代碼提交: GitX - 我鼓勵(lì)在代碼提交時(shí)使用git的GUI工具如GitX而不是命令行,因?yàn)镚UI工具可以進(jìn)行代碼整理,有利合理的代碼提交記錄
- 終端操作: TotalTerminal/iTerm - 隨時(shí)隨地可以進(jìn)行敲命令
- 文檔編輯:MacDown - 所寫(xiě)己所得、兼容github GFM格式
- API查看:Dash - 快速離線查看各種技術(shù)API文檔,開(kāi)發(fā)者必備
- 窗口操作:Spectacle - 多屏幕操作利器
- 應(yīng)用訪問(wèn):Alfred - 把Mac變成Google Instant Search 般的體驗(yàn)
- 圖片編輯:Skitch - 一圖勝千言,快速給截圖加上注釋
- 數(shù)據(jù)庫(kù)操作:Navicat Lite - 支持鏈接mysql/postgres/oracle/sqlite/sql server,開(kāi)發(fā)者必備
- 代碼編輯器:Sublime Text/Vim/Emacs/Atom - 編輯器的選擇對(duì)程序員而言是場(chǎng)“圣戰(zhàn)”,為了找出“哪個(gè)才是最好的代碼編輯器”,我特意在團(tuán)隊(duì)內(nèi)發(fā)起過(guò)專(zhuān)題分享活動(dòng):“編輯器到底哪家好”——技術(shù)分享 @ 2015-01-10
自動(dòng)文化
優(yōu)秀程序員三大特質(zhì)之一是“懶”,能用程序、腳本解決的,就不用手工,更有“以自動(dòng)化為榮,手工為恥”的說(shuō)法,常會(huì)出現(xiàn)花費(fèi)幾個(gè)小時(shí)的腳本去解決一次只要十幾分鐘簡(jiǎn)單但會(huì)重復(fù)的問(wèn)題,作為管理者遇到這種情況不應(yīng)該一昧的打壓,因?yàn)檫@種思想就是以自動(dòng)化思維去解決重復(fù),前面“技術(shù)管理”章節(jié)中就提到過(guò)了自動(dòng)化的重要性,從本地開(kāi)發(fā)、到代碼提交、測(cè)試、集成、部署、發(fā)布、監(jiān)控等各個(gè)環(huán)節(jié)中都有加入自動(dòng)化的操作,能執(zhí)行自動(dòng)化的都盡量推行自動(dòng)化,提高效率之余減少人為誤操作。
以現(xiàn)在的觀點(diǎn)來(lái)看,一個(gè)技術(shù)團(tuán)隊(duì)中有沒(méi)推行自動(dòng)化技術(shù),可以認(rèn)為這個(gè)團(tuán)隊(duì)是否達(dá)到“高效”的檢驗(yàn)特征之一了。
腳本文化
無(wú)論是作為Java,C++,.Net 這類(lèi)靜態(tài)語(yǔ)言的程序員,還是使用Ruby,PHP,Python,JavaScript 這類(lèi)腳本語(yǔ)言的程序員,在開(kāi)發(fā)過(guò)程中都會(huì)接觸到Shell腳本(Shell Script),因此掌握一些基本的Shell腳本操作,可以有效提高工作效率。
除了可以使用上面提到的“工具文化”中推薦的一些交互式shell來(lái)提高CLI操作效率外,還應(yīng)掌握一些簡(jiǎn)單的Shell語(yǔ)法,用以編寫(xiě)輔助開(kāi)發(fā)的腳本。
最簡(jiǎn)單的做法是可以增加一些alias作為一些常用命令的組合,使用有語(yǔ)義的命名,配合可交互Shell的提示,很簡(jiǎn)單、很低廉的操作成本,就可以在很大程度上減少重復(fù)敲打鍵盤(pán)、錯(cuò)誤輸入。例如我給不熟git的新人建了個(gè) git-cmd-helpers,就是增加一些常用git 操作的封裝,用以提高git的使用效率。
開(kāi)源文化
作為技術(shù)開(kāi)發(fā)者,我們是技術(shù)開(kāi)源社區(qū)的收益者(可見(jiàn)我發(fā)表的 blog post:Beansmile用到的開(kāi)源產(chǎn)品),因此也鼓勵(lì)開(kāi)源精神。我會(huì)經(jīng)常在團(tuán)隊(duì)中鼓勵(lì)在開(kāi)發(fā)中使用一些開(kāi)源組件遇到問(wèn)題修復(fù)時(shí),給源作者發(fā)PR,我們?cè)趃ithub上也有發(fā)布一些開(kāi)源作品。
流程文化
制訂流程,是團(tuán)隊(duì)多人協(xié)作的基礎(chǔ),是“規(guī)范化”的細(xì)節(jié),是“自動(dòng)化”的前提。
在前面的“團(tuán)隊(duì)管理”提到工作要流程化,我制定了涵蓋從招聘到入職、升退評(píng)價(jià)的招聘和入職流程;“項(xiàng)目管理”中我制定了[Beansmile開(kāi)發(fā)流程規(guī)范]、[Beansmile Trello使用規(guī)范],涵蓋從需求對(duì)接到項(xiàng)目結(jié)束交付;“技術(shù)管理”中提到[trello + git開(kāi)發(fā)流程規(guī)范],涵蓋了代碼提交流程、代碼審查流程、部署流程步驟細(xì)節(jié)。
制訂制度、規(guī)范的流程
同樣的,在企業(yè)中制定一種新的制度、規(guī)范時(shí),也應(yīng)該遵從類(lèi)似以下流程:
- 調(diào)研 - 先看人家怎么做
- 制訂 - 自己要怎么做
- 發(fā)布 - 跟團(tuán)隊(duì)說(shuō)明是什么、怎么做
- 執(zhí)行 - 怎么說(shuō)就要怎么做,最忌光說(shuō)不練
- 監(jiān)督 - 了解執(zhí)行效果,收集反饋
- 修正 - 根據(jù)反饋意見(jiàn)調(diào)整細(xì)節(jié),收集到足夠多的改動(dòng)后發(fā)布新版
- 發(fā)布新版 -> 執(zhí)行 -> 監(jiān)督 -> 修正 ->(重復(fù))
思路:跟寫(xiě)單元測(cè)試一樣
- 編寫(xiě)測(cè)試代碼
- 運(yùn)行測(cè)試
- 觀察結(jié)果
- 修正實(shí)現(xiàn)代碼 -> 運(yùn)行測(cè)試 -> 觀察結(jié)果 -> (重復(fù))
推衍:企業(yè)內(nèi)所有的重大決策都應(yīng)該如此推行
所以一個(gè)成熟的技術(shù)團(tuán)隊(duì)中,為了明確職責(zé)、分工清晰、減少?zèng)_突,是很有必要制定一些常用流程,并將之作為的規(guī)范文檔沉淀下來(lái)反復(fù)推行實(shí)踐,以下我制定過(guò)且形成規(guī)范文檔的流程:
- [Beansmile招聘流程] (見(jiàn)「圖3-5」)
- [Beansmile新員工入職流程] (「圖3-6」)
- [Beansmile開(kāi)發(fā)流程規(guī)范](見(jiàn)「圖3-15」)
- wiki:[Beansmile任務(wù)開(kāi)發(fā)流程]
- wiki:[Trello + git開(kāi)發(fā)流程規(guī)范]
小結(jié)
以上這八種便是我認(rèn)為是對(duì)技術(shù)團(tuán)隊(duì)有益的文化總結(jié)。
企業(yè)文化建設(shè)能否建設(shè)好同樣是門(mén)不簡(jiǎn)單的技術(shù)活,但更大程度上是受企業(yè)創(chuàng)始人、管理層影響,因此不同技術(shù)團(tuán)隊(duì)中即便是使用相同的技術(shù)棧,但由于創(chuàng)始人不同,所施行的管理理念、思考方式不同,執(zhí)行結(jié)果也就不一樣。因此我不認(rèn)為有“最好”的團(tuán)隊(duì)文化,只有“最適合”的團(tuán)隊(duì)文化,因地制宜、量身打造的才是適合自己的。