如何提升程序员的生产率 (2)

版权声明:本文由韩伟原创文章,转载请注明出处: 
文章原文连接:https://www.qcloud.com/community/article/252mysql

来源:腾云阁 https://www.qcloud.com/community程序员

 

接上篇 如何提升程序员的生产率 (1)正则表达式

三. 开发过程

沟通

软件一般都须要通过不少人和不少次的沟通才能生产出来,可是沟通自己又每每会影响软件的开发速度。这是一段很矛盾的关系。好的沟通方法能下降开发中由于信息不透明致使的开发资源浪费,而又尽可能减小沟通所占用的精力。算法

1. 需求沟通
在任何一个软件产品中,如何应对需求的变动,都是相当重要的。需求一直是软件工做得以成功或者失败的最重要因素。软件开发中不少技术和方法都是围绕着需求来设计的。sql

需求的沟通是需求工做的第一个环节。首先沟通的对象必须是通过挑选的,以避免添加没必要要的需求混乱。最佳的需求沟通是和用户或者用户表明。可是他们每每他们缺少必要的计算机知识。而程序员却不多有丰富的需求领域的知识。这个鸿沟须要双方共同去弥补,最重要的作法是,不要光靠口说。shell

程序员应该认真研究需求领域的知识,仔细查看涉及的单据、原型产品、现有工做流程等,并且必须用笔记录下来,以后再去整理问题,逐条咨询用户。在仔细了解状况以前,不宜开始设计总体程序结构。数据库

当你有必定了解以后,程序员就能够动手开发一个快速的原型,若是没有足够资源,一组界面图也是很好的。以程序的外观来帮助用户来协助设计,是最有力的需求沟通方式之一。不断的在用户的帮助下完善这些界面图,标识上那些可能须要的数据和流程,而后完善,而后再继续找用户确认。这个过程在前期可能会至关枯燥,由于那些沟通用的原型也许一点都不会给后续的开发带来重用。可是能明确需求,倒是对开发最大帮组。编程

2. 需求评审
在需求基本有一个思路以后,须要开始准备需求评审。首先说说评审的材料,通常会是《用例图》,《领域建模的模型》,用例规约,一些《非功能需求点列表》,甚至软件的一些通过用户确认的使用流程和使用界面。设计模式

评审的过程其实远没有沟通的过程重要。这个环节主要是给你们一个明确的开端:如今咱们开始作系统设计了。做为在一些公司内部,需求评审是否获得经过仍是产品是否能正式开始立项的一个流程。数组

对于评审,不少时候会认为是,提交评审者来写报告,而后向一堆专家或者上级来介绍,最后他们提出问题,幸运的话就盖章承认。但我认为评审不该该是这样的。由于若是上级和专家没有参与项目需求的沟通,他们对项目的了解是片面的,靠一些文档和口头介绍,必定会以“挑毛病”的姿态出现。而项目自己是否真的可行,却不负担真正的责任。

所以我认为需求评审应该是项目发起者,也就是有权拍板是否是作这个项目的人,来主持这个评审会议,全部的材料由他宣讲,疑问由他回答。而其余的与会者包括专家团和可能的开发团队,纷纷向他提出问题,以确认真正的可行性。最后主持者在搜集了众多意见后,筛选出有意义的意见,改善需求评审的材料,最后拍板是否完成需求评审。这种流程,无疑会要求公司的权力下放,而事实上,若是不是下放,又或者不是老板亲自主持,不少项目最后就输在了起跑线上。

3. 合做沟通
程序员的沟通讲求的是效率,准确是最重要的要素,若是没法表达“准确”,那就只是在创做,而非沟通。对于须要高度注意力的工做——开发软件来讲,群体创做的效率实在不够高。所以提升沟通的“准确”程度是相当重要的效率因数。

开发中的沟通有不少种,其中最重要的一种是需求沟通。特别是做为技术人员,和策划、美术的沟通最多。这里须要重视的就是,和非技术人员沟通,快速原型:如假的界面图或者手画稿,填写了假数据的表格等等,是很重要的沟通手段。不少时候我都会要求把这些沟经过程中的手画稿扫描保留下来做为设计文档的一部分。

另一种沟通是程序员之间的。我一直认为程序员之间最好的沟通就是“不用沟通”。客户端和服务端之间调整协议,最好的方法是直接两个IDE联调。关于工做任务的接口,最好是定义出接口代码,而且有单元测试针对接口代码作处理。固然拉,对于这些接口的设计,仍是须要当面沟通的。

最后要说说会议。我认为沟通不该该打断开发。无论是5分钟仍是1个小时,会议都是一种打断。而不少会议须要开前准备不少东西,你们试图用这种方法减小会议的时间,但实际上却占用了一样多的时间。咱们应该关注如何减小会议,以及减小会议对开发的打断。在午饭的时候开会,我认为是一个比较好的方式,这种打断是自然的,不会产生额外的打断。并且与会者一般不会睡着。午饭时的讨论气氛也会比较好,比起一本正经的会议要活跃的多。

4. 测试沟通
程序员和测试人员之间的沟通必定是密切与频繁的,虽然咱们有JIRA、BugZilla之类的BUG跟踪系统,可是每每不少问题仍是要经过口头的沟通来解决,我认为和测试人员的沟通关键是要分出优先级,对于“可重现”的BUG应该优先沟通,由于能够很快解决。而那些偶现的问题,可能沟通中一大半都会是猜想,其实能够先放后,这不表示那些问题不重要,而是应该在肯定能解决的问题都先解决掉,这些时间内测试人员也能够努力把偶现变成必现。

测试沟通的内容中,对于“名词”必定要明确,由于咱们会有不少个环境,必需要让每一个概念有个清晰的表达方法。咱们常常会在“测试”这个词上犯糊涂,好比“测试版”究竟是哪一个版本,“测试网”又是哪一个网?甚至“测试机”是个PC仍是个手机?这些都必须明确下来。好比用alpha网,beta网就清晰的多。

设计

