分类目录归档:未分类

轮子还是要重复发明的

“不要重复发明轮子”,很多开发者在新入行不久,就经常会被这样叮嘱:这个世界上程序员已经太多,遇到的问题已经够多,而解决方案层出不穷。你走过的路,跳下的坑,已经有无数的先驱在你之前路过,跳过。

所以在做技术选择的很多时候,你不需要自己从头去实现一个东西,就可以在现实世界中找到现成的趁手的利器,小到一个类库,工具,大到一个框架,平台,来满足自己的“需求”。你以为你看到了绝美的风景,后面是一马平川。

invent-wheels而这,只是不愿意拒绝懒惰和诱惑的借口,背后很可能面临更多的困难,陷入其中不得自拔。

开发者在技术选型的过程中,很容易对已有的神往已久的某个技术或者工具情有独钟。

“什么都是现成的,直接拿来用(一套)就好了!”

而往往忽略了它们在后期定制化需求,或者弹性及扩展方面对自己可能存在的限制。下面看两个例子。

关于构建工具的例子

比如Maven在Java的世界里很长时间都是主要的自动化构建工具,它的插件化结构,提供的很多现成的archetype和插件,以及命令行和插件化扩展的可能让很多程序员眼前一亮。

而随着手头的项目变得愈加复杂的时候,你会发现Maven的XML声明式结构和插件化,恰恰是阻碍自身伴随项目复杂度进化的绊脚石,因为它缺乏灵活性,以及对于自动化测试实践的支持,尤其在持续交付方面。

Ant有同样的问题,我们不断发现团队在不可维护的Ant和Nant构建脚本上耗费了巨大的精力。由于工具自身与生俱来缺少的表现力以及清晰的模块性,这些脚本难以理解和扩展。

XML配置文件中太多让人觉得多余的尖括号,以及粗糙的插件架构。虽然语法问题可以通过升级换代来解决,但插件化架构严重限制了构建工具随着项目变得愈加复杂自我优雅进化的能力。我们发觉插件的抽象层次是错误的,相反我们更青睐基于语言的工具,比如Gradle和Rake,因为提供了细粒度的抽象,以及更多的灵活性。

Gradle是一个把理智带入企业级构建世界的尝试,它把划时代的技术和最佳工具组合相结合。Gradle可以让你访问你已有的Maven仓库,但通过清晰的领域特定语言为你的构建添加脚本功能。

logo_for_Gradle

相对于像Ant和Maven这样基于XML和插件的构建工具,像Gradle和Rake这种基于语言的构建工具,在持续提供细粒度的抽象和更多的灵活性。这样它们就能伴随项目变得越来越复杂而随机优雅地应对。

关于前端可视化框架的例子

另外一个例子是关于前端(可视化)框架的选择上,一些提供了丰富UI渲染样式的框架库很是夺人眼球,漂亮的表格和图表样式,简单的Demo示例代码,让开发人员都以为这是实现当下棘手UI需求的不二法宝,可以极大地提高开发的效率。

比如ExtJS,开发人员在经历了初期的甜蜜之后,会发现他们很难控制Ext渲染出的HTML和DOM,而编写功能测试代码看起来也不太可能,尤其是当对UI的外观和样式有个性化的定制变化需求时,会显得一筹莫展。

Ext会把你限制在它的UI实现思想框框里面,这样也许可以在那些不需要投资UX的团队里面工作得很好。

Highcharts是个另外一个例子,丰富的图表类型,以及基于提供的图表类型的定制化功能,优异的JavaScript引擎,对HTML内嵌SVG文档的支持,一度是我们在项目中选择前端图表展现库的不二选择:

highcharts

但随着对图表渲染的个性化UX定制需求的加入,我们会发现Highcharts通过公开API提供的很多灵活性,比如对于X轴、Y轴和渲染细节的定制,已经很难满足我们对更多图表本身的修改,和添加新的样式。

而这时候,如果不是让UX设计迁就Hightcharts既有的实现,也许更好的选择是D3,虽然它会在开始显得底层,需要团队更多的精力来创建通用的不那么复杂的可视化元素,但这也意味着更多的灵活性,加上它的插件模型,以及像Rickshaw和Crossfilter这样的库支持,会让D3比以前更具亲和性。

