- 浏览: 139858 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
邪恶八进制:
译的还不错,其实简单说、JPA三种继承映射体系如下:1.参照父 ...
[译文]JPA的实施模式:映射继承的层次体系 -
mondayw:
卓越上有售,地址:http://www.amazon.cn/m ...
翻译的第一本书出版了 -
黑暗浪子:
哪里有订?
翻译的第一本书出版了 -
mondayw:
不好意思,没有测试过,我以为这只是示范性的代码而已。
[译文]Java EE 6中的依赖注入——第1部分(二) -
jimmy.shine:
不知道你有无测试过这范例程序,在JBoss 6.0M2中,程序 ...
[译文]Java EE 6中的依赖注入——第1部分(二)
原文:The Developer Insight Series, Part 1: Write Dumb Code -- Advice From Four Leading Java Developers
作者:Janice J. Heiss
出处:http://java.sun.com/developer/technicalArticles/Interviews/devinsight_1/
Cay Horstmann:模式并非魔法药水
关于Cay Horstmann:
荣获Java Champion称号的Cay Horstmann在德国北部长大,并入读波罗的海边上的海港城市Kiel的Christian-Albrechts-Universität大学,拥有Syracuse大学计算机科学的M.S.学位和Michigan大学的数学方面的Ph.D.学位,他现在是California的San Jose州立大学的计算机科学教授。他曾是一家新兴的网络公司的VP和CTO,在此之前,他拥有一家很成功的销售编辑科技文档的DOS程序的公司。Horstmann利用空余时间提供Internet编程方面的咨询。
我同意Brian Goetz的观点。就我这些年的经验来说,除非已做了配置,否则你不会优化代码,我们更发愁的是数据的缓存而不是重新计算他们、消除层次等这样的事情,更多时候,这仅使性能稍有不同,但却在调试方面引入了颇为痛疼的问题。
我看到你有问Heinz Kabutz相同的问题,他说:“我通常都鼓励软件开发公司在设计模式方面培训他们的所有的开发者,包括从最初级的人员到最聪明的架构师。”我对这一说法有些不太能接受。我同意模式应该是每个人接受培训的一部分,但我有太多的初级程序员在他们的代码上放上了过多的模式,以期改善代码。模式并非魔法药水,且需要相当多的经验而不是一般情况下就能做到明智地使用他们。
以Java I/O库为例,该库就深深浸染了装饰模式(decorator pattern)的价值观念,例如,BufferedReader是一个装饰器,从文件中获得缓冲读,你这样做:
Reader reader = new BufferedReader(new FileReader("foo.txt"));
如果你还想往前看看(lookahead)的话该怎样呢?现在你需要在装饰器链中插入一个PushbackReader。
真是痛苦!我倒宁愿更多一点可用性而少一点模式教条,在C++中,缓冲以及往前查看是每个文件流的组成部分,在实践中这一方面提供了更多的便利性。
查阅对Cay Horstmann所做的完整访谈。
Kirk Pepperdine:傻瓜代码的可读性更强
关于Kirk Pepperdine:
荣获Java Champion称号的Kirk Pepperdine是javaperformancetuning.com的主要贡献者,该网站被广泛当作Java性能调优信息来源的首要网站,Kirk是Ant Developer’s Handbook一书的合著者,自开始编程生涯起,他就一直积极地参与应用性能方面的工作,并对各种语言编写的应用进行调优,这些语言包括:Cray汇编语言、C、Smalltalk等,以及自1996年以来的Java技术;他还致力于为分布式应用构建中间件。
他曾在加拿大国防部做过Cray超级计算机方面的工作,以及做过Florida Power & Light的顾问和GemStone Systems的高级顾问,他目前是一个独立顾问,以及TheServerSide.com的编辑。
我询问Pepperdine如何看待Brian Goetz的观点。
实际上这里有两个问题:首先,编写傻瓜式代码如何有助于性能?其次,编写结构性好的代码如何有助于性能?我先来回答“傻瓜代码”的问题。
虽然我们编写的代码运行在机器上,但代码的主要消费者是人,傻瓜代码往往更具可读性,因此更易于理解。如果我们能消除某些缺陷的话,我们就会更好地避免一些愚蠢的、可能会被聪明的代码隐藏起来的错误。
HotSpot、IBM的MMI以及JIT都是通过动态配置来进行代码优化工作的工具,复杂的代码往往会使这些工具陷于混乱,结果他们要么提供不太理想的优化,要么完全没有进行优化。
我们可以通过一个编写良好的微性能基准来了解这一点。大部分编写良好的微基准代码都会导致JIT的困惑,以致JIT不能把我们的代码转换成不再丈量我们感兴趣的效果的东西,虽然微基准有可能是一种非常态的情况,但是同样的这些情况有可能会发生在实际应用的代码中。
另一个编写傻瓜代码的理由是,大部分的复杂性出于每个人都认为是需要的那些优化。在许多情况下,这些优化是不成熟的,虽然我非常赞成做性能计划,但我坚决反对不成熟的优化,计划何时只是一个计划?何时还不算成熟?我猜这有点类似于是艺术与色 情之间的区别:你看到时自然就会知道。
这就带来了我们的第二个问题:结构良好的代码如何有助于性能?大部分的性能问题只能通过添加或者修改应用中的代码来解决,我发现,如果代码结构良好且是低耦合的,如果代码是内聚的,且代码用到了代理的话,那么在开始修改代码的时候就能够避免这种打地鼠(whack-a-mole)问题。
这一问题也被称作是霰弹式重构(shotgun refactoring)——如果在应用的某一部分中做了修改的话,应用中看起来很随机的其他部分就会遭到破坏,但当我修补了某个破损之处时,我又创建了一系列新的破坏,如此等等。
那么我们怎样才能避免此种情况呢?首先,遵循DRY——不要重复自己——这一原则,让我们来看一下集合的一个例子,传统上,我们在Java中会通过创建一个迭代器来管理一个对集合的查询:
....
Iterator iter = customers.iterator();
while (iter.hasNext()) {
Customer c = (Customer)iter.next();
doStuff( c);
}
....
这儿有一个陷阱:如果应用的另一个部分需要用到doStuff()的话,那么就有可能或是通过剪切复制或是通过简单地重写来重复这部分代码,无论使用哪种方式,你都违反了DRY原则,这会引发几种后果。你还忽略了另一个设计原则:委托,不承担(责任)。
在不做委托的情况下,你会冒着违反DRY原则的风险,且你一定会违反信息隐藏原则。从这方面来考虑一下:通过调用get方法,你不仅违反了封装,而且把你的类和被调用者紧密地耦合到了一起。当你因导出状态而违反了封装时,你就被迫还要导出需要用来管理状态的应用逻辑,结果又违反了DRY原则,因此你可以看到,就从多个不同的角度来说,这种做法都是错的。
这是一个很重要的性能方面的技巧:假定正在使用的数据结构是不太理想的,并且假设你意识到需要做出修改,如果你使用迭代器或者别的什么来导出状态和行为的话,你就已经造出了一个打地鼠问题。让我们来看看当我们采用委托时情况会怎样:
public class Customers {
Hashmap customers = new Hashmap();
public void putCustomer( Customer customer) {
allCustomers.put( customer.getId(), customer);
}
public Customer getCustomer( String id) {
allCustomers.get( id);
}
public Customers getCustomers( String pattern) {
return doSomeStufftoGetACollectionOfCustomer( pattern);
}
这里的代码量会多些,不过在一个较小的人为例子中说明问题时这是经常会发生的情况,你只会见到大的代码库的好处,他们提供的例子当然也是会吓坏人的。
除此之外,我们还有一个用来封装预期集合的类,新类在语义上要适合我们的领域,有多少问题领域是包含了Hashmap这个词,以及有多少领域是包含了Customers了的?因此我们已经对词汇表做了修正。
接下来,我们为查询提供一个落脚点,至少是那些我们已预期到的查询。如果我们取得其他的查询模式的话,那么就有可能加入一个有不同键值的二级集合,可把它看成是在数据库表上添加另一个索引。
这一做法的美妙之处在于,因为我已经封装并委派了调用,于是我可以自由地做出我的客户可能知道也可能不知道的修改而不受限制,换言之,不用打地鼠。此外,每个客户都会感受到优化带来的性能好处,因此这是一个多赢的做法。
我有意地不使用泛型,使用这种开发模式的话,我就不需要编译时的集合类型检查,因为类API提供了所需的所有安全性。我一直认为,在API中暴露原始的集合是个错误,且因为我从来都不觉得泛型的那些主要的使用场景是合理的,不过这是另一个话题了。
那么,如果有人需要我们并未提供的查询话,该怎么办呢?闭包看起来像是一个好的解决办法,但需要非常小心地实现他们,否则的话我们可能会把自己“闭包”到某个打地鼠问题中了。
闭包应该只访问那些被归类为非基本的元素,在这其中我指的是那些无需了解底层结构就能够工作的元素,这是相对于原始方法或是需要了解类的底层数据结构的方法而言的,关键之处是要隐藏我们领域之外的事务的实现细节。
总之,性能调优通常要求涉及代码,这与重构并没有太多不同。敏捷开发那帮人提出的所有论点——松散耦合、简单代码、遵循好的设计模式、制定好的单元测试、自动构建等等——同样适用于性能调优。
查阅对Kirk Pepperdine所做的完整访谈。
其他参考
Heinz Kabutz的访谈和Java Specialists’ Newsletter
与Google的Joshua Bloch谈更加有效的Java
讨论
你有关于如何编写更好的代码的建议吗?特别是,你会不同意编写傻瓜代码这一通常建议吗?我们欢迎所有的意见,且特别鼓励不同意本文观点的开发者发表你的不同见解。欢迎你加入到我们的社区中来,请保证评论的礼貌性和相关性,你可以选择提供电子邮件地址以获得对你的答复的通知——你的个人信息不会做其他用途。在提交评论时,你要同意这些使用条款。
发表评论
-
[译文]技巧:防范代码的终结器漏洞
2011-08-02 11:11 742你的Java代码有可能会因终结操作带来的漏洞而易受到攻击,了解 ... -
[译文] 一种减少多线程Java应用的工作队列中的竞争和开销的方法
2011-06-21 10:08 986许多的服务器应用,比如说Web服务器、应用服务器、数据库服务器 ... -
[译文]Java SE 7带来更好的资源管理:不仅仅是语法糖
2011-06-18 19:55 775本文介绍了Java Platform, Standard Ed ... -
[译文]双重检查锁定和单件模式
2011-05-06 11:50 840所有的编程语言都会有分享一些它们的惯用技法,其中的 ... -
RJC501:为周转期付出的代价有多大?
2011-04-18 16:43 809通过重载Java类(Reloading Java ... -
RJC401:HotSwap和JRebel——幕后的故事
2011-04-11 16:31 1023在本文中,我们会回顾类在没有动态类加载器情况下的重载方式;我们 ... -
RJC301:Web开发——Tomcat、GlassFish、OSGi、Tapestry等服务器和框架中的Classloader
2011-04-04 15:26 948在本文中,我们会回顾真实的服务器、容器和框架是如何使用动态的类 ... -
RJC201:ClassLoader的泄漏是如何发生的?
2011-03-28 19:58 866你如果使用Java编程已有一段时间的话,那么你就会知道内存泄漏 ... -
jQuery的.bind()、.live()和.delegate()之间的区别
2011-03-19 22:01 830.bind()、.live()和.delegate()之间的 ... -
示例:JavaScript中的后续传递风格
2011-03-19 21:57 830本文介绍了CPS所扮演的两种角色——作为JavaScript中 ... -
[译文]开发者见解系列,第3部分:编写代码的步骤(下)
2010-07-27 22:11 878原文:The Developer Insight ... -
[译文]开发者见解系列,第3部分:编写代码的步骤(上)
2010-07-27 22:05 1116原文:The Developer Insight Series ... -
[译文]开发者见解系列,第2部分:谈谈编码(下)
2010-07-14 22:31 854原文:The Developer Insight Series ... -
[译文]开发者见解系列,第2部分:谈谈编码(上)
2010-07-14 22:26 1077原文:The Developer Insight Series ... -
[译文]开发者见解系列,第1部分:编写傻瓜代码——来自四位首席Java开发者的建议(上)
2010-06-28 12:25 1412原文:The Developer Insight Series ... -
[译文] Java EE 6中的DataSource资源的定义
2010-05-20 12:29 1931原文:DataSource Resource Definiti ... -
[译文] Java Applets和ASP.net——你可让他们玩到一起吗?
2010-05-13 18:01 1688原文:Java Applets, ASP.net - Can ... -
[译文]使用Java编写你的第一个Google Wave机器人(下)
2010-01-25 21:03 1060原文:Write Your First Google Wave ... -
[译文]使用Java编写你的第一个Google Wave机器人(上)
2010-01-25 21:02 1323原文:Write Your First Google Wave ... -
[译文]一些Java并发技巧
2009-12-20 18:25 1017原文:Some Java Concurrency Tips ...
相关推荐
( Nutch,第1部分:爬行(译文) ( Nutch,第1部分:爬行(译文)
Nutch,第2部分:搜索(译文) Nutch,第2部分:搜索(译文)
译文:Fork and Join: Java Can Excel at Painless Parallel Programming Too!(Fork and Join Java也可以轻松地编写并发程序)
1) 静态代码分析:使用静态代码分析工具对代码进行分析,发现潜在的代码缺陷和安全漏洞。 2.)单元测试:编写单元测试用例并执行,以验证代码的正确性和稳定性。 3.)集成测试:将各个模块集成到一起进行测试,以...
如果你是wxPython初学者,你一定会想从第一部分开始。第一章至第三章帮助您夯实 wxPython相关概念的坚实基础。第六章则对构建合理大小程序的步骤进行了完整回顾。第五章介绍如何让代码更易于管理的方法,第四章提供...
学习SDN控制器之一floodlight的中文文档。
深度学习三维重建 PVSNet——2020 (原文+译文) 深度学习三维重建 PVSNet——2020 (原文+译文) 深度学习三维重建 PVSNet——2020 (原文+译文) 深度学习三维重建 PVSNet——2020 (原文+译文) 深度学习三维重建...
Clojure是一个JVM的动态函数式语言,最近发布了1.0版本,版本中Clojure提供了一个健壮的代码。Clojure是一套发展快速的新的编程语言,特别是,它为多核计算做了新的解决方案。在今后的软件设计中无论使用Clojure语言...
企业市场营销外文文献——中文译文.doc
JSP(JavaServer Pages)是一种基于Java的脚本技术。是由Sun Microsystems公司倡导、许多公司参与一起建立的一种动态网页技术标准。JSP技术有点类似ASP技术,它是在传统的网页HTML文件(*.htm,*.html)中插入Java程序...
译文: 开发者指南> 前言 在电脑软件的历史上,很少有一种技术能够得到开发者和业界如此强烈的正面响应。全球已经有数百万的开发者下载了Microsoft的.NET软件开发工具包,已经出现了很多有关.NET平台及其相关技术和...
当代研究生英语(吴输敬)——译文,研究生英语课文翻译
浅议传统出版社研发APP的意义和困局——从上海译文出版社“译文的书”APP说起.pdf
本资源原文为java-for-Anylogic-user英文版,即面向Anylogic用户的Java开发,本人纯手工翻译,讲述以拖放方式以外的编程思路,对于建立复杂系统有很大帮助。这是一个信息论,可以在模型中进行数据操作以及智能体的...
cascade-MVSNet——CVPR-202(源码、原文、译文) cascade-MVSNet——CVPR-202(源码、原文、译文) cascade-MVSNet——CVPR-202(源码、原文、译文) cascade-MVSNet——CVPR-202(源码、原文、译文) cascade-...
最好还是阅读原文,因为译文毕竟经过译者的再加工,受限于译者的英语水平和国语水平,或许原作者的意思不能完全理解,理解的部分书写出来也可能辞不达意。 重要说明 原文中 rule 指作者行文中的一些条目,而 ruleset...
计算机类专业毕业设计外文翻译的原文及译文。已经排版,下载即用。
2918.F密钥分散管理系统——密钥确认算法实现外文资料翻译--译文.doc
深度学习三维重建 CVP-MVSNet——CVPR-2020(源码、原文、译文) 深度学习三维重建 CVP-MVSNet——CVPR-2020(源码、原文、译文) 深度学习三维重建 CVP-MVSNet——CVPR-2020(源码、原文、译文) 深度学习三维重建 ...