1. 设计意见搜集
负责设计方案的人必须负责搜集设计意见。我不同意方案由下属设计,意见由下属向上级搜集。我认为方案应该由上级负责,而意见向下属争取。若是有一个上级并不负责设计方案,那么他也不该该有权力去“评审”这个方案。这样作看起来风险很大,由于咱们不少的上级并不负责具体的“设计”工做,可是对比起上级提供一些不知道该怎么办的“指示”,而非要加到方案中去的状况,可能危害要少的多。

通常来讲咱们认为上级会比下属的经验更丰富,若是“无权”评审方案,就必须换一种工做方式:要不本身来作设计,要不采用建议的方式说服下属——这样作的好处是能让上级对本身的概念讲解的更清晰、更细致。不然不足以说服下属。

2. 设计评审
设计评审的形式每每是一个结论是yes or no的会议。可是实际上要用好这个沟通工具,却不能怎么简单。首先,方案的评审提交者应该是最后决定者,固然应该在一个机制的监督下决定。这个决定就是,对于与会者提出的问题,包括提交者提出的问题,都要有明确的答案。

与会者可能会与提交者就一些问题有分歧,但提交者会有最终决定权。这个机制听起来很荒谬,好像本身指定法律本身又能够修改。可是,实际的开发上,若是方案和执行者并不统一,最后执行者仍是会有办法“规避”一些决策。这里也涉及一个重要的问题,就是要把权力给有能力承担他的人。不能想着只是让某些本身还不放心的人去作方案,而后试图在评审的时候“把关”了事。

最后把关当然比不把关要好,可是把关要避免成为扯皮或者阳奉阴违,就必需要权事统一。真正的把技术的知识灌输到底,这样会耗费指导者较多的精力,由于须要在提交评审前更多的沟通。固然了,虽然方案又提交者决策,可是,做为业绩考核和技能评定,上级仍是能够针对这些设计方案来给出专业评判意见。对于很是顽固者,实际上也有一个“秋后算帐”的“威慑”。

设计方案,也是开发者的一个重要输出,表明了开发者的技术水平和工做绩效。

对于设计方案的组成部分,下面架构设计章节会有更多的讨论。

测试

1. 单元测试
单元测试的好处是让你在设计代码以前,就要考虑别人如何去使用你的代码。代码的可读性是创建在读者的前提上的,若是强迫第一个读者和使用者就是做者本人,那么在设计API和接口部分,就会考虑更少的耦合。由于强耦合会让单元测试很是难写。IDE和单元测试结合是一个很好的实践,虽然并不能节省多少输入的代码量,但起码会给与一个正式的环境。

每一个细节组成部分的正确性测试,会加强你重构代码的信心。对于单元测试,我认为最少应该覆盖全部正确的路径,以及重点防护的错误路径。对于覆盖了这些重点关注的地方以后,放开手重构代码就很方便了。虽然不少语言能经过编译就已经消灭了不少的BUG,可是起码仍是要运行一下。而单元测试能够分区域的运行完成的代码,避免的整个系统一块儿运行,忽然爆发一长队的错误,让DEBUG工做无从入手。

单元测试应该是代码的一部分,和源代码一块儿存放。自动构建时也应该进行检查输出结果。一般提交代码的时候都会自动运行单元测试,可是当版本树有分支合并的时候,单元测试尤其重要,而最重要的是在分支上创建的单元测试,这些测试会大大增强系统的稳定性,由于检验了“合并”功能产生的代码——这些代码是最容易出错的。

2. 系统测试
系统测试的自动化程度决定了其重要性。系统测试必定要先办法找到测试的“切入点”,如对WEB系统测试,使用HTTP请求列表做为测试发起事件。对于WINDOWS测试,则使用窗口消息。对于服务器,使用协议包。必定要想办法把手工操做“记录”成可编程控制的操做。第二个重点就是要有办法用程序鉴别测试目标的输出,这里可能会用到正则表达式,词法分析,图形辨认等,可是若是一个好的系统设计,在考虑到测试时候,应该设计出尽可能简单的测试输出点数据。如一些结构化网络数据,或者客户端数据中的模型数据等。

系统测试的环境自动化部署是关键,其中测试数据还原也很重要。通常系统测试须要反复执行——每次发版本都要。而测试结果不少和数据结果有关,所以必定要有办法把系统的数据(数据库内容)还原成每次测试的初始状态。这个在创建系统测试的环境的时候就应该考虑,而且作成每次测试执行前都自动还原数据,不然最后的“断言”测试极可能会失败。

3. 压力测试
咱们必需要作压力测试。由于咱们要提供有限服务。服务器或者客户端都应该对系统的最大能力值有一个设定,而后经过压力测试得到最可靠的数据,用以设定这个值。这样能保证程序在合理环境下正常运行。
压力测试能够经过搜集、复制产生数据。好比服务器能够记录网络请求包,而后按会话记录成一个个队列,最后经过并发一块儿回访,就能够模拟多人同时的状况。若是还不够压力,能够复制队列,而后修改一些互斥数据(如用户ID),产生更大的并发压力。这种测试每每能很真实的反应状况,缺点是必需要搜集必定的用户操做。可是我以为公司通常的QA的操做就是很好的复制源。

压力测试若是用本身构建的压力数据,须要注意的事项:密度、顺序、覆盖率。有时候须要本身构造压力数据,我认为最少应该有几个可输入的调控相:每秒并发发起多少请求,每一个请求的间隔时间;每一个请求的顺序是否按预约顺序排列好(由于有的操做是须要前后次序的),请求包是否覆盖了系统的全部处理逻辑,而覆盖的密度比例是否和真实的环境大致相似。如各类协议格式的包,是否按外网的比例来产生。

压力测试必需要注意专用环境:带宽、磁盘、硬件、测试数据还原。高速的局域网,最好和办公网分开,不然会影响工做。磁盘要清空足够大,不然可能会让日志把磁盘填满。要用专用的测试硬件,以避免形成别的工做数据的破坏——同时也提供了性能指标的硬件基准,这个尤为重要。压测的数据包数量巨大,必定会产生巨大的持久性数据,为了能够重复操做,这些数据必定要能自动还原。同时也是保证自动化重复压力测试的须要。