最后

所以对于技术的官方网站提供的所见即所得的特性展示,简单的示例代码,和想当然的心满意足,开发者需要在接受诱惑的同时,多考虑一些在技术投资后可能存在的风险,以及是否有足够的支持。

需要考量的因素和角度可能但不限于:

  • 文档和社区支持的成熟度
  • 复杂的代码示例
  • 可能的功能性需求变化
  • UI呈现上可能的需求变化
  • 性能,安全等非功能性需求
  • 团队知识和学习能力
  • 后期的维护成本

需要针对这些因素,做一一的评估和侦测,才能最大限度地保护成本的投入。

有的时候,你真的需要重复发明轮子。

写作,我写什么?

这篇是关于技术写作系列的第三篇,在尝试解决为什么要写,以及怎么写的问题后,让我们来看一下关于能写什么的问题。但在进入具体的问题,给出一些可能的选项之前,我们首先需要回答的问题是,我为谁而写,写的目的是什么,这两个问题。

what-to-write

写作的目的,受众是什么

按照我自己的写作经验,当开始说我像写点东西,小到一篇文章,大到一本书,这两个问题恰恰是最容易被忽略的。而忽略这两个问题,产生的结果就很有可能是,文章的定位不清楚,读者也很难get到你想在内容中表述的点,成了自说自话,王顾左右而言他的局面。

如果期望自己的内容能在网络发布,或者在一些知名的媒体发表,能影响到更多人,和自己的思想产生共鸣,就要认真考虑这两个问题:

  1. 我写这样的内容是为了什么?是为了展示我对卓越新技术的追求,对技术的深入思考和经验所得,还是展现自己对商业领域知识的掌握。也许会有更具体的目的,比如为了呼应和反驳之前网络上出现的一篇文章。
  2. 我这样的内容的目的受众到底是谁?是有着怎样背景的人,有着多少年经验的人,是大概担任怎样职位的人?为什么他们会对我的内容感兴趣,愿意读下去一直到底,甚至愿意为我传播分享这篇文章给更多的人?我希望她们能得到什么,从我的内容中。

举个例子,例如这篇文章《敏捷软件测试常见的七个误区》,可以分析这篇文章写作的目的是为了分享作者近十年来,结合实际的项目经验,在敏捷测试领域对于自己经验的总结和回顾。而针对的目的读者,就是那些同样从事测试领域工作,但对敏捷测试还不甚了解,或者是刚开始尝试敏捷测试的人,他们对敏捷测试的理解还不到位,对于敏捷测试的那些坑还没趟过,而这样的内容对于他们是很有帮助的。

写作线索的来源

我跟我的同事说,其实什么都可以写,可以写的东西很多啊,但我看到的仍然是面露难色。那现在我给大家介绍一下具体的可以尝试想和写的线索:

Lightening Talk on Insights

就像你能从这幅图里面所看到的,我们可以从日常工作和生活中太多角度,得到写作的灵感了,下面是一些其中的例子:

  • 刚刚解决了一个很难克服的问题。在自己耗费了半天时间,请教了同事,翻查了不少资料后,一个棘手的问题终于被解决了。而这个问题可能只是未来出现的诸多问题之一,要保存对解决方案的记忆,以及分享给更多可能面临这个难题的人,写一篇文章记录下来就是唯一的出口。我的经验是,当过一段时间再次面对这样的问题是,脑子里的答案早已淡去,而当初自己留存的文章记录帮了大忙。
  • 团队在头脑风暴时候的一些想法。“三人行必有我师”,当有更多的人和自己一起动脑经的时候,冲突和想法也会指数级的上涨,而不做记录甚至成文,也是很大的浪费的。
  • 从失败中得到的教训。失败了,也许不会有再次经历同样状况的机会,但对自己的将来,和可能经历同样情形的他人而言,记录的经验会让人获益良多。
  • 从自己阅读的几篇极好的文章中的所得。站在巨人的肩膀上,总是可以有更好的视角和新的发现。所谓的创新也是从前人的研究和总结中来。阅读了几篇同样主题的内容,沃恩总可以有新的角度,或者更高的角度,来看待这个主题。而记录下所思所想,就是一篇新的内容。

