引用透明性
① 什么是 RMI / IIOP 协议
RMI定义了一组远程接口,可以用于生成远程对象。客户机可以象调用本地对象的方法一样用相同的语法调用远程对象。RMI API提供的类和方法可以处理所有访问远程方法的基础通信和参数引用要求的串行化。
远程方法调用类似于Sun公司1985年提出的远程过程调用(RPC)特征。RPC也要求串行化参数和返回数值数据,但由于没有涉及对象,情况比较简单。Sun开发了外部数据表示(XDR)系统,支持数据串行化。RPC和RMI之间的一个重要差别是RPC用快速而不够可靠的UDP协议,RMI用低速而可靠的TCP/IP协议。
远程方法调用(RMI)和CORBA都是分布式计算技术,在进行分布式时各有其优缺点,为了有助于了解RMI的特点和用途,有必要讨论一下CORBA和RMI的区别。
CORBA(Common Object Request Broker Architecture)是OMG的Object Management Architecture(对象管理结构),它是面向对象的分布式系统建立所依据的标准。CORBA被设计成一个能供所有编程语言使用的一个开放性说明,就是说一个机器上的Java客户可以要求另一个用SmallTalk或C++的机器服务。正是由于这种语言的独立性使得CORBA这么灵活和吸引人。为了适应语言独立性,CORBA采用了非常通用的标准作为其接口。在不同的语言中,远程调用、签名和对象的引入有各自不同的定义,所以CORBA必须尽可能的中立和开放。正是这种通用性是CORBA的一个弱点。当开发人员都采用CORBA时,他们要用一种新的标准定义语言接口,它要求开发者学习新的编程接口,从而减小了远程模型的透明性。
RMI是为仅在Java对Java的分布式计算中而开发的。远程调用的标准是为了Java和应用Java的自然Java签名和调用而开发的,这使得RMI对Java的开发者相当透明而且易于实现。RMI用Java语言紧密集成从而同CORBA相比能够提供非常好的容错能力及对异常的处理。尽管Java的RMI标准不像CORBA那样语言独立,但Java本身是一个独立的平台,这就使RMI在跨平台的分布软件开发中是一个很好的选择。
IIOP
它是一个用于CORBA 2.0及兼容平台上的协议。这个协议的最初阶段是要建立以下几个组件部分:一个IIOP到HTTP的网关,使用这个网关可以让CORBA客户访问WWW资源;一个HTTP到IIOP的网关,通过这个网关可以访问CORBA资源;一个为IIOP和HTTP提供资源的服务器,一个能够将IIOP作为可识别协议的浏览器。
② 增量式开发的优点
进展的可见性
利用增量式开发,每一步增量实现了一个或多个最终用户功能。每一步增量包含所有早期的已开发的功能集加上一些新的功能;系统在逐步累积的增量中增长。例如,在早期增量结束时,开发者很有信心地说:系统的20%已100%完成了,而不是推测系统已完成了20%。
智能控制
增量式开发通过引用透明性,实现了整个系统开发过程中的智能控制。当在后续增量待实现的函数的子规范被嵌入当前增量流程逻辑中时,这种特性,即等式的等量替换令人满意。当拥有引用透明性时,一个系统的部件无需回溯就能根据其子规范得以实现。无需重做前期增量。这里策略有利于在一个完整系统中对每个增量进行正确性验证。
增量系统集成
净室增量式开发允许在整修开发生命期引用透明的用户函数增量的连续集成。因为每一步增量设计基于一个已验证的子规范和前期增量已测试的接口,因此几乎没有更深的设计和接口错误。较好的定义增量贯穿于整修系统开发过程,系统在良好定义的增量中深化。测试和验证工作始于开发周期早期。
连续质量反馈贯穿统计过程控制
已在净室中实践的增量式开发为统计过程控制提供了基础。每一个净室增量都是过程的一个完整周期,包含规范、开发和新的用户函数的验证,加上到目前为止所有已工作的测试。作为统计过程控制的典型,把过程的每一次反复的性能度量与性能目标相比较,以决定是否过程一直在控制之下(即:是否正如所期望的那样发生)。
净室软件小组常使用在测试中的开发性能度量作为过程控制的标准。通常使用的度量包括每千行代码的错误数、失效的间隔时间(MTTF)、可靠性及可信性。其他过程控制方法或许依赖于所管理的事务,而不是产品的质量。进度一致性一、预算一致性瑟整体计划的一致性等等,都是按增量的实际性能与目标性能相比较而言。净室增量度量依据的标准描述了过程控制的具体级别,要按计划继续该项目,开发小组要求此级别。如果标准不符合,开发小组能从增量中检测执行数据,确定问题所在,必要时调整项目计划,修改软件开发过程,避免此类问题的再次发生。例如,如果增量的测试提示过程失去控制(如:质量标准不符合),开发者们应停止测试,返回设计阶段,如果过程是在控制之下,下一歨增量工作才能继续。
统计过程控制(Statistical Process Control ,SPC)是为数据悼念和分析提供较好的开发技术的成熟的工程实践。丰富的方法和工具支持是希望从事更高实践的设计者可利用的。然而,SPC的基本实践要求少量的投资和努力就能产生充足的回报。统计过程控制应用的基本任务很简单:每一过程周期的性能度量,比较实际性能与预先定义的目标性能,确定不可接受偏差的原因,以及通过过程改变改进将来的性能。
例如,如果一个净室小组开发的一个产品在测试中习惯于每千行代码有三个或更少失效,那么一个增量每千行有5个失效或许认为是不可接收的偏差。在调查中,小组或许发现失效是由错误引起的,实际上在验证过程中错误才能被发现,不能证实代码改变的正确性。从这种分析中,小组认识到直到所有错误代码的改变被验证为正确之前这种验证不视为完整的。小组相应地修改验证过程,决心在将来的增量设计中避免因不正确的补丁而引起的失效。以这种方式,每步增量中产生的反馈用于改进下一歨增量过程。
统计过程控制的能力取决于针对正在进行的计划性能与实际性能的对比检验。确定造成不可接受的偏差的原因,制定专门过程改进措施,以重新获得控制或改善控制。净室软件小组实践这些基本原理,并加以发展。每个净室增量都是针对完善的期望来测试,任何失效都被认为是不可接受的。仔细分析由错误发生的失效与开发过程的关系,错误的来源是什么?为什么在小组评审中错误被忽视?如何改进过程避免相同错误站起来重犯?净室软件小组真诚地追求完美,统计过程控制是衡量和提高小组成果的工程规范。
用户使用中不断的功能反馈
增量式开发有助于用户对一个进货系统的执行功能做出尽早的不断的反馈,必要时允许改变。因为增量执行于系统环境并代表了用户功能的子集,早期的增量能通过用户对系统功能性和实用性的检测来反馈。这种反馈有助于避免开发出失效的系统和建立用户可接受的最终产品。
变更的适应性
在系统需求和项目环境中增量式开发允许不可避免变更的系统适应性。在每一步增量完成时,系统需求的积累变更所产生的影响能根据当前规范和增量设计来评估。如果变更与将来增量想到独立,则通常与现已存在的增量开发计划相合并,并对进度和资源进行可能的调整。如果变更影响已完成的增量,自顶向下修改系统开发,通常重用绝大多数已存在的增量代码(通常是全部),按照要求的进度和资源来进行相应调整。
进度与资源管理
项目资源在增量式开发全过程中能在可控制的方式下分配。可用进度是决定待开发的增量数据和其规模的一个因素。在短进度中,小规模增量将有助于在增量交付与认证组之间维持充分的时间段,允许一个有序的测试过程。然而,这将给项目开发小组设计和实现更大、更复杂的增量带来更多负担。进度和复杂性的折衷能够反映增量式开发计划。另外,从后续增量得到的反馈,为过程和产品性能的目标度量提供了管理,以允许在开发和测试中对不足和意外收获的适应。
③ 为什么主函数和中断函数不能调用同一函数
中断服务函数ISR不被任何函数调用,ISR和main可以看作是并行发生的。
函数式编程:
函数式编程是种编程典范,它将电脑运算视为函数的计算。函数编程语言最重要的基础是 λ 演算(lambda calculus)。而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。和过程化编程相比,函数式编程里,函数的计算可随时调用。
在经常被引用的论文 “Why Functional Programming Matters”(请参阅 参考资料) 中,作者 John Hughes 说明了模块化是成功编程的关键,而函数编程可以极大地改进模块化。在函数编程中,编程人员有一个天然框架用来开发更小的、更简单的和更一般化的模块, 然后将它们组合在一起。函数编程的一些基本特点包括:
支持闭包和高阶函数,支持惰性计算(lazy evaluation)。使用递归作为控制流程的机制。加强了引用透明性。没有副作用。我将重点放在在 Java 语言中使用闭包和高阶函数上,但是首先对上面列出的所有特点做一个概述。
闭包和高阶函数:
函数编程支持函数作为第一类对象,有时称为 闭包或者 仿函数(functor)对象。实质上,闭包是起函数的作用并可以像对象一样操作的对象。与此类似,FP 语言支持 高阶函数。高阶函数可以用另一个函数(间接地,用一个表达式) 作为其输入参数,在某些情况下,它甚至返回一个函数作为其输出参数。这两种结构结合在一起使得可以用优雅的方式进行模块化编程,这是使用 FP 的最大好处。
惰性计算:
除了高阶函数和仿函数(或闭包)的概念,FP 还引入了惰性计算的概念。在惰性计算中,表达式不是在绑定到变量时立即计算,而是在求值程序需要产生表达式的值时进行计算。延迟的计算使您可以编写可能潜在地生成无穷输出的函数。因为不会计算多于程序的其余部分所需要的值,所以不需要担心由无穷计算所导致的 out-of-memory 错误。一个惰性计算的例子是生成无穷 Fibonacci 列表的函数,但是对 第 n 个Fibonacci 数的计算相当于只是从可能的无穷列表中提取一项。
递归:
FP 还有一个特点是用递归做为控制流程的机制。例如,Lisp 处理的列表定义为在头元素后面有子列表,这种表示法使得它自己自然地对更小的子列表不断递归。
引用透明性:
函数程序通常还加强引用透明性,即如果提供同样的输入,那么函数总是返回同样的结果。就是说,表达式的值不依赖于可以改变值的全局状态。这使您可以从形式上推断程序行为,因为表达式的意义只取决于其子表达式而不是计算顺序或者其他表达式的副作用。这有助于验证正确性、简化算法,甚至有助于找出优化它的方法。
副作用:
副作用是修改系统状态的语言结构。因为 FP 语言不包含任何赋值语句,变量值一旦被指派就永远不会改变。而且,调用函数只会计算出结果 ── 不会出现其他效果。因此,FP 语言没有副作用