编写

1. 需求分析
KISS:保持简单。需求之因此复杂,是由于人的思想难以界定,充满了是和否的中间地带。因此第一原则是:只认可肯定是的需求。将来的需求暂时不考虑,在第一批需求完成后,真实的第二批需求就会肯定下来。人类不可能未卜先知,因此不要妄想一开始就能准确的预测需求,只须要把肯定的需求理解清楚,就打下了基础。以学习的心态去了解需求,不要被固定的合同束缚,才真正能跨过需求的第一关。软件领域最大的、永恒的挑战,正是需求变动!

面向对象分析:寻求领域概念。计算机把世界抽象为0和1的序列,这种方式也影响了程序员。可是世界是复杂而多变的。固定的数据建模已经被证实了没法很好的应对需求变动,因此真正的方法应该是去先认识世界,对于业务领域中的概念作学习和界定,而后用面向对象的方法去框起来。这样“对象”和现实世界与0、1之间,就搭起了一我的类能够理解的桥梁。所以咱们的需求应该从领域模型出发,使用业务领域的名词做为系统中对象的名词,尽可能用对象去“描述”这个领域中的概念,而不是急着去完成一个个概念供使用者交互的“流程”。

需求分析有不少工具,如领域建模。UML中的用例图和用例规约。针对非功能需求的“场景-决策”表格。还有著名的鲁棒图,能够转变成UML的模块图。这些都是值得学习的需求分析工具。并且不会太花费时间。

2. 代码风格
这个方面《编写可读性代码的艺术(ARC)》里面说的已经很详细。只须要认真的按照里面所说的去作就能够了。

另外有一些惯例,我以为明确一点的好:

  • 关于英文缩写命名,为了简单,通常只取前三个非元音字母为好,并且单词长度超过5个字母的才缩写。
  • 对于C++这类兼容过程式的语言,若是是过程式的变量或函数,应该采用下划线链接小写单词,如arg_num, get_file_name(),若是是和类与对象相关的,包括属性、方法,就采用JAVA风格的命名,如argNum, getFileName()

3. 代码重用
理论上代码重用这是个大话题,不该该放在这么小的位置来讲。可是实际上软件开发不少地方都涉及重用。因此这里只提一些我认为最重要的:能下载到的代码毫不开发。——事实上不少程序员都以从新发明轮子为荣,而且都认为别人的轮子很差用,好比鄙视STL的C程序员比比皆是。我认为老板给你的工资不少时候并不包括从新发明轮子,无论你以为怎样,学会使用已有的轮子都是一个程序的义务。不然等于浪费老板的投资,对于本身来讲虽然好像技术长进了,可是整个项目都被你脱了后腿。与其你本身去写STL,不如去认真读一读STL源码,掌握它的内容,而后教更多的程序员去用他。不然我怀疑最后你只能去写汇编了,那就随便你了。

代码重用每每和机器性能有必定冲突,可是在我看来,不多项目由于性能差那么一点点而挂掉。可是由于代码开发效率过低,跟不上项目需求变化而挂掉的项目多的多。因此那些只以性能做为技术水平标杆的程序员,某些时候是项目的毒瘤!

4. 设计范式
过程式:C语言
结构化编程当中,最重要的设计方法是:自顶而下,逐步细化。不管你是否在写过程式范式的代码,这个方法都应该遵照,不然必定会出现划分粒度不一,难以重用的代码块。大部分的巨大函数体都是忽略这个原则形成的。

通常来讲C语言会要求对一个内存进行操做,而且反应执行结果在其之上。因此一般都会有一个相似g_Env之类的全局变量,用来存放多个过程须要的数据。为了不多个函数须要反复的经过不一样的输入参数和返回值来“串接”调用,一般都会设计成一块儿去修改 g_Env变量。

同时也会有一个g_Cfg的全局变量充当配置文件。面向过程的代码则不多使用全局变量做为“操做台”来处理数据,由于都被封装到对象里面了。

C语言的回调模式通常经过函数指针来实现,这个几乎是作框架代码的最好用的方法。而面向对象则采用多态来取代函数指针,会更安全一些。

对于函数的返回值,通常来讲不会用来真正的“返回”某些数据,而是返回的是处理的结果是否正常\异常。而处理结果的数据每每经过输入参数(指针)来获得,这个是和面向对象代码很大的区别。面向对象的语言通常支持异常,取代了返回值的“错误报告”功能,而返回值则真正是一个处理的结果。这样减小了输入参数,会让API更容易使用,符合理解习惯,也更不容易出错。

整体来讲,注意抽象好函数的层次,使用统一的,尽可能少一点的全局变量,使用函数指针实现回调,使用返回值做为函数的错误报告,使用输入参数,就是过程式C语言的主要特色。

OO:设计模式
对于封装、多态、继承的玩法,最后演变成GOF23种设计模式。说到底都是为了实现几个主要的原则,其中最关键的就是“开闭原则”。这方面的书籍也是汗牛充栋,特别须要关注的是《重构:改善既有代码的设计》。

面向对象编程方式是如今最利用适应需求变化的一种技术。包括泛型这种静态化的对象技术。因此不管什么缘由,都应该掌握必定的这方面知识。

面向对象设计范式的核心点是去描述现实世界的概念,而非用算法和数据去模拟这个世界的运行。由于关注点在概念这种名词特征上,因此能够先初略后精致的逐步细化设计,正好符合需求变化的特征。

动态模式:JS/PHP/PYTHON……
动态类型语言以其极致快速的开发效率,容易掌握的语法而闻名。其中最能提升效率的是动态数据类型。减小了大量的声明、定义和局限的代码。甚至减小了大量的数据结构的使用。如PHP里面全部的数组都是哈希表,而JS/PYTHON里面的Object就是哈希表。实际上AS3.0也是有相似的特性。更好的利用这些语法糖和数据类型是提升开发效率的关键。因此我也反对在这类语言里面本身从新包装一套相似C语言的数据结构或者容器类库,实在是不必。