情绪写作

这是我自己个人的经验,而我认为这可以提醒到那些实在对周遭正在发生的线索不敏感,而且对上面这幅图中提到的诸多可能一筹莫展的人,那你可以尝试留意你自己的情绪变化。

当你对团队中发生的一些事情表示不满意,敲桌子,大声咆哮的时候; 当你对面对的代码无法容忍,憋着气要对它大动干戈的时候; 当你对一项新技术突然冒出来,你觉得它能极大改善你的工作方式,你对它充满无限激情和饱满兴趣的时候; 当你以一种平和甚至感恩的心态,看着周围发生的一些积极的变化的时候,内心里欣慰自己的努力没有白费的时候;

这些都是你的情绪在发生一些甚至激烈的变化,而这就产生了一些可能,让自己把自己的情绪写下来的可能。

我把这样的过程称作“情绪写作”。

相比较正常状态下的写作过程,情绪写作难能可贵的是,自己的情绪可以支撑自己连续写作很长一段时间甚至一蹴而就。在基本完成后可以离开一段时间,再回头重新打磨,甚至考虑祛除掉那些因为情绪所带来的,对于主题没有帮助的部分,让内容本身主题更加明确,目的性更强,或者显得更加理性。

最最不该做的就是任由情绪稀释,白白流失掉一次很好的写作机会。

最后

到这里,关于写作的三个问题就基本回答完成了。怎么写为什么写,写什么,似乎是当我们面对写作的时候,最首当其冲要解决的问题,而解决它们也不会一蹴而就,甚至可能会在纠纠结结,反反复复中徘徊。

但一旦解决了愿意去写,知道写什么的时候,剩下的问题就好办了。

解读ThoughtWorks技术雷达

接地气的技术雷达

ThoughtWorks在每年都会出品两期技术雷达,这是一份关于技术趋势的报告,它比起一些我们能在市面上见到的其他各种技术行情和预测报告,更加具体,更具可操作性,因为它不仅涉及到新技术大趋势,比如云平台和大数据,更有细致到类库和工具的推介和评论,从而更容易落地。

这是2016年4月份的技术雷达全貌:

2016 April tech radar post

其中,自上次雷达发表以来新出现或发生显著变化的技术以三角形表示,而没有变化的技术则以圆形表示。每个象限的详细图表显示各技术发生的移动。

技术雷达对于不同层级和水平的技术从业者,有可以从不同角度和分类进行解读的可能。不管你是个人开发者,对于新工具和技术有执着的追求,寄希望于从新工具和技术那里获取改进每日工作的灵感,或者你是技术领导者需要针对自己的系统做技术选型,以及对未来技术趋势的把握,技术雷达都会是一份很好的参考。

而如何解读技术雷达就是变成一件很有意思的事情,解读方式可以帮助我们更有效地利用它。下面会介绍几种观察技术雷达的不同角度。

这里可以下载到最新版本的中文技术雷达。

继续阅读解读ThoughtWorks技术雷达

每个人都是内容营销者

在聊了怎么用精益创业的思维开始写作怎的问题之后,我们来尝试回答一下为什么要写作这个问题。而这个是本源问题。

full_res0415

其实这是个老生常谈的问题,很多具有丰富写作经验的朋友或者同事,已经给出过无以复加的观点。

下面是我很认可的几个:

回到写作这件事情,抛开那些“总有一天”才能实现的好处外,眼前的好处无外乎就是帮助我们记录理解消化沉淀学到的知识了。不过我们的内心里总有一个声音反复出现:反正书看了,Session听了,感觉知识已经学会了,那还值得花时间写么?我用这个时间多学点东西不更好?

你越是不开始书写,总是拿有限的思维缓存去默想一个问题,就越是没有内容可以写,如果你逼着自己将一些不成熟的想法写下来,看着自己写的内容,试着进一步拓展它们,就有可能在理性的道路上走得很远,很远。

继续阅读每个人都是内容营销者

用精益创业思维开始写作

