上一节:5. 物 - 技术管理
文 - 文化建设
核心思想: “八面”玲珑
团队文化是指团队成员在相互合作的过程中,为实现各自的人生价值,并为完成团队共同目标而形成的一些行事态度、思考方式和行为准则。在技术管理方面,我主要是负责塑造技术文化氛围,并通过这些思想、准则来影响及推行“团队管理”、“项目管理”及“技术管理”等方面。
我眼中的工程师文化
所谓“八面”玲珑,不是指要把人培养成圆滑的人,而是我认为在一个以工程师为伍的技术团队中,应该建立以下八个方面的文化:
- 学习文化
- 创新文化
- 工程文化
- 工具文化
- 自动文化
- 脚本文化
- 开源文化
- 流程文化
学习文化
- 技术调研
- 技术总结
前面“技术管理”中说过要“喜新厌旧”,不断扩宽知识边界、填平知识短板,团队技术水平才能不断提高。对新出现、不熟悉的技术点要进行调研,出调研报告;对已经熟悉用过的,要做技术总结,使得经验可以复用。如何鼓励内部分享,外部交流、互通有无,在前面“团队管理”如何“培养”已经具体说过就不再展开。
创新文化
公司无创新则无独特的竞争力,这点大家都懂不多用解释。但我认为“创新”不止是说创造新的工具、组件,勇于使用新技术、引进新框架、打破陈规做法也是一种创新,能引起“有益的变化”就是创新,应该鼓励。
例如我看到我们有一个项目后端是ruby,前端是coffee语言编写,都有大量的类定义,新加入的开发人员上手会比较困难,为此我编写了一个文档构建脚本,能自动对2种语言的代码分别生成统一的YARD风格的文档,再合并在一份文档中,以方便开发人员查看熟悉程序结构,如「图6-1」
∆ 「图6-1」build app doc
这种有利于提高工作效率的改进在我看来就算是一种微创新。
工程文化
软件工程开发,从来不是写个“Hello World”这么简单的事情。一个完整的软件工程,需要考虑程序语言、数据库、开发工具、系统平台、依赖包管理、代码目录结构、设计模式、日志记录等方面,开发项目交付时,除了代码,还要功能说明文档、代码说明文档、单元测试、压测报告、部署说明文档。所以在我看来,一个开发框架的工程化成熟度,就是看以上这些方面的覆盖程度。
前面“技术管理”中说过了我们的Web 开发框架是用Rails,而Rails是fullstack的、从一开始就走工程化的风格,从初始化一个rails项目的第一步的命令: rails new MyProject --database=postgresql --javascript=jquery
看出它会期待你预先考虑好后端使用什么数据库,前端使用什么js库,当然这些参数都是可选,不选择则使用默认配置,Rails遵从CoC(约定优于配置) 原则。
再看一下rails 5自动生成的项目目录结构:
├── Gemfile # gem依赖管理(Gem是Ruby领域的apt)
├── README.md # 说明文档
├── Rakefile # 构建任务管理入口(Rake是Ruby领域的Make)
├── app/ # 应用代码
│ ├── assets/ # 静态资源文件(js,css,img,font)
│ ├── channels/ # 基于WebSocket 的Pub/Sub实现
│ ├── controllers/ # 控制器,负责处理请求,调取Model,选择View渲染
│ ├── helpers/ # view 的辅助模块
│ ├── jobs/ # 队列任务
│ ├── mailers/ # 邮件内容
│ ├── models/ # 业务模型
│ └── views/ # 视图(HTML模板)
├── bin/ # 一些项目CLI命令、自定义脚本
│ ├── bundle*
│ ├── rails* # 主要CLI,提供启动app server、控制台、生成器、运行测试
│ ├── rake*
│ ├── setup* # 项目初始化脚本,一步完成安装依赖、数据库初始化、启动rails server
│ ├── spring*
│ └── update* # 开发过程更新脚本,一步完成安装依赖、数据库迁移、清理临时文件、重启rails server
├── config/ # 各种配置,如启动方式、数据库配置、路由配置、环境配置、密钥配置、i18n配置
├── config.ru # Rack架构服务调用接口
├── db/ # 数据库迁移改动、种子数据
├── lib/ # 独立的类、模块、app相关的rake任务
├── log/ # 各种日志文件
├── public/ # 不用预处理、可公开访问资源目录,如404.html,robots.txt
│ ├── 404.html
│ ├── 422.html
│ ├── 500.html
│ ├── favicon.ico
│ └── robots.txt
├── test/ # 单元测试、集成测试
│ ├── controllers/
│ ├── fixtures/
│ ├── helpers/
│ ├── integration/
│ ├── mailers/
│ ├── models/
│ └── test_helper.rb
├── tmp/ # 缓存、临时文件
│ └── cache/
└── vendor/ # 第三库、资源
└── doc/ # 文档存放目录,从rails 4不再默认生成,但可以通过`rake doc:app` 来检查并生成app代码文档
从所生成目录就能看出在 rails 项目里会涉及到依赖包管理、构建任务、静态资源处理、消息订阅处理、消息队列处理、MVC架构、邮件处理、提供CLI、i18n处理、多环境适配、Rack架构、数据库连接、数据库查询(ORM)、数据结构迁移管理、初始化数据管理、日志处理、单元测试、集成测试这些概念,几乎涵盖了一个Web项目需要用到的方方面面,可以大方说句使用rails的开发者相对是比较“幸福”的,因为有很多细枝末节的地方都已经有被考虑到,而且还在不断的补充引入新的feature。
我们使用的技术框架不止rails,在前后端分离的架构中,前端使用过Backbone/Angularjs/React & Redux,在移动开发中使用Ionic/React Native,但这些技术框架中有些没有很统一、符合要求的工程化规范,因此我安排整理了一些目录规范,例如:
- angularjs 项目目录结构规范文档
- react-redux 项目目录结构规范文档
- React Native项目结构规范
以便开发项目时更工程化、结构化,可以在新项目中可以复用架构、组件可以通用
工具文化
“工欲善其事,必先利其器”这句话我非常赞同。如果说任务开发是战场,那么开发者使用的工具就是他们的武器,把“武器”打磨得是否顺手就会成为战场生存的关键之一。我经常在团队中推荐并鼓励每个人都分享、推荐自己使用过、认为高效的工具,例如:
- Shell: zsh/fish - 交互式shell,提高CLI操作效率
- 代码提交: GitX - 我鼓励在代码提交时使用git的GUI工具如GitX而不是命令行,因为GUI工具可以进行代码整理,有利合理的代码提交记录
- 终端操作: TotalTerminal/iTerm - 随时随地可以进行敲命令
- 文档编辑:MacDown - 所写己所得、兼容github GFM格式
- API查看:Dash - 快速离线查看各种技术API文档,开发者必备
- 窗口操作:Spectacle - 多屏幕操作利器
- 应用访问:Alfred - 把Mac变成Google Instant Search 般的体验
- 图片编辑:Skitch - 一图胜千言,快速给截图加上注释
- 数据库操作:Navicat Lite - 支持链接mysql/postgres/oracle/sqlite/sql server,开发者必备
- 代码编辑器:Sublime Text/Vim/Emacs/Atom - 编辑器的选择对程序员而言是场“圣战”,为了找出“哪个才是最好的代码编辑器”,我特意在团队内发起过专题分享活动:“编辑器到底哪家好”——技术分享 @ 2015-01-10
自动文化
优秀程序员三大特质之一是“懒”,能用程序、脚本解决的,就不用手工,更有“以自动化为荣,手工为耻”的说法,常会出现花费几个小时的脚本去解决一次只要十几分钟简单但会重复的问题,作为管理者遇到这种情况不应该一昧的打压,因为这种思想就是以自动化思维去解决重复,前面“技术管理”章节中就提到过了自动化的重要性,从本地开发、到代码提交、测试、集成、部署、发布、监控等各个环节中都有加入自动化的操作,能执行自动化的都尽量推行自动化,提高效率之余减少人为误操作。
以现在的观点来看,一个技术团队中有没推行自动化技术,可以认为这个团队是否达到“高效”的检验特征之一了。
脚本文化
无论是作为Java,C++,.Net 这类静态语言的程序员,还是使用Ruby,PHP,Python,JavaScript 这类脚本语言的程序员,在开发过程中都会接触到Shell脚本(Shell Script),因此掌握一些基本的Shell脚本操作,可以有效提高工作效率。
除了可以使用上面提到的“工具文化”中推荐的一些交互式shell来提高CLI操作效率外,还应掌握一些简单的Shell语法,用以编写辅助开发的脚本。
最简单的做法是可以增加一些alias作为一些常用命令的组合,使用有语义的命名,配合可交互Shell的提示,很简单、很低廉的操作成本,就可以在很大程度上减少重复敲打键盘、错误输入。例如我给不熟git的新人建了个 git-cmd-helpers,就是增加一些常用git 操作的封装,用以提高git的使用效率。
开源文化
作为技术开发者,我们是技术开源社区的收益者(可见我发表的 blog post:Beansmile用到的开源产品),因此也鼓励开源精神。我会经常在团队中鼓励在开发中使用一些开源组件遇到问题修复时,给源作者发PR,我们在github上也有发布一些开源作品。
流程文化
制订流程,是团队多人协作的基础,是“规范化”的细节,是“自动化”的前提。
在前面的“团队管理”提到工作要流程化,我制定了涵盖从招聘到入职、升退评价的招聘和入职流程;“项目管理”中我制定了[Beansmile开发流程规范]、[Beansmile Trello使用规范],涵盖从需求对接到项目结束交付;“技术管理”中提到[trello + git开发流程规范],涵盖了代码提交流程、代码审查流程、部署流程步骤细节。
制订制度、规范的流程
同样的,在企业中制定一种新的制度、规范时,也应该遵从类似以下流程:
- 调研 - 先看人家怎么做
- 制订 - 自己要怎么做
- 发布 - 跟团队说明是什么、怎么做
- 执行 - 怎么说就要怎么做,最忌光说不练
- 监督 - 了解执行效果,收集反馈
- 修正 - 根据反馈意见调整细节,收集到足够多的改动后发布新版
- 发布新版 -> 执行 -> 监督 -> 修正 ->(重复)
思路:跟写单元测试一样
- 编写测试代码
- 运行测试
- 观察结果
- 修正实现代码 -> 运行测试 -> 观察结果 -> (重复)
推衍:企业内所有的重大决策都应该如此推行
所以一个成熟的技术团队中,为了明确职责、分工清晰、减少冲突,是很有必要制定一些常用流程,并将之作为的规范文档沉淀下来反复推行实践,以下我制定过且形成规范文档的流程:
- [Beansmile招聘流程] (见「图3-5」)
- [Beansmile新员工入职流程] (「图3-6」)
- [Beansmile开发流程规范](见「图3-15」)
- wiki:[Beansmile任务开发流程]
- wiki:[Trello + git开发流程规范]
小结
以上这八种便是我认为是对技术团队有益的文化总结。
企业文化建设能否建设好同样是门不简单的技术活,但更大程度上是受企业创始人、管理层影响,因此不同技术团队中即便是使用相同的技术栈,但由于创始人不同,所施行的管理理念、思考方式不同,执行结果也就不一样。因此我不认为有“最好”的团队文化,只有“最适合”的团队文化,因地制宜、量身打造的才是适合自己的。