动态类型语言另一个特色是脚本化解释运行,不须要维护堆栈,也不须要考虑编译的定义。甚至还有交互式终端一行行的去命令式运行代码。把尽可能多的业务逻辑的处理细节“过程”用动态类型语言(脚本)来执行,是提升开发效率的重要手段。若是你比较一下用C语言编写CGI和PHP比较一下,你就知道效率相差有多少了。

特定领域:SQL/SHELL
SQL这类语言和通常的语言有比较大的设计差异,他更多的设计为“表示”而非“命令,因此须要另一种思考方式。而这类语言由于和领域结合很紧,因此是强大的领域工具,包括SHELL和AWK这种脚本语言,具有别的语言很是费劲才能实现的功能。在这些领域,尽可能使用这些语言会有事半功倍的功效。

SQL中的函数和存储过程,是强大的工具,有时候整个统计系统均可以直接在数据库里面运行。而不少运维的系统工具,用shell来实现则会简单高效,由于须要操做的功能是操做系统自己。

函数式:强大的数学表达力
Lisp,schema,erlang这些函数式语言,采用链表来描述一切,只须要栈而无需堆,用递归代替循环,这些都很符合多核并行运行的要求,并且还能很方便的中断和恢复程序运行。在业务需求变化较少的,而计算任务比较多的场景,是一种很是强悍的编程工具。对此我了解不是不少,可是很但愿有机会能用函数式语言作一个东西看看。

构建-集成-部署-测试

版本管理-构建脚本-自动构建-构建包管理:
全部的源代码都必须进入版本管理;全部的构建、部署、测试脚本也须要进入版本管理,全部的一切都应该进入版本管理。一个构建系统的运行,应该是能够彻底从版本管理服务器上重建一切的。

Hudson是一个很好的自动构建服务器,可是构建脚本你仍是须要本身去写。确保你的脚本能够从零开始构建,而且在全部你可能碰到的平台上正常构建,如32位和64位系统。

构建出来的软件包,应该让hudson这类系统自动发布给全部相关的人,并且能够很方便的经过网络获取到,如HTTP或者SVN。而且须要保留多个历史版本以备回滚。

部署脚本-部署环境-自动部署
部署脚本每每是用动态语言写成,还会带有数据库操做等复杂的内容,所以必须也归入版本管理。部署环境应该是足够安全并且和生产环境有足够快速的网络链接的。有了这些保障,才最后有自动部署的可能性。最好就是有一个部署服务器是和生产环境和办公网络,都属于内网(局域网)链接的。简单的自动部署工具必需要运维人员能掌握,而且取消开发人员的使用权限,避免开发人员直接修改线上服务产生的故障。

各种测试-自动测试-结果报告
代码提交前应该运行完成单元测试,代码在自动构建以及自动部署后,应该自动运行必定的系统测试脚本,结果放置到构建报告中。

通常来讲,测试环境有几种:开发环境、内测环境、外测环境、运营环境。

在开发环境应该是单元测试的运行环境。内测环境则应该是在自动部署后的其中一个环境,用以和产品人员沟通和验证基本功能。外测环境应该和运营环境尽可能一致,自动部署后,全部的测试失败和人员手工测试缺陷,都应该视之为BUG进入跟踪系统。并且外测环境应该是运维人员的工做范围,不该该让开发人员上去捣鼓。通过了这三层的测试环境,无论是代码功能仍是部署设置,应该都能自动化的在运营环境上可靠的运行了。

重构

两顶帽子:加功能、改结构
关于重构有不少经典的书籍能够参考,好比《重构:改善既有代码的设计》《重构与模式》。但其中很重要的一点,就是重构的时候禁止添加新的特性,由于会让代码在修改的时候陷入复杂的“连锁”修改,从而让重构困难增长。同时若是你修改了特性,也须要新的单元测试来保障重构的正确性,这些都是本身搅合本身的作法。而在增长特性的时候最好也不要重构,由于你在努力经过测试的时候,也是在整理和验证需求。只有需求肯定了,重构的目标才会清晰。

单元测试的重要性
重构的一个最大的困难,就是怕改的代码太多,从而出现BUG。可是若是你有一个覆盖率很高的单元测试集合,你就能够比较放心的去修改代码,由于一旦出错你马上就能知道。固然有不少时候单元测试并不是万能,有些状况单元测试确实没法覆盖,或者架设测试自己比较复杂。因此说重构仍是一个比较高风险的动做。测试的工做自己是重构成功的最重要保障。

明确重构目标
不少时候重构起源于某些需求难以加入现有系统,可是若是只以这个做为重构目标,每每结果并不是彻底让人满意。实际上重构的目标应该是一个对于需求变动的总结以及前瞻。某些时候是以实现某种设计模式做为重构的目标。而选取的模式就是对于需求分析的结果。重构中目标的选取是相当重要的,这个须要对业务和技术有深刻的理解,从另一个角度看,重构目标和一开始的设计工做是同等的工做。因此说软件开发的“架构设计”其实是持续在进行的。

加班

加班的缘由:学习、体力活
程序员的加班司空见惯,究其缘由,有两种,一种是不知道如何实现,另一种是工做量大。

对于第一种状况,有些人会写一堆代码而后调试,发现不对又改。而我建议是应该把“不肯定”的部分,设计一些代码片断功能(单元),而后使用单元测试做为验证,经过逐步掌握这些功能,最后造成可重用的代码。这会是最节省时间的方法。

对于第二种状况,应该多考虑设计一些工具。好比使用一些脚本语言来代替一些数据的体力活,尝试抽取可重用代码来简化逻辑。作这些可能一开始会比较费时间,可是长期来看,倒是能够节省下大量的加班时间。

实际每一个程序员都知道生命宝贵,并不会有意的拖延工期,除非以为这个工做实在是不值得去作。因此由于进度缘由致使的强制加班,最后都会被“减班”还回来。损失比不加班还要大。《人件》里对于这个有详细的论述,我也不去重复了。

若是是自愿性加班,本节会有用。若是是被迫性加班,其实是不管如何不会增长总体的开发效率。因此若是真的要用加班这招,最重要的是变“被迫”为“自愿”。