我的周围有很资深的同事,进入软件这个行业没有十年也有五六年,我和她们在一个项目中工作时,往往惊讶于她们处处显现的真知灼见。她们会很轻易地点出设计上的短板,流程上的浪费,还有潜在的缺陷,然后轻轻挥一挥手离开,留下我们傻傻地坐在屏幕前,一身冷汗。

而我试图抓住潇洒的她们,说可以把这些宝贵的实践经验写下来,分享给更多人的时候,得到的回复更多是:

啊,我没写过文章啊,不知道怎么写?

这些都是常识啊,很多人都写过了吧,还有什么可写的?写出来谁会看啊?

我实在太忙了,项目家里一堆事儿,顾不上写了。

这是三个问题,我们一个一个来解。今天,我们先解第一个。

很有意思,在我们组建团队,开始构建软件的时候,我们已经习惯了拥抱变化,我们说不变的是需求的变化,我们接纳这样的变化和挑战,我们对它习以为常,我们认为这样才是解决软件需求之道。

我们会和客户以很小的迭代周期进行频繁反馈,然后上线,或者改进,去交付最终的价值。但让人好奇的是,我们对待写作的态度却一直没有怎么变化,没有对待软件变化那样宽容,而是一如从前。

继续阅读用精益创业思维开始写作

Pair小记3——争论

Team的人员组成各不相同,有可能是经验丰富的团队,也有可能有将近半数的新人。这样对于有交付压力的项目来说,采用怎样的技术栈会有不同的观点。有保守起见,不愿意引入复杂框架的观点,也有要努力利用成熟框架学习新技能的想法,何去何从?

Well,这是一个team,自组织的团队,区别在于这样的争论可以让整个team的人来加入来选择,来承担可能好可能坏的结果。

更有帮助的是,可以咨询具备丰富实践经验的来自团队外的专家。然后还是由团队自己来决定。

自组织的团队让我很消受,Who is Boss? Who care!

吉祥三宝TW版

吉祥三宝TW版—

小女孩问:“爸爸,你的code写好了吗”
爸爸回答:“没有。”
小女孩问:“你的pair去哪里了?”
爸爸回答:“在天上。”
小女孩问:“你们发疯coding为了什么?”
爸爸回答:“拯救苍生。”
女儿爸爸合:“济济苍生以软件,担担道义为世范呀。”
小女孩问:“妈妈,爹当码农为了神马?”
妈妈回答:“基业永续。”
小女孩问:“他跟别人怎么不一样呀?”
妈妈回答:“止于至善。”
小女孩问:“别人会尊敬他吗?”
妈妈回答:“等到春天。”
爸爸妈妈女儿合:“不以利回不以义疚就是我们的信仰。”
爸爸妈妈问女儿:“宝贝,你也学你老爸搞软件吧?”
女儿回答:“那妈妈呢?”
爸爸妈妈回答:“妈妈正在面试骚窝的路上。”
女儿回答:“那我呢?”
爸爸妈妈回答:“你像种子一样正在发芽。”
女儿回答:“掻迪斯嘎。”
爸爸妈妈女儿合:“我们三个就是贵司幸福的一家。”

不得不景仰了。。。

Pair小记2

今天Pair遇到的问题是,我跟我的Pair在某一个问题上纠结太久,没能找到解决的方案。这是一个很典型的问题。

浏览器兼容的问题,历来让前端开发头疼。再加上是遗留系统,页面上引入了太多了三方和自己的js导致IE下页面无法显示。

看得出,我的Pair对前端开发经验不多,而我又不能一下子指出问题所在(可恶的IE),Pair自信心比较高,会很坚持用自己的方式来解决,他试图修改一些JS的内容来减少业务逻辑的涉入,以测试能否在IE下显示完整。而根据我的经验,这种IE特有的问题多半是某些JS语法的(不兼容)问题,但办法只有从上到下一个一个JS的排除,直到找到问题JS。Pair的做法引入了业务逻辑变化的不确定性,背离问题本身,反而容易引入更复杂的变化。

可惜我对Pair时所应有的态度和精神体会不深,尝试过说服Pair,但见他坚持,不忍冲突,结果是时间白白浪费。

