- 浏览: 144230 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
邪恶八进制:
译的还不错,其实简单说、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 2: Code Talk
作者:Janice J. Heiss
出处:http://java.sun.com/developer/technicalArticles/Interviews/devinsight_2/
Victoria Livschitz:编程语言不仅仅是面向对象那么简单
关于Victoria Livschitz:
Victoria Livschitz是Grid Dynamics的创始人和CEO,在过去超过15年的时间中,她曾是一位多个企业的创建者、革新者以及Java技术和网格计算方面的行业权威专家。
在2006年创建Grid Dynamics之前,她在Sun Microsystems作为主要的技术专家工作了10年,担任了多个高级职位,其中包括一些大客户的首席架构师。在Sun任职期间,她还进行了下一代计算机语言的原创性研究,并设计了一种新的编程语言Metaphors。1994年作为一个高性能计算工程师她在Ford开始了自己的职业生涯。
Livschitz是几个有名的工程优秀奖的获得者,其中包括Ford的Chairman Award和Sun的系统工程师年度奖,她在网格技术方面拥有多项专利。
她拥有Case Western Reserve University大学的计算机科学学士学位,她还曾就读于Vilnius University大学、Kharkov State University大学、 Purdue University大学和Stanford niversity大学,主修应用数学、电子工程和计算科学等。
Jaron Lanier辩称,我们不可能编写有大量代码的大程序却不会创建出许多的bug,他的结论是这表明有些事情从根本上就是错误的。
我完全同意Jaron的论点,软件的规模和它的质量之间的相关性是压倒性的并且非常具有启发性,我认为他的看法提出了几个问题:为什么大的程序会如此多bug?且不仅是bug多,且多到了超出可挽救的程度。是否存在一种内在的复杂因素使得bug在数目、严重性以及如何难于被诊断方面成倍地增长?如果是这样的话,我们如何来界定复杂性并进行处理?
Jaron强调,用模式识别来代替在目前的编程中占统治地位的刚性且容易出错的二进制“匹配/不匹配”构造,这引起了我的兴趣,特别是因为我一直认为,模糊逻辑原则应该被更广泛地应用在软件工程中,不过,我对Jaron的问题的答案的寻求看起来似乎是产生了与他自己的回答正交的想法。
我可以确定两种合理的创建复杂程序但又不会带来太多bug的方式,如同在医学方面,既有预防也有治愈,涉及预防和治愈的目标和手段这两者是如此不同,因此应该对他们进行各自的考虑。
预防措施努力确保bug不可能会出现在首个地方,在过去的20年中,这方面已经取得了很多进展;诸如允许编译时指定安全检查的强类型化、自动管理内存的垃圾收集器,以及在可追溯和可恢复事件中捕捉和传播错误的异常机制等这些编程实践确实是使得编程更加的安全。
Java语言当然是有着一流系统安全性品质的现代通用编程语言的代表,相对于它的前任C++来说这是一个巨大的进步,关于可视开发工具方面也有许多值得一提,他们简化并自动化了编程的比较单调和比较容易出错的方面。
尽管如此,这些技术上的进步仍不足以处理许多类型的bug,你看,一个“bug”通常就是程序不符合要求的行为举止的识别标志,这种“不合需求性”可能确实是由机械性问题引起的,在这种机械性问题中,代码做了有别于它原打算要做的事情,但更多的时候,代码当时做的正是程序员期望的事,结果(最后)却被证明实际上是糟糕的主意。
前者是一种编程方面的bug,而后者则是设计上的bug,或者在某些特别致命的情况下,是架构方面的bug。与Microsoft产品相关的那些不断出现的安全相关的问题是要归因于其产品的基础平台架构。Java技术则相反,其在病毒方面有着特殊的免疫力,这是因为它的沙箱架构的缘故。
我不认为在软件工程方面的未来进步会防止开发者犯下导致设计上的bug的错误,随着时间的推移,任何成功的软件都要进化以解决新的问题,一段在早期版本中正确运行的代码突然证实是有缺陷的——或者是有bug的,这很正常!编程领域的实际情况已经发生改变,因此程序也必须要改变,bug只不过是新发现的偏差的表现而已,它必须是预期会发生的,千真万确!从这一有利点来说,并不是bug的预防,而是修复——优雅地消灭他们的能力——才是最重要的。
至于修复,我不认为近期会有技术上的突破。多态性和继承帮助开发者编写新的类而无需影响到程序的其他部分,然而,大部分bug的修正都要求某种程度的重构,而这总是危险且难以预料的。
作为软件bug的主要起因的复杂性的概念是怎样的?你有一些关于如何降低复杂性的具体想法吗?
嗯,我认为有两种主要的手段。其一是来自开发者观点的直观的编程经验,另一种是把整体分解成较小的单元的能力,以及把独个的单元聚合成一个整体的能力,让我先从编程经验说起。
当我们能够在远低于全神贯注、全力以赴、艰苦思考的意识水平之下,凭直觉运作时,事情看起来是很简单的,因此,复杂的对立面——以及对付它的最好手段——是直觉。软件工程应该源于直观的编程经验,能够轻松地应付复杂的程序的编程者并不认为程序有多复杂,这要感谢我们的感觉和认知能力工作的方式,森林是一个复杂的生态系统,但对于一般的徒步旅行者来说,树林看上去并不复杂。
你认为现代的编程语言,特别是Java语言能在多大程度上帮助开发者隐藏掉复杂性?
不幸的是,我认为现代计算机科学和软件工程未能在这方面取得重大进展,所有主流的编程语言的语法都相当深奥,能够轻松应付纯粹抽象的语法的数学家需花费多年紧张学习以掌握某些特定的技能,但编程者不像数学家,编程者被教导成非按照绝对的证据而是按照工作的隐喻来进行思考。为了理解系统如何工作,编程者不是创建出一个数学方程系统,而是找出她或者她作为一个人所“感受到”的现实生活所象征的正确的东西。编程者是一些“普通”的家伙——他们不得不是这样,因为编程是有上百万人从事的职业,其中的许多人没有大学学位。深奥难解的软件的规模难以扩展到百万的级别,在编程人员方面不行,在代码的行数方面也不行。
现在回到你的问题上来,长期以来,编程者一直在熟练地使用着子例程、函数、数据结构、循环以及其他的一些完全抽象的构造,这些构造忽略了——不,是失去了这一感觉——人的直觉。后来面向对象(OO)编程开始启用了,开发者第一次能够创建效仿现实世界的元素的编程结构——在名称、特征及与其他对象的关系方面。即使是一个非编程者也能够在基本层面上理解“银行账户”对象这一概念,直观的理解事物之间的意义及关系的能力是人所共识的杀手锏,如果在这场反对复杂性的战争中有制胜的法宝的话。
面向对象编程允许开发者创建的行业软件远比过程化编程允许创建的复杂得多,不过,我们看起来好像已经到达了OO的失效点,没有人能够毫无费劲地与有着成千上万的类的系统打交道,因此,很不幸地,面向对象编程有着一个基本缺陷,具有讽刺意味的是,这却是与它的主要优势相关的。
在面向对象的系统中,“对象”是唯一的基本抽象,某个领域总是被简化成一组预定义对象类的集合,其中的一些是另外一些的结构性超集。这种模式的简单性即既是祝福也是诅咒,爱因斯坦曾指出,解释应该尽可能地简单,但不能过于简单,这是非常微妙的一个观点,却常被忽视,通过对象集合来解释世界正是太简单了!这个世界比我们能够用面向对象语法来表达的丰富得多了。
考虑一下人们普遍用来理解和描述所有系统的几个常见的概念——这些概念并没有与对象这一模具相吻合。“之前/之后”范式,同样的还有“前因/后果”范式,以及“系统状态”的概念等都是这其中最明显的例子。事实上,“煮咖啡”、“组装车”或者“漫游者登陆火星”等过程并不能被分解成简单的对象,是的,他们是通过OO语言来这样做了,但这是人为的且是违反直觉的。例程本身的先后顺序——什么在其之前,其处于哪种条件下,该条件基于什么样的因果关系——在OO中只不过是没有意义的表示,因为OO没有先后顺序、状态或是前因的概念。
在现实世界和编程中过程都是非常普遍的,多年来一些复杂精致的机制已被设计出来处理事务、工作流、流程编排、线程、协议以及其他固有其“过程式”的概念。这些机制当他们企图弥补OO编程中固有的不随时间改变的缺陷时就会引发复杂性,相反,通过允许过程特有的构造,比如“之前/之后”、“前因/后果”,以及也许还有“系统状态”等作为语言的核心部分,这个问题应该就能得到解决。
我设想的编程语言是比OO更为丰富的一个级别,其应该基于不多的几条基础概念,对于任何成年人来说都是直观明显的,并且是绑定到众所周知的一些象征性的东西上的,比如对象、条件以及过程等。我希望保留面向对象系统的许多使得系统很安全且便利的功能,诸如抽象类型化、多态、封装等等。到目前为止,这项工作的前景不错。
可参阅对Victoria Livschitz所作的访谈:编程的下一步行动和构想一种新的语言。
Brian Harry:在修正错误时,查明平台的较早版本
关于Brian Harry:
来自Iowa的开发者Brian Harry,在java.net上也被称作是“leouser”,因其在Java SE 6的错误修正方面所作的贡献而为人所知,其修正的bug数目很可观,总计达到了几百个,这为他赢取了2006年度的Duke’s Choice优秀平台贡献奖。他的方法很简单,就是扫描Sun公开可用的bug数据库来获取那些令人好奇的bug,主要是Swing用户界面(UI)代码中的那些,把他们打印出来,并把这些bug报告放在他的计算机旁边的架子上,然后逐个地修正他们,通过标准JDK社区的捐献流程来提交他们。他的工作是Sun认证的Java开发者(Sun Certified Java Developer,SCJD)以及独立的顾问。
修复Bug是了解代码如何工作的一种很棒的方式,阅读代码是好事,但使用它来工作更好,纵然没有找出解决方案,但通过代码学习你会成为一个更加有实力的开发者。
试想一下你面对着那些具有某种意义的API的时刻,但是你难以让它运作起来,如果你越过Javadoc的范围而进入源代码之中的话,则成功的机会就增加了。比如,我曾帮助java.net上的某人找到了一个关于“JInternalFrame不能与Heavyweight放在一起使用”这一问题的适合的解决方法。Sun的文章和教程通常会说你不能这样做,但因为我对代码很熟悉,所以我能够帮助到开发者,当然,我不是百分之百地满意该解决方案——当改变大小时frame会闪烁——但有东西可以用总比什么都没有要好。
有什么贴士是可以和我们共享的吗?
首先,始终要拿到错误报告所附带测试,bug数据库的状态是各种事态的混合,有时可见到有测试,有时却没有,如果你失去了耐心,因为测试不可见而决定基于报告来进行修复的话,那么你有可能是在浪费时间来尝试重现问题。在某些情况下,在我重新审查了测试之后,就可以明显看出报告对问题做了错误的描述。
接下来,问问自己这是否是个真的bug,在某些情况下,报告者从Java论坛寻求帮助的话会做得更好一些;此外,有时测试用例是容易出错的。一旦你确定了这是一个bug的话,你就可深入研究它,获取成效的最好方法是熟悉源代码。
还有,当找到有助于澄清问题的方法时写下我的想法,并文档化修改历史以备我需要时重视过程。把你的理解过程记录放在补丁包中有助于与任何评估该补丁包的人沟通。
并可考虑写下多种解决方案,你的方法可能是行得通的,但有可能不是最优的。基于类似的理由,准备再三重复你的方案,这可能看上去是一个好的方案,但意想不到的问题可能会让你犯错误。
至于编写单元测试,考虑补丁代码与之交互的部分,这可能需要浏览大量的代码,但对于测试补丁的各个不同路径来说是必要的。
是什么造就了一个好的bug修复者?
做一个研究者,并在事情最初犯错时没有放弃。这儿有一个例子,我曾被这一串字节码搞得狼狈不堪:
1 goto 8
2 set i to 100
3 set i to 100 --> start protected block
4 do stuff with i
5 return --> end protected block
6 use i to print out error message --> start exception handler
7 return
8 jump to 2 or 3
这段代码似乎很简单,设置某个局部变量的值为整数100,但校验器的检查失败了,因为i变量有可能没有被初始化,这种情形怎么会可能发生呢?有可能是在异常处理程序中有一个内存不足的错误被抛出,从而导致了该问题。查看一下VM(virtual machine)规范,数据流分析器一节中说到,其必须“确保指定的局部变量包含有正确类型的值。”我就想:“嗯,这似乎和这儿正在发生的事情对应上了。”
在我开始研究字节码之前,我从没有真正地理解过校验器为Java开发者做了多少事情,如果你是新接触它的话,那么你很快就知道它是一个多么严格的监工,有那么一段时间我都有可能被它逼疯了,不过我还是能够忍受住这一VM规范,并找出了问题合理化的一面以及后来的有效的重构方法。
同样,如果你正在进行Java代码的修复的话,不要只是检查平台的当前版本,我通常都会在4.0、5.0以及6上测试bug的测试用例,这样就可以查出问题何时开始而在何时终止,看看你是否能够找出为什么问题会开始发生。我的“未初始化”问题的根源在于校验器规范,JDK的一些bug会源于某些过去的版本,纵观全局则有可能会获得提供某些与导致了错误的设计因素相关的线索。
可参阅对Brian Harry作的完整访谈。
其他参考
开发者见解系列,第1部分:编写傻瓜式代码——来自四位首席开发者的建议
Joshua Bloch:更有效的Java和Java解惑两个访谈
Masood Mortazavi:访谈第1部分和第2部分,以及博客On the Margins
Jaron Lanier:访谈第1部分和第2部分,主页以及关于Phenotropic计算的思考
Vicotria Livschitz:编程的下一步行动和构想一种新的语言两个访谈
Brian Harry:访谈
评论
你有关于如何编写更好的代码的建议吗?我们欢迎所有的意见,且特别鼓励不同意本文观点的开发者发表你的不同见解。欢迎你加入到我们的社区中来,请保证评论的礼貌性和相关性,你可以选择提供电子邮件地址以获得对你的答复的通知——你的个人信息不会做其他用途。在提交评论时,你要同意这些使用条款。
发表评论
-
[译文]技巧:防范代码的终结器漏洞
2011-08-02 11:11 769你的Java代码有可能会因终结操作带来的漏洞而易受到攻击,了解 ... -
[译文] 一种减少多线程Java应用的工作队列中的竞争和开销的方法
2011-06-21 10:08 1021许多的服务器应用,比如说Web服务器、应用服务器、数据库服务器 ... -
[译文]Java SE 7带来更好的资源管理:不仅仅是语法糖
2011-06-18 19:55 796本文介绍了Java Platform, Standard Ed ... -
[译文]双重检查锁定和单件模式
2011-05-06 11:50 871所有的编程语言都会有分享一些它们的惯用技法,其中的 ... -
RJC501:为周转期付出的代价有多大?
2011-04-18 16:43 839通过重载Java类(Reloading Java ... -
RJC401:HotSwap和JRebel——幕后的故事
2011-04-11 16:31 1047在本文中,我们会回顾类在没有动态类加载器情况下的重载方式;我们 ... -
RJC301:Web开发——Tomcat、GlassFish、OSGi、Tapestry等服务器和框架中的Classloader
2011-04-04 15:26 983在本文中,我们会回顾真实的服务器、容器和框架是如何使用动态的类 ... -
RJC201:ClassLoader的泄漏是如何发生的?
2011-03-28 19:58 893你如果使用Java编程已有一段时间的话,那么你就会知道内存泄漏 ... -
jQuery的.bind()、.live()和.delegate()之间的区别
2011-03-19 22:01 859.bind()、.live()和.delegate()之间的 ... -
示例:JavaScript中的后续传递风格
2011-03-19 21:57 862本文介绍了CPS所扮演的两种角色——作为JavaScript中 ... -
[译文]开发者见解系列,第3部分:编写代码的步骤(下)
2010-07-27 22:11 915原文:The Developer Insight ... -
[译文]开发者见解系列,第3部分:编写代码的步骤(上)
2010-07-27 22:05 1144原文:The Developer Insight Series ... -
[译文]开发者见解系列,第2部分:谈谈编码(上)
2010-07-14 22:26 1113原文:The Developer Insight Series ... -
[译文]开发者见解系列,第1部分:编写傻瓜代码——来自四位首席Java开发者的建议(下)
2010-06-28 12:32 861原文:The Developer Insight Series ... -
[译文]开发者见解系列,第1部分:编写傻瓜代码——来自四位首席Java开发者的建议(上)
2010-06-28 12:25 1452原文:The Developer Insight Series ... -
[译文] Java EE 6中的DataSource资源的定义
2010-05-20 12:29 1964原文:DataSource Resource Definiti ... -
[译文] Java Applets和ASP.net——你可让他们玩到一起吗?
2010-05-13 18:01 1725原文:Java Applets, ASP.net - Can ... -
[译文]使用Java编写你的第一个Google Wave机器人(下)
2010-01-25 21:03 1086原文:Write Your First Google Wave ... -
[译文]使用Java编写你的第一个Google Wave机器人(上)
2010-01-25 21:02 1355原文:Write Your First Google Wave ... -
[译文]一些Java并发技巧
2009-12-20 18:25 1052原文:Some Java Concurrency Tips ...
相关推荐
EN 15085-2_ 2020 中文版(译文)铁路应用-铁路车辆及部件的焊接-第2部分: 对焊接制造商的要求.pdf
ISO 17294-2 2023 水质电感耦合等离子体质谱法(ICP-MS)的应用第2部分:包括铀同位素在内的选定元素的测定.pdf
( Nutch,第1部分:爬行(译文) ( Nutch,第1部分:爬行(译文)
《EN 15085-2_2020 中文版(译文)铁路应用-铁路车辆及部件的焊接-第2部分:对焊接制造商的要求》是针对铁路行业中焊接工艺的重要标准,旨在确保铁路车辆及部件的安全性和可靠性。这份文档详细规定了焊接制造商在...
EN1279标准分为多个部分,本部分(EN1279-2)关注的是透湿性,即中空玻璃防止水汽透过的能力。标准旨在确保中空玻璃在使用过程中能保持稳定的节能性能(如U值和遮阳系数)、健康维护(如隔声和透光性能)以及安全...
学习SDN控制器之一floodlight的中文文档。
SDN开发:Floodlight开发文档的译文 SDN(Software Defined Networking,软件定义网络)是当前网络架构的主要发展方向之一,它通过将控制平面和数据平面分离,实现了网络架构的軟件化和自动化管理。Floodlight是...
标题中的“Microsoft Access 2000: Choosing between MSDE and Jet”指的是在使用Access 2000时,开发者面临的一个关键决策:选择使用改进版的Jet引擎还是微软数据引擎(MSDE)。这两个数据引擎都是用于存储和管理...
Linux内核编码风格指的是在编写Linux内核代码时应遵循的一系列约定和格式规范。由于Linux内核是用C语言编写的,其编码风格遵循了C语言社区的传统习惯,同时根据性能和可读性的需要做了一些调整。这些规则被Linux内核...
这次分享的是系列教程的第三部分,涵盖了第11节至第13节,内容包括45度角瓷砖地图、物理引擎以及弹球游戏的实现。 第11章:45度角瓷砖地图(Isometric Tilemaps) 在这一章节中,我们将深入学习如何构建和管理45度...
此函数的第一个参数实际上是传入DriverEntry函数的`pDriverObject`参数(即驱动对象),第二个参数通常是传递给DriverEntry的第二个参数`RegistryPath`。 在迷你小端口驱动中,除了使用以`VideoPort`开头的API之外...
总结来说,Linux内核的编码风格注重代码的清晰度、一致性及可维护性,通过严格的规则确保所有开发者遵循统一的标准,从而提高整个项目的质量和效率。理解和遵循这些规范,对于任何参与Linux内核开发或希望提升代码...
在"apachecn-bigdata-zh-master"目录下,我们可以预见到一系列与大数据相关的项目和文档,这些项目通常包括但不限于以下几个方面: 1. **Hadoop**:Hadoop是大数据处理的基础框架,提供分布式存储(HDFS)和分布式...
本文将基于《倍加福ENA58IL-R-ProfiNET手册(译文)》的内容,详细介绍该系列编码器如何与PROFINET网络进行整合。 #### 二、产品概述 根据描述,本手册涵盖了以下几种类型的绝对旋转编码器: - Exx58N-...PN... - ...
"计算机英语第二版译文及答案"提供了学习者深入理解和掌握专业术语的重要资源。 这份资料包含两部分:译文和答案。译文部分是对计算机英语原文的中文解释,有助于非英语母语的学习者理解复杂的IT概念和技术用词。...
Huffman编码是一种高效的数据压缩算法,它基于字符出现频率构建最优前缀树,以此来为每个字符分配一个唯一的二进制编码。这个编码方法在文本压缩、数据存储和传输等领域有着广泛的应用。在这个主题中,我们将深入...
2. **链表**:非连续存储的数据结构,每个元素(节点)包含数据和指向下一个节点的指针。链表支持动态大小调整,适用于插入和删除操作。 3. **栈**:后进先出(LIFO)的数据结构,常用于表达式求值、递归和回溯问题...