若是做为团队领导者,你看到整个团队已经能在天天6小时内高效的工做,再强迫加班最后只能是下降开发速度。缘由再也不细速,能够参考《人件》。所以,如何让团队加班的方法,应该改为如何让团队不用加班的思考。改进开发工具,提升开发技术,增强团队建设,这些都是有效的方法,惟一须要避免的就是如何“强迫”团队加班。

避免加班的方法:思考设计、学习提升工做效率的方法、在上班时间内加班
根据个人经验,若是一个程序员一天有6小时都高度注意力的作开发,实际上开发效率已经能够达到很高,而不少一天工做12小时的程序员,其高度注意力时间每每只有4个小时。因此不加班彻底是可能的,除去别的因数,对于我的来讲,避免本身玩死本身是最用的知识。在动手以前先仔细考虑清楚细节,能够避免后期逻辑BUG的折磨,这种BUG是最难调试的。而学习各类工具以及关注代码在提升开发效率上的知识,则是另一个重要的手段。所以再次吐槽那些不重视开发效率的程序员,大家轻视面向对象,轻视软件工程知识,轻视那些对程序性能无关的知识,最后的苦果就是——一生加班!

程序员的状态起伏

【设计-编码-调试-总结】的循环
程序员在开发程序的过程当中,每每会经历以上几个阶段,在编码阶段是状态的高峰,调试阶段开始陷入痛苦,不少时候会跳过总结。整个循环完成后,则是疲惫不堪,注意力没法集中。所以咱们能够注意几个重要的环节,减轻这些压力。

首先设计阶段若是能尽快热身,直接更专一的深刻细节,则会避免无休止的修改方案,对于开发的指导也会更明确。而编码环节采用更多的工具和技巧减小体力和脑力的消耗。若是设计阶段和编码阶段的工做能关注代码可读性和结构,最后的调试每每也不会很是困难,而后为了奖励一下本身,能够写一点总结。

打破循环形成的心理影响
若是在每一个阶段中能尽可能多的融入下一个阶段的工做,一样也能够起到下降压力的做用。好比在设计阶段就把不少重要的代码命名工做作了,在编码的时候就顺手解决全部的语法错误,调试阶段的测试用例就能够用来做为工做汇报的材料。

避免疲劳战术的方案:缩小循环体
在开发的循环中,每一个阶段越长,最后的疲劳就会越大,而每一个过程越短,则越容易被接受。因此尽可能在设计阶段划分的细致一些,能够明显的下降后续的工做压力。缩小开发流程也是敏捷开发模式的重要观点。这对需求分析、代码结构、测试技巧都有很高的要求。重视这些知识,就会明显的下降工做压力。

四. 架构设计

逻辑架构

逻辑架构主要是为了明确需求而作的设计。针对需求以及需求变化做为架构目标。所以逻辑架构在架构设计中,是对于提升程序员生存率最相当重要的一个设计。采用合理的逻辑架构,将会大大下降需求变动对开发的延迟做用。逻辑架构最直接指导代码中互相耦合的状况,仔细设计好耦合的规则,会让后续开发事半功倍。

逻辑架构的经典模式有《POSA》中指出的几种,其中以分层和微核模式最为经常使用。MVC和管道过滤器模式则在特定系统中是最优模式。后续基于分布系统的SoA等架构模式,则可能是创建在分层的基础上。分层模式能够按需求关注点来划分层次,所以能够安排不一样经验水平的程序员分别承担。微核模式则直接按具体功能划分代码,适合水平相差不大的团队进行功能的并行开发,由于能够单独测试。

无论何种逻辑架构,都是把功能-代码划分红多个不一样的部分。这些部分经过必定的规则互相耦合。这提供了最好的工做量划分依据,以及互相之间的接口定义。因为存在接口定义,未来人员流动的时候,也能够根据接口来理解代码模块的逻辑。良好的工做划分,能极大的下降程序员之间的低效沟通,使得工做能被多我的同时推动,而工做能被同时推动,则是软件项目能利用好人力资源最直接缘由。

须要指出的是,不少使用非面向对象语言的项目,特别是C语言项目,很是蔑视进行逻辑架构设计,由于所谓结构化编程其实约束不多,而你们每每直接忽略掉。这是很是大的问题,致使一些复杂的“过程”最后彻底没法维护。有不少项目到最后无论如何增长人手,都没法提升开发速度,就是由于实际那些代码没法利用更多的人力,反而增长了更多的沟通成本,架构直接下降了开发效率——往进度落后的项目增长人手,只会让进度更见落后。

运行架构

运行架构主要是为了解决运行时的质量需求,主要分为性能需求和可用性需求。系统的性能需求除了在代码内部经过算法来提升,每每还要采用缓存和并行的方式来扩展。这就涉及到程序的运行时设计,如数据处理流,多进程间通信,数据的多种格式转化。对于可用性,实际上也是经过并行热备的方法来实现,所以运行时的各类控制命令、地址、消息数据流也是运行架构须要考虑的。

运行架构一旦肯定,等于大部分的“实现”代码肯定了下来,设计一个有足够扩展性和可用性的运行架构,能够减小后期为了扩展性能或提供可用性作更多的代码。并且也下降了系统在运行期对开发工做的干扰——正在运行系统出了问题,每每是在节假日或休息时间,都会迫使程序员回公司或者上线维护,极大的增长了开发人员的疲劳,一样会影响项目的进度。所以一开始就考虑可用性和性能扩展问题,而且实际的用代码去实现好,绝对是一个未雨绸缪的好方法。明智的项目经理会愿意在项目前期花多一些资源在这种“非功能性”方面的开发,从而获得一支士气水平稳定的开发团队。

一般运行架构须要至少设计一个能够水平扩展的接入层或逻辑层,以便经过增长服务器来提升性能扩展。所以也须要预先设计负载均衡的系统,若是是WEB系统,用DNS轮训是最简单方便的,若是是游戏类用户间交互比较强的,设计一个“目录服务器”用来提供客户接入地址是最少须要作的。