回家路上跟彦辉君聊到此事,他的建议是:
1. 寻求技术帮助
2. 正义提出自己的想法
3. 如果2不可行,寻找更具说服力的力量

还是需要一种Open的态度。

小步前进

敏捷、Scrum和XP实践里面,到处体现着小步前进。

比如代码重构,这在Martin Fowler的书里面处处谈到,在没有IDE的refactoring功能的帮助下,唯有手头的小步前进,才能保持信心。

持续集成,每次checkin触发一次集成过程,快速的反馈和修复,同样保持信心。

每个Sprint给客户showcase,让实现和需求不偏离太远,才会进入下个迭代,这仍然是个增进信心的过程。

真是欢乐啊!

Pair小记

今天跟凡哥pair,遭遇CXF的蹂躏。客户遗留系统糅杂了JAXB,CXF诸多Java EE和web service“高端”特性,调试很难,好不容易找到负责(反)序列化的XmlAdapter实现,才看到遗留系统工程师编写的奇怪正则表达式,过滤了本不该过滤的字符串,导致web service接收端接收数据不完整。

一边pair,一边感叹,Java的企业应用现在如此复杂,Java技术发展已经背离了最初解决问题的初衷。Java出路在哪里呢?

采访:Maven贡献者、《Maven实战》作者许晓斌

1. 首先,请您介绍你自己,从什么时候开始你从事Maven的推广工作,以及你现在在做些有什么有趣的事情呢?

我从07年开始接触Maven,慢慢学习并在实际项目中推广使用,然后慢慢喜欢上了这个技术。1年之后我开始编写Maven中文博客并翻译《Maven权威指南》,并且维护了一个Google Group,我想这些事情对于Maven在国内的推广起到了一定的作用。也正是由于这些工作的关系,我有机会熟悉Maven的方方面面,并加入了Sonatype —— Maven之父Jason Van Zyl创建的公司。

目前我主要做两方面的工作,其一是维护Maven中央库Sonatype OSS仓库托管服务,该服务为开源项目提供免费的Maven仓库并帮助他们同步自己的构件至中央仓库。目前有超过600个项目在使用该服务,包括知名的JUnit、TestNG、Ehcache等等。除此之外我也参与Nexus的开发,开源的、商业的都有。

 

2. Maven 3刚刚推出不久,据说这个新版本在性能上有很大的提高。相比较以前的版本,你觉得最大的变化、最重要的新特性是哪些呢?

Maven 3发布的第一时间我就写了篇博客进行介绍,其实从性能上来说,抛开并行构建不谈,用户不会感受到很明显的提高,这是因为Maven本质上是将构建工作给其他工具来做的,例如编译用javac,测试用JUnit,因此给Maven的改进余地不多。使用Guice代替Plexus从一定程度上能改进性能,但不是很明显。我个人认为Maven 3最重要的改进是清理,包括代码清理和不良特性的清理,例如在Maven 3中,你使用插件不声明版本不会引入快照,而Maven 2就因为快照插件的问题被很多人诟病。此外,Maven 3的并行构建特性也让人眼前一亮,只要模块组织合理,多个模块能够得以同时构建,充分利用多核资源。

 

3. 在今年2月份,InfoQ有篇新闻是关于Maven 3即将采用Guice来作为新的DI层,请问这在Maven 3里面实现的如何?这对那些采用Maven的开发者来说,有着什么样的好处呢?

采用Guice作为DI容器最大好处在于标准化,Maven之前使用的Plexus历史也很久,但发展得很差,文档也很缺乏,转到Guice后,由于大家更熟悉,就可以吸引更多的贡献者。Maven团队也不再需要花时间去维护,有了问题,可以得到Guice社区的帮助。

Maven 3在采用Guice的同时还必须支持Plexus风格DI标注或XML配置,以兼容现有的数以百计的Maven插件。为此Maven团队基于Guice 2.0所支持的自定义注入器,开发了一个中间层模块,该模块包含一个匹配器来识别你的标注配置是Plexus风格还是Guice支持的JSR300风格,如果是Plexus风格则再应用额外的集成逻辑。实现的细节在这两篇博客中有介绍:The Guice/Plexus Bridge and Custom Bean InjectionCreate a Guice Bean Extension Layer

 

