blogjava-凯发k8网页登录
blogjava-凯发k8网页登录http://www.blogjava.net/killme2008/category/30223.html生活、程序、未来zh-cnsun, 22 may 2011 03:33:07 gmtsun, 22 may 2011 03:33:07 gmt60- 做基础产品的体会http://www.blogjava.net/killme2008/archive/2011/05/22/350752.htmldennisdennissun, 22 may 2011 02:30:00 gmthttp://www.blogjava.net/killme2008/archive/2011/05/22/350752.htmlhttp://www.blogjava.net/killme2008/comments/350752.htmlhttp://www.blogjava.net/killme2008/archive/2011/05/22/350752.html#feedback0http://www.blogjava.net/killme2008/comments/commentrss/350752.htmlhttp://www.blogjava.net/killme2008/services/trackbacks/350752.html 一个公司大了,总有部分人要去做一些通用的东西给大家用,我这里说的基础产品就是这类通用性质的东西,不一定高科技,但是一定很多人依赖你的东西来完成各种各样的功能。做这样的东西,有些体会可以说下。
首先,能集中存储的,就不要分布存储,数据集中存储有单点的危险,但是比之分布式存储带来的复杂度不可同日而语。况且集中式的存储也可以利用各种机制做备份,所谓单点风险远没有想象中那么大。
其次,能利用开源框架的,就不要重复造轮子。程序员都喜欢造轮子,但是造轮子的周期长,并且不一定造的更好。在强调开发效率的互联网时代,如果能直接利用现有框架组装出你想要的东西,迅速占领市场,比你造的高性能、高可用、高科技的轮子更实用。这个跟做新产品开发有点类似,迅速组装,高效开发,然后再想办法改进。
第三,要文本,不要二进制。协议要文本化,配置要文本化。不要担心性能,在可见的时间里,你基本不会因为文本化的问题遇到性能瓶颈。
第四,要透明,不要黑盒。基础产品尤其需要对用户透明,你的用户不是小白用户,他们也是程序员,而程序员天生对黑盒性质的东西充满厌恶,他们总想知道你的东西背后在做什么,这对于查找问题分析问题也很重要。怎么做到透明呢?设计,统计,监控,日志等等。
第五,要拥抱标准,不要另搞一套。已经有了久经考验的http协议,你就不要再搞个sttp,有了amqp协议,你就不要再搞个bmqp。被广泛认可的标准是一些业界的顶尖专家制定出来的,他们早就将你没有考虑到的问题都考虑进去了。你自己搞的那一套,随着时间推移你会发现跟业界标准越来越像,因为面对的问题是一样的。使用标准的额外好处是,你有一大堆可用的代码或者类库可以直接使用,特别是在面对跨语言的时候。
第六,能share nothing,就不要搞状态复制。无状态的东西是最可爱的,天然的无副作用。水平扩展不要太容易。
第七,要将你的系统做的越不“重要”越好,如果太多的产品依赖你的系统,那么当你的系统故障的时候,整个应用就完蛋了。我们不要担这个责任,我们要将系统做的越来越“不重要”,别人万一没了你也能重启,也能一定时间内支撑正常的工作。
第八,要专注眼前,适当关注未来。有远见是好事,但是太多远见就容易好高骛远。为很小可能性设计的东西,没有机会经历实际检验,当故障真的发生的时候,你也不可能完全信赖它。更好的办法是将系统设计得可介入,可在紧急情况下人工去介入处理,可介入是不够的,还要容易介入。
第九,不要对用户有假设,假设你的用户都是smart programmer,假设你的用户不需要位运算,假设你的用户要同步不要异步。除非你对这个领域非常熟悉并实际使用过类似的东西,否则还是不要假设。
第十,咳咳,似乎没有第十了,一大早憋了这么篇无头无脑的blog,大伙将就看看。
]]> - 高质量软件,从点点滴滴做起http://www.blogjava.net/killme2008/archive/2010/12/30/341964.htmldennisdennisthu, 30 dec 2010 03:01:00 gmthttp://www.blogjava.net/killme2008/archive/2010/12/30/341964.htmlhttp://www.blogjava.net/killme2008/comments/341964.htmlhttp://www.blogjava.net/killme2008/archive/2010/12/30/341964.html#feedback9http://www.blogjava.net/killme2008/comments/commentrss/341964.htmlhttp://www.blogjava.net/killme2008/services/trackbacks/341964.html
写这篇文章的想法产生在昨天晚上读《面向对象分析与设计》的时候,我渐渐发现我们这个小组不知不觉地贯彻了很多非常有价值的实践经验,这些点点滴滴都对我们的最终的产品质量产生了或大或小的影响,保证我们的系统不会出现重大的故障。我想有必要将这些“隐性知识”稍微总结一下,以供参考和记录。
从过程的连续光谱来看,我们大概处于中间位置偏左的位置,更偏向一个轻量级团队的敏捷过程,但是也包含计划驱动过程中的因素。我们的小组是自管理的,没有专门的qa和sa,我们自己去想出最好的工作方法,但是在执行中我们的计划还是相对确定的,每个季度做什么都会有一个比较明确的计划和里程碑,并且对问题领域都相对熟悉;我们的过程是迭代式,一般一个季度至少会交付一个稳定可执行的新版本,我们在文档上做的不是特别好,很多都依赖于团队成员之间的“隐性知识”;同时我们对问题的改进基本还是有一个流程和机制,会持续的跟踪问题并改进。
下面分阶段总结下我们的一些实践经验。
一、分析和设计阶段
1、在这个阶段,我们会明确准备做什么,界定问题的边界,对功能进行一个取舍。一般在一个版本完成之后会马上开始这个过程。大家都想一想接下来做什么,经过几轮pk后确定重要紧急的事情优先做,定义下一个版本的功能列表。
2、功能列表出来之后,我们会针对每个功能提出各种方案做比较,在此期间,我们会邀请更大团队范围内的专家参与方案和设计的评审,剔除不切实际以及明显有缺陷的方案,针对一些风险点提出改进建议和防范措施。
3、在设计方案出来之后,我们会分配功能的开发任务,根据每个开发人员熟悉的领域,自主领取或者被动分配任务。这个过程不是一成不变的,考虑到团队内部知识交流的必要性,也可能让不熟悉某个领域的人去做他不熟悉的事情。
二、构造阶段
1、整个系统已经有一个关键的抽象机制,针对凯发k8网页登录的服务器有一个核心的pipeline机制,针对我们的客户端,有一个核心的发送消息流程。将所有的功能模块组织在这个关键机制周围,形成一个强有力的整体。
2、开发完成不仅仅意味着功能代码的完成,还包括测试代码:单元测试和集成测试。如果你没办法做到全面的覆盖,那就要求必须覆盖运行的关键路径和极端场景。
3、单元测试我们使用junit,适当使用mock可以简化测试。但是mock对象如果太多,也许会失去测试的价值,这里有一个权衡。
4、在整个构造过程中,我们贯彻每日构建、持续集成的原则。使用hudson做持续集成,时刻关注测试状况,有问题及时反馈给开发者。
5、有一个功能强大的集成测试框架,模拟实际环境做各种测试,它的目的是尽量在接近真实状况下去执行系统并尽早暴露问题。
6、每个功能完成之后,立即发起review,请同事和你一起复审代码。复审代码的作用不仅是发现bug,改良设计,也是一个知识交流的最佳途径。我们经常能通过代码审查发现一些设计上的缺陷,以及功能实现上的bug。我们团队应该说是非常看重代码审查的作用。
7、使用findbugs和clover等工具,分析代码质量并改进。
8、在发布之前,做一次集中的代码review,每个人介绍下自己的功能实现代码和设计,一般我们会申请一个会议室和投影仪,并邀请团队之外的人加入review。
9、在发布之前,有一个系统的压测流程,针对每个版本更新压测方案,并预留一到两周的时间做性能压测。压测不仅能尽早暴露性能隐患,还可以发现系统在特殊情况下的一些bug。压测除了关注系统的吞吐量、gc情况之外,还应该关注硬件的性能指标。
三、发布和总结
1、发布之前,最好让使用我们系统的用户使用新版本做一个回归测试,一方面是测试兼容性,一方面也可以及早发现bug。
2、我们的发布流程:线下、beta、线上。每个阶段通常都持续一到两周,才会进行到下一阶段。并且是从相对不重要的系统,到关键系统的顺序进行发布。
3、发布之后,通过日志、运行时监控、用户反馈等方式收集系统运行状况,发现bug,修正bug,补充测试,测试通过,重新发布。
4、每个版本发布后,需要总结下本次发布过程中遇到的所有bug以及经验教训,并提出可能的改进建议。
5、需要一个跟踪线上问题的bug跟踪系统,可以用jira之类的trace软件。跟踪不仅是记录,最好列出解决的时间点,在哪个版本确定解决,甚至确定交给谁去解决,并持续跟进。
]]> - 代码自我审查的一些体会http://www.blogjava.net/killme2008/archive/2010/05/18/321219.htmldennisdennismon, 17 may 2010 16:28:00 gmthttp://www.blogjava.net/killme2008/archive/2010/05/18/321219.htmlhttp://www.blogjava.net/killme2008/comments/321219.htmlhttp://www.blogjava.net/killme2008/archive/2010/05/18/321219.html#feedback3http://www.blogjava.net/killme2008/comments/commentrss/321219.htmlhttp://www.blogjava.net/killme2008/services/trackbacks/321219.html
1、首先态度需要端正,做代码的自我审查并不是否定自己,而是给自己将工作做得更好的一次机会。在审查过程中要尽量将自己作为一个旁观者的心态去审查自己的代码,尽管这比较困难。
2、代码审查离不开重构,在审查过程中发现任何坏味道都请使用重构去改善,发现缺乏测试的地方要及时补充测试,不要让bug遗漏。
3、代码的自我审查可能不是越早越好,隔一段时间之后回去看自己写的东西,对一些设计上的选择能有更客观的评价,在审查的过程中可能需要重新去理解代码,在此过程中可以检查自己代码的可读性,并思考如何改善可读性,切记代码首先是给人读的。
4、审查过程中需要记录下一些犯下的错误,以及当时为什么会犯下这样的错误,建立自己的bug数据库,并时常review,在以后的工作中避免同样的错误。
5、代码的自我审查应该是一个持续性的过程,而非特定时间的特定行动,时常审查自己的代码,不仅能辨析自己的得失,还能够进一步提高自己在未来工作中的设计能力和预见能力。
6、代码的自我审查跟团队成员之间的相互review并不矛盾,在相互review之前做一个自我审查,有助于提高review的效率,包括可读性的提高和一些一般错误的避免。
7、代码自我审查的一些常见注意点:
(0)自认为绝不会出错,并且从来没有审查过的代码。
(1)注意else语句,if条件下的子语句通常可能是个正常的流程,而else意味着异常的情况或者特殊的场景,你可能特别注意怎么处理正常的情况,却忽略了else子句的实现细节,如该释放的锁没释放,该递减的计数没有递减,该赋予特殊值却没有赋予等等。
(2)注意空的方法,没有方法体的方法,是不需要实现?还是忘了实现?
(3)注意switch语句,有没有忘了break?这种错误通过findbugs之类的静态代码检查工具都能避免。
(4)注意大块的注释,为什么这么多注释?是代码写的很糟糕?还是遗留的注释?遗留的注释会误导人,要及时删除。
(5)注意一些看起来“不合常理”的代码,这样的代码很多都是基于所谓性能考虑而优化过的代码,这样的优化是否还需要?是否能去除这些“奇怪”的代码也能实现正常的需求?
(6)对客户端的使用有假设的代码,假设用户只会这么用,假设用户只会用到返回对象中的某些属性,其他属性一定不会用到?不要对客户代码做假设!这个客户代码包括外部用户和调用这个模块的内部代码。
(7)标注了fixme、todo之类task标签的代码,是否忘了修复bug,实现功能?
(8)任何超过15行以上的方法,这些方法是否能拆分成更细粒度的方法,并保持在同一个抽象层次上?
(9)任何在代码中出现的常量值,是否应该提取出来成为单独的常量,常量的默认值设置是否合理?
(10) 任何持有容器的代码,提供了放入容器的方法,是否提供了从容器中移除对象的方法?确保没有内存泄漏的隐患。
(11)重构中提到的其他坏味道,别放过它们,但是也不要追求完美,oo不是圣杯,如果能简单的实现一个算法,你不要引入3个对象和4个接口。
(12)在review最后能列出一张清单,开列下该项目面临的风险点,并提出解决办法,然后按照这张清单去review关键代码,着重检查异常情况下的处理。风险点的review,我建议可以放在后面,在一般性错误解决之后进行,此时你对代码也将再度变的熟悉。
]]> - 从nt开发过程中看到的东西http://www.blogjava.net/killme2008/archive/2009/08/13/290969.htmldennisdennisthu, 13 aug 2009 04:44:00 gmthttp://www.blogjava.net/killme2008/archive/2009/08/13/290969.htmlhttp://www.blogjava.net/killme2008/comments/290969.htmlhttp://www.blogjava.net/killme2008/archive/2009/08/13/290969.html#feedback2http://www.blogjava.net/killme2008/comments/commentrss/290969.htmlhttp://www.blogjava.net/killme2008/services/trackbacks/290969.html
单纯从软件构建的角度去看这本书,可以说说我看到的东西,这些是我今天早上走在上班路上的时候想的,咳咳。
1、开发os是烧钱的事情,nt开发接近5年,每年的花费据说在5000万美刀,那可是在90年代初期,换算成现在更是天文数字。从另一个侧面也说明了linux系统的伟大。开发一个这么烧钱的玩意,如果没有管理层的强力支持,那么不是被砍掉,就是遭遇流产的命运,幸运的是nt团队得到了盖茨的鼎力支持,大概也只有他能这么烧钱了。dave culter从dec辞职的原因也是因为管理层砍掉了他的团队。盖茨另一个做法是不干涉nt团队的开发工作,他只提出目标和期望,然后就偶尔过来看看,不对不知道的东西指手画脚,这点可不容易。
2、每日构建非常重要,nt团队的构建实验室一开始是每周构建,后来做到了每日构建。只有每日构建,持续集成,才能帮你掌控产品质量,及时发现潜在的问题。我们现在的项目使用了hudson,比cc容易配置一点,效果还不错。
3、测试极其重要,专业的测试团队对于大型项目来说尤其重要。除了测试人员之外,开发人员需要做自测,需要对自己check-in的代码负责,如果你签入的代码导致构建失败,那么dave culter可能冲破墙壁进来,拍着桌子冲你咆哮。对check in必须做严格控制和跟踪,如果在项目的最后冲击阶段,除了showstopper级别的修正代码允许签入之外,其他的修改都不被接受。开发者和测试人员很容易存在对立,检讨自己,我对测试人员也存在偏见和某种程度上的轻视和厌烦,如果从就事论事和都是为一个目标努力的角度来说,测试和开发并不对立,两者是相辅相成,甚至于测试人员更为至关重要。
4、在一个长期而复杂的项目中,如何保持团队成员的士气也是个难事儿。软件开发归根到底是的因素是人,而非工具或者其他,关注人,其实就是在关注你的软件。鼓励士气的常见做法就是设定里程碑,在这个里程碑上发布一个重要版本,让大家看到希望,但是对于os这样的巨型项目来说,里程碑不是那么容易设定,这从书中项目的不断延期可以看到。另外就是宽松的工作环境和假期,微软的工作环境有目共睹,能做到每个员工独立一个办公室的国内企业还没有吧。国外的开发者似乎很会玩,赛车、滑雪、空手道,其实不是我们不会玩,是我们玩不起,国内的待遇和生活压力让你想玩也玩不起。
可是就算是再好的物质待遇,其实也换不来美好生活,书中充斥着开发者对家庭和婚姻的困惑和痛苦,为了nt,他们也失去了很多,对工作过度投入的后果就是失去平衡的家庭生活,再次验证上帝是公平的,有得必有失,就看你看重的是什么。
5、开发者的效率差异是惊人的,在《人月神话》里已经说明了这一点,开发者之间的效率差异可以达到惊人的10倍,在nt这样的团队里也再次验证了这一结论。
6、投入越多的人力,并不能带来效率的提升,当ntfs文件系统的进度拖慢的时候,微软的经理们考虑添加人手,但是经过慎重的考虑还是没有加人,因为文件系统是技术活,新人很难马上投入开发,而需要老手的带领和培训,引入了更多的沟通成本和培训成本。
7、优秀的代码无法通过行数来衡量,软件某种程度上还真是魔法的产物。
8、nt的一个教训是,应该及早设定你的性能目标,并在适当时候开始关注并优化系统。nt团队后期的很大部分工作都是在优化系统性能,并缩小尺寸。
9、设定deadline常常是不靠谱的事情,对软件开发的时间估计也常常是不靠谱的事情,这一点从nt的一次又一次的延期可以看出。延期失望的不仅仅是客户,也会打击你的团队成员,遥遥无期的开发过程容易让人崩溃。
10、nt的开发贯穿了对市场的需求的考虑,有个牛x的产品经理还是相当重要的。当然,没有开发者喜欢添加新功能,特别是在已经完成一个新功能的情况下,以至发展到nt的开发者看到产品经理就不由得拿起球棒击墙的地步:)
这本书花了我两个晚上看完,还是看故事有趣呀,上面所说只是我的印象,书中还有许多八卦故事老少咸宜,如果有出入,请看原著:) 有空还得重读下。
]]> - 说说迭代中的需求变更(更正)http://www.blogjava.net/killme2008/archive/2008/04/28/196940.htmldennisdennismon, 28 apr 2008 13:04:00 gmthttp://www.blogjava.net/killme2008/archive/2008/04/28/196940.htmlhttp://www.blogjava.net/killme2008/comments/196940.htmlhttp://www.blogjava.net/killme2008/archive/2008/04/28/196940.html#feedback4http://www.blogjava.net/killme2008/comments/commentrss/196940.htmlhttp://www.blogjava.net/killme2008/services/trackbacks/196940.html
]]> - 代码详查的几个要点http://www.blogjava.net/killme2008/archive/2008/03/20/187420.htmldennisdennisthu, 20 mar 2008 02:27:00 gmthttp://www.blogjava.net/killme2008/archive/2008/03/20/187420.htmlhttp://www.blogjava.net/killme2008/comments/187420.htmlhttp://www.blogjava.net/killme2008/archive/2008/03/20/187420.html#feedback1http://www.blogjava.net/killme2008/comments/commentrss/187420.htmlhttp://www.blogjava.net/killme2008/services/trackbacks/187420.html
2、详查应当专注于检测错误,而非修正
3、详查的角色包括:
1)主持人:负责分配复查任务,报告详查结果,主持详查回忆,他需要能够理解被详查代码的相关技术细节,整体上控制详查进度
2)作者:代码的作者,负责陈述项目的概况,解释设计和代码中不清晰的部分
3)复查者(reviewer,《代码大全2》称为评论员,感觉不是很恰当):负责实际复查的工作的执行,负责找出缺陷。
4)记录员:记录发现的错误,记录任务的指派情况,记录会议
5)管理人员:详查是一个纯技术性的复查,应当避免管理人员的介入。如果管理人员介入了详查,那么参与的人可能会觉的在被评价,而不是去复查材料,导致焦点从技术问题转移到行政问题。按国情,这种情况相当常见。
4、明确详查的目的是发现设计或者代码的缺陷,而不是探索替代方案,或者争论谁对谁错,其目的绝不应该是批评作者的设计和代码。如果出现复查者做出不恰当的评价和发言,主持人应该制止,引导详查的活动的健康进行。这一点我觉的相当重要,对事而不对人。
5、详查会议后,主持人撰写详查报告,最好能提交给管理人员一份,并且应当及时进入返工环节,将缺陷分配给某人去修复(往往是原作者),并及时跟进监督缺陷的修复情况。
]]>