可用性架构中,最少要为逻辑服务器和数据库(持久层)服务器设计至少一个热备服务器,在机器断电或者机房断网的状况下,能够通过程序本身的检测机制,自动跳转到备份服务器上处理。通常数据库服务器mysql采用master-slave用来备用,而逻辑服务器则能够使用目录服务器来指定备份服务器地址。固然了,若是目录服务器也须要热备的话,则须要另一些代码支持,如客户端自己就会去屡次尝试不一样的目录服务器。

通常有“架构设计”的系统都会有运行架构的设计,因此我并不认为须要如何强调其必要性,反而须要强调的是,系统架构设计,远远不止是运行架构的设计。

开发架构

开发架构通常用于知足开发时质量需求,和逻辑架构有密切的关系。开发架构定义了源代码、二进制和发布包的文件、路径、负责人的划分和依赖关系。一个按照固定开发架构设计的系统,能方便的开发出持续集成的各类工具。

开发架构通常的主要呈现形式为SVN目录构造方式,或者在makefile、IDE的项目设置文件中。一个软件一般分红多个不一样的“系统”或者“项目”。不少如Eclipse须要每一个项目只存在一个执行入口main(),因此开发架构在这种状况下同时也收到运行时架构的进程设计限制。

通常来讲功能相对独立的代码会成为一个“模块”或者“系统”(项目),经过提供程序连接接口,如DLL,.a和.h文件,JAR文件,或者SWF文件来提供。这个粒度的划分有多种标准,如按功能的,按开发者的。可是有一个通用的准则,就是若是已经设计的不一样“模块”中都有调用同一个或者相似的代码块。这块代码就有资格本身成为一个平行的“模块”,以便往后修BUG能够单独升级。

我的比较喜欢按业务功能的层次来划分模块,这样有利于划分任务,减小代码互相影响,最重要的是比较容易让人理解。可是就必须常常把工具类模块协商抽取成为“公共模块”。

部署架构

部署架构对于持续集成,下降程序员的运营期压力,有相当重要的做用。一个好的部署架构能够提升性能和可用性。让程序员能够循序渐进的去解决问题。

运行时架构在软件层面提供性能和可用性。而部署架构考虑的更可能是硬件层面。好比网络机房的分布,服务器硬件的搭配,监控和维护工具软件的安装。开发测试网络和运营网络的设置。关于安全性的配置。

几个比较明确的经验是:

  1. 尽可能靠近用户部署机房
  2. 全部机房间应该有一条专用的局域网链路,让服务器间数据能够有专用线路可用。
  3. 运营网络的防火墙对于公网接口设置为只开启服务端口,运营和维护端口所有放在局域网线路上。
  4. 开发办公网络不能直接和服务器的局域网直接链接,下降我的PC被入侵形成的影响。全部运营网络的服务器都必须限定有限IP的机器去链接远程登陆,而且这些机器须要是LINUX的。
  5. 对于服务器硬件按照磁盘IO密集型、网络IO密集型、计算密集型、存储空间大需求型、经济节省型的分为5种型号,由业务技术人员仔细选择。
  6. 在测试、开发、管理等资源要求很小的服务器上,尽可能采用虚拟机,最大化利用硬件,同时减小维护成本。
  7. 对于平常服务器的维护和监控,创建报警和预警机制,如磁盘、带宽、CPU、特定进程、监听端口。
  8. 对于机器和带宽的部署,采用最少可用性保障的策略,就是最少有2份服务器以及2倍预计带宽需求(或其余需求)。
  9. 对于部署过程须要的脚本、配置文件、安装包,必需要有本身独立的SVN或者文件服务器管理。同时也须要创建“自动化”部署的工具。在这些工具完成以前,不该该正式对外运营。而部署工具自己应该在“外测”环境下通过详细测试,才更新到正式运营网络上。

数据架构

数据架构对于任何业务都有很重要的影响。对于用户产生的数据,架构自己须要容易备份和恢复,数据就是财富,而数据架构是存放财富的方案。对于开发团队产生的数据,则须要完善和方便的管理工具,便于修改和增长这些数据。

数据架构自己还涉及性能、易用性等多个方面。通常来讲分为使用关系型数据库和不使用关系型数据库两种。可是无论那种,对于数据的备份(热备)和恢复都是最首要应该考虑的问题。数据的结构过于复杂其实不利于备份和恢复。而不少时候大数据量又产生“分区”需求(分库分表),这是分布数据存储的课题。

对于使用关系型数据的,通常须要依赖数据库服务器本身的热备功能和分区功能,或者本身去实现。而后使用ORM软件来操做这些数据。因此关系型数据不宜作的过于复杂,太多的“外联”表会让整件事变得很复杂。
若是不使用关系型数据库,如今的NoSQL风潮提供了不少可选的方案,这些方案最大的特色就是对于结构复杂的数据有良好的扩展性,对于大数据量也有优秀的扩展功能——重要的是不用你本身去代码实现。缺点则是可能没法保证“统一性”。比较实际的观点是,尽可能少使用关系型数据。虽然它的概念已经深刻人心。

每一个模块均可以作架构设计

上面的几个架构,基本包含了整个软件架构应该涉及的方面。而咱们每每比较重视一些“大项目”的架构设计,而比较忽视一些中小项目的架构设计。实际上大部分项目并不是“大项目”,而大型项目自己也极可能划分红更小一点的项目来外包,因此咱们应该对于每一个项目,都以架构设计的观点去分析和设计,只是不须要陷入文档的案牍之中就行了。

一些好的架构设计,也能够在多个模块和项目中共用。这种共用的好处很是多,一个是能够节省开发时间,另外也能够少走之前的弯路。最重要的是若是积累下这种设计的文档和思想,可让整个团队的开发效率都获得提升。

五. 管理激励

明确目标

目标管理是现代管理学的一个重要成果。明确团队的目标,而后让全部人都理解并认同这个目标,是管理中最重要的工做。只有每一个人明确了目标,才可能发挥出他的主观能动性。并且要有明确的目标,团队成员之间才可能合做。不然成员之间可能会互相拆台或者推卸责任。

目标应该是整个团队的目标,而不该该是只划分到我的,由于这样不利于团队的整合,而会造成严重的我的主义。固然咱们最多见的是团队中对于目标不明确。