4. 在InfoQ的这篇关于Maven 3的新闻里,出现了很多开发者对于Maven的评价,可谓毁誉参半。作为Maven的推广者,你怎么来评价这样争论的存在呢?

关于Maven的争论从来没有休止过,类似的争论还可以找到很多。但有目共睹的是,越来越多的开源项目在使用Maven作为他们的构建工具。我想那些人反对Maven主要是以下三个个因素:

  1. Maven提倡约定优于配置,例如目录结构的约定,很多习惯高度自定义的用户受不了,于是当然就排斥。其实约定有很多好处,例如当你从一个项目转到另外一个项目的时候,你不需要学习另外一套结构。
  2. Maven的学习曲线陡峭,一些人花了时间去学习,但没体验到快乐就学不下去了,因此完善的文档很重要。
  3. 与IDE的集成,这方面m2eclipse的质量确实比不过其他集成如Ant,问题也有一些,但这些都在改善。IDEA对Maven的集成就相当不错。

争论还会继续,只要反对者能提出合理的需求,那就是Maven改进的空间。

 

5. 谈一谈你编写的即将出版的那本新书吧,名字叫《Maven实战》?为什么我需要这样一本新的Maven书呢?

由于种种原因,我翻译的《Maven权威指南》没有能够在国内出版,这是一个遗憾,很多人告诉我他们自己打印了那本书看,这让我很感动。我很希望国内能有一本印刷上市的关于Maven的书,这是我写《Maven实战》的最原始动机,后来我发现借助这个机会,我能将书写得更接近国人,包括语言的组织,以及内容的安排。例如在《Maven实战》一书中,我介绍了使用Maven进行自动化部署,以及结合Hudson进行持续集成等内容,这些内容都是我实际体会到大家迫切需要的。前面说过,Maven的学习曲线比较陡峭,这是他的天生问题,弥补的办法就是提供完善的文档,对于初学者来说,这样一本书无疑能帮他们少走弯路,节省时间。

 

6. 请您给那些不甚熟悉Maven的开发者们一点建议,怎样才能又快又好的掌握Maven呢?

首先不要排斥它,很多人因为Maven有很多约定而受不了,其实Maven这样做能帮助你更规范的管理项目。其次,如果不要太依赖于IDE,IDE能做很多事,但在自动化构建以及持续集成这些方面他不擅长,试着多用用命令行,熟悉Maven命令的同时,也能更深刻地体会一些Maven的概念。还有要耐下心来读读文档,你买我的书看当然最好,想省点可以看《Maven权威指南》。最后就是实践啦,可以看看开源项目怎么用Maven的,然后在实际的项目中尝试,并使用Nexus建立自己的Maven私服。

利用tortoiseSVN在两个版本库间merge code

需求总是奇怪的,但好在有这么一个还算顺手的工具。

我有一份code base的两个不同版本库,这两个版本库所在的server是不一样的,然后对应本地有两个不同的Working Copy。我需要把一个版本库里面做的部分变化,merge到另外一个版本库。一开始想过用SVN命令行diff,但似乎那是服务于同一个版本库的不同branch的,也就是要host在一个server上的。

幸好在小乌龟里面发现了Merge revisions to…这个功能,具体做法是:

  1. show log版本库A
  2. 选择需要提取出change的revisions,可以多选
  3. 然后右键,选择merge revisions to…
  4. 选择版本库B所在的WC
  5. 小乌龟开始替你干活,能自动Merge的会自动Merge,不能的会提示conflict

小乌龟干活有两个问题:

  1. 提示你有conflict时,你可以看到变化的对比,但有时并不真有conflict,这时可以选择使用全部覆盖或者忽略覆盖。
  2. 如果真的有conflict,注意了,即使在edit conflict时resolve conflict,目标文件也还是有问题,并未真的把conflict resolve掉,一试便知。这应该是小乌龟的bug,我用的是1.6.10。这时正确的做法是,发现的确有红色的conflict,选择resolve later,待这一轮Merge之后,逐个选择文件把conflict resolve掉。