目标应该包括如下内容,才称得上明确。首先是项目要知足的市场需求,这是项目的愿景。其次是项目怎样才叫作的好的标准,通常是和竞争对手比较的结果。最后是项目目标和我的发展之间的关系。三层目标必须都让每一个人明确和认同,才能真正激发出团队的动力来。

市场需求若是你们不承认,就会以为项目不值得作,这个时候就须要领导者来用数据和事实证实给你们看。

项目优秀的标准,不可无限拔高或者虚无缥缈,明确的竞争对手数据是最好的标准,虽然这个信息一般很难得到,可是这个是团队中很是有凝聚力的信息。应该尽可能的获取,而后公布给团队。

每一个人和项目成败的关键,则是核心的激励机制,虽然不少时候开始很难明确到金钱上的奖励,可是应该起码提供一个“最好状况下”的许诺。不少项目以收益分成,或者过程评价来加工资做为明确的激励。

主要手段

人在集体中能发挥的做用必然比单我的要大,这是人类做为群居动物的天性所决定的。若是你有必定的工做经验,一定会体会过一个团结的团队所发挥的良好做用。如何能构造起一个真正的高效的团队,我认为最重要的方法是“沟通”。这种沟通必须是全方位的,包括团队成员之间的私交,他们互相之间在工做能力、人品性格、兴趣爱好方面的了解。在管理者和团队之间,对于项目前景、公司情况等一切和团队切身利益相关的方面的信息,都必须有良好的沟通。若是程序员以为你在隐瞒些东西,你必定就是在某些方面有所保留。这种猜忌会破坏团队的造成。因此对于大量看起来是“保密”的信息上面,对团队尽可能多的公开,是能让团队获得主人翁感受的重要手段。传统管理方法中不少时候强调公司的信息保密,我的对于团队的效忠。而这些在高科技开发企业中是行不通的,由于他们就掌握着公司的最大机密——产品开发。

管理者除了对“人”作事,直接作事也必不可少,开发工做有不少方面是在作设计,因此开发工做自己并非所谓的体力活,而是一些精巧的设计工做。除了本身参与开发工做,对于团队其余部分的设计工做,特别是其中的重要决策,管理者也须要尽可能多的参与。一方面这种参与能够培训团队成员,另一方面能增强对于项目控制。在决策的过程当中,经过普遍的讨论,也是团结团队的一个手段。固然刚愎自用的处理方法就会产生反效果。

由于程序开发自己是一种高度自律型的工做,因此管理者的“不作”比“作”更重要,并且应该提供不受干扰的环境。在程序员注意高度集中的状况下,工做效率是最高的。试图不断的“参与”开发而打断程序员的工做,实际上是在下降工做效率。好的管理者应该能让程序员沉浸在开发工做当中,彻底不去考虑什么进度报告,工做汇报之类的事情。

由于程序员对于电脑的熟悉,因此常常会把一些别“专业”的行当混合起来交给程序去作。好比写代码的同事去处理数据库,由或者让程序员同事负责运维服务器和网络……术业有专精,若是一个程序员专心的作数据库的工做,他会比同时作其余几个事情作的更好。更不用说让程序员去夹网线搬箱子这些了。整体来讲,提供资源支持,下降团队的“非专业”精力消耗。

人力分工

按照专业领域分工;专业再细分分工;软件开发团队应该学习外科医生的团队,采用严格的分工合做,来下降混乱的沟通。每一个人只负责本身的事情,会作的很是好。所以若是程序能很好的分红5个模块,就使用5个程序员,而后为他们配上专业的秘书,数据库管理员,测试人员,项目经理,运维人员,IT人员,以及其余的资源处理人员,好比美术资源处理专员。

关注工做分切点的协议,由于人力分工是提升效率的重要手段,因此人员之间的切分点——协议或者流程,就是很关键的东西。客户端和服务端程序员之间,一般就是直接的通信协议,应该把通信协议变成一种代码,而后双方都使用这种代码。客户端程序员和美术之间一般也应该使用某种基于软件工具的格式文件,好比是UI编辑器的结果。处理WEB的团队每每由美术提供图片,而后由专人切图变成HTML,而这个HTML文件就是很好的协议文件。有些数据录入人员使用JSON格式的文件,或者是某种严格定义的EXCEL文件做为协议文件。

不少团队喜欢“广播”方式的沟通,任何一个事情都让全部人在一个QQ群里面看到,或者任何一个事情都抄送邮件给一堆人。实际上这种沟通只会浪费别人的时间,因此管理者应该下降沟通范围,减小“噪音”。

在《人件》中,提到了高效团队的形式——胶冻团队。也就是咱们所说的很是团结并且互相信任的团队。不少公司会以拓展训练和部门活动的方式去推进造成团队互信,这些都是有用的。可是在工做过程当中,更重要的是让信息共享来打破可能存在的隔膜,给与更大的自由发挥空间让团队成员有机会互动,组织团队成员间一块儿讨论和解决问题。让团队成员都感受到受关注,而且提醒他们互相关注。多让你们一块儿吃午餐。

绩效考核

绩效考核应该考核作了什么事,而不是作的怎么样;这个和不少按“结果”管理的老板很不接受。可是若是你只是想把绩效考核做为一个发奖金的机制的话,单独使用奖金考核机制就能够了。绩效考核应该是推进别人去作某件事的工具。对于已经明确的方法或者子目标,经过这种细化的方式去指导下属工做。由于是须要过后算帐的,并且是量化的,因此下属会对这个事情很认真,同时那些很差量化的事情,管理者也很难执行绩效考核。因此对于“去作某些事”,是绩效考核最好的目标。

经过考核结果提供正式的工做方法意见。绩效考核自己有个反馈的过程,这个反馈的过程应该提供给下属针对每一个具体事情的建议。这种具体的,单独的一对一的指导,会提升团队的稳定性。并且也让团队成员得到“受关注”的感受。这种感受是造成高效团队的重要工具。

考核不能代替目标,不能阻碍目标,而应该是一个沟通工具。绩效考核一般会涉及大量的文档工做,也会有不少量化的工做,可是这些工做,每每不能彻底表明商业目标的完成状况。因此有些时候只是平白的增长了管理工做量。绩效考核的设定首要须要考虑是不能阻碍团队目标的实现。不少时候甚至难以覆盖目标。因此绩效考核应该是成为一种沟通的工具:定时、定量、定人的交换对于工做方法的意见。

目标达成状况做为考核的客观指标,但不该该是主要绩效考核指标。最简单的绩效考核指标就是收入或者利润率。可是这种简单指标除了在动机上提升下属的工做热情外,并无从方法和经验上帮助团队成员。有效的考核是引导下属安装更有经验的方法去实现目标。

进度掌控

经过测试来了解进度;一切软件的开发,若是没法测试,就是没法了解的。没有人回去经过读代码了解项目的进度。因此项目自己必须具有常常提供“可测试”的功能。一旦进入测试,项目完成的数量和质量都马上一目了然了。
用提升工做效率和提供资源的方法推动进度,而不是经过加班。加班是最有效的下降工做效率的方法。只有下降自己进度推动的损耗——内耗,改善工做方法——更好的工具和更多的知识,除此以外很难有别的加快进度的手段。可是,你也能够经过增长更多的资源,好比人力或者机器。如何把资源放在合理的地方,自己是一门学问,本文在上面不少节都有提到如何有效的使用资源——人力和金钱。

庆祝每个进度节点。团队须要鼓励,才能保持速度。庆祝自己又是凝聚团队的一个契机,让成员以为在这群人中间能不断取得成功,自己就会增长互相合做的意愿。若是无故端搞一些团建活动,会让人以为厌烦,可是庆祝进度节点,则你们都会认同,可能只是一块儿吃个饭,可是也是很是有效的一顿饭。

确保公布进度的目标,而且争取团队支持。进度的目标必须能达成共识,“无理”的目标实际上不能成为目标,团队今后也会陷入最差的情况——没有目标。因此进度目标自己须要让全部人理解而且愿意去努力。经过共同的进度目标,来促进团队中全部人的积极性——那些喜欢偷懒的家伙也会很差意思。

在重视质量的状况下推动进度,而且为质量牺牲必定的进度。项目质量是团队和我的为之“自豪”的重要因数。若是你想拥有具有荣誉感的团队,就须要为此付出必定代价,可能牺牲一些时间,来得到更好的产品质量,实际上这是个事半功倍的事情。由于产品质量在长期来看,仍是能提供更好的效益的。进度压力若是形成太多的粗制滥造,会让后期的团队愈来愈没信心遇上进度。最后被迫推倒重来,或者陷入一个“长期的重构”工程中。这些都是缺少远见致使的问题。

预算制订

放松固定资产的预算,尽早投入固定资产预算。项目初期成本中有很大量的固定资产投入。而这些预算看起来能够用更便宜可是质量更差的替代品来替换。可是从长期来看,人力成本才是最重要的大头。而若是你的固定资产太少,也会难以招聘或者稳住最优秀的那批员工。优质的固定资产不但折旧率更低,并且能让程序员发挥出更好的功效,直接节省那些高额的人力成本。
收紧人力资源预算,重视10倍效率员工的做用。人员的沟通成本,是全部关于人员的成本中最高昂的。人越少,须要的沟通就越少。不少公司在发展期喜欢快速扩充团队,但愿能抓住机会尽快占领市场。可是请记住,一个母亲怀一个孩子须要10个月,100个母亲去怀一个孩子,一样须要10个月。团队和项目的进度并不是靠人的数量增长就能加快的。并且更重要的,优秀员工的工做效率最大能够比通常员工的效率高10倍以上,你只须要给他们5倍的工资,就能节省下另外50%的工资,同时还有不止50%的固定资产投入和其余费用。少而精的团队在更方面都比庞大参差不齐的团队更有效率。
针对风险,不断修改预算,项目进度越后期,预算越准确。软件项目开发和拍电影同样,具有很高的风险。不但成本难以预料,并且收益也要最后才能知道。所以对于预算来讲,不断的记录和回顾预算执行状况,以及其效率,修改现行预算方案,才能真正适合开发的进度。那种一年都按年度预算去执行的死板方法,是没法适应快速变化的软件开发项目的。

风险防护

留出过冬的口粮,定出必须笼络的人员,尽早进入资金循环。软件项目风险之高,难以用其余行业彻底类比。就算最著名的公司如微软、IBM也频频推出失败的产品。所以在资金上留有尽可能大的余地很是重要,不少项目经历过濒死体验后,才能实现商业成功。软件项目能继续高效的开发下去,核心人员是相当重要的,让他们拥有足够的耐心和薪水,和项目继续下去,才有收获那天的但愿。而下降风险的最好方法,则是尽快去接触风险,尽快让产品上市,让产品开始尝试赚钱,能让开发方向尽快明确到最实际的内容上来。团队内的争论和疑惑也会由于实际的财务数字而消散,你们的目标会更清晰——赚钱。

师徒制度预备人员流动。人员流动是不可避免的,就算你作到100分,仍是会有别的缘由致使程序员离职。所以除了在代码上提倡可读性和良好的结构,重视文档和过程记录,采用预备接替人员是很重要的手段。让资深程序员和一个学徒程序员一块儿工做,能尽快提升学徒程序员的能力,同时也让代码能有多一我的熟悉。在师傅离职后,徒弟就能够升职到师傅的地位,也是一种良性的激励。而徒弟对于这个代码的感情,是别人所没法比拟的。

尽早进入团队和项目估值,寻找合适的买家。项目除了直接到用户市场上去实现商业价值外,还应该看到,软件项目由于他的结构性和扩展性,每每会在更大的范围内具备价值。一些其余商业方向的公司或者投资人,可能会看重你的项目的扩展价值。而这些扩展价值须要必定时间来让别人认识到,所以对于管理者,在清晰的掌握项目的全面价值的状况下,尽早的介绍给潜在的投资人和客户,能让项目拥有更广阔的前景,从而下降其自然的风险。

相关文章
相关标签/搜索