面向对象软件构造(第2版)-第4章 复用性方法Approaches to reusability (中)

4.4 NON-TECHNICAL OBSTACLES

4.4 非技术障碍

 

Why then is reuse not more common?

为什么复用不能更普及?

 

Most of the serious impediments to reuse are technical removing them will be the subject of the following sections of this chapter (and of much of the rest of this book). But of course there are also some organizational, economical and political obstacles.

对复用而言,大部份严重的障碍是技术上的;解决这些障碍是本章下面各段的主题(同时也是本书其它部分的主题).但是当然也有一些是组织的,经济的和政治上的障碍.

 

The NIH syndrome

NIH综合症

 

An often quoted psychological obstacle to reuse is the famous Not Invented Here (“NIH”) syndrome. Software developers, it is said, are individualists, who prefer to redo everything by themselves rather than rely on someone else’s work.

对复用来说,一个时常被提起的心理障碍是出名的非自创("NIH")综合症.据说,软件开发者都是个人主义者,他们宁愿亲自重做每件事而不愿借助于他人的工作.

 

This contention (commonly heard in managerial circles) is not borne out by experience. Software developers do not like useless work more than anyone else. When a good, well-publicized and easily accessible reusable solution is available, it gets reused.

这个争论(在管理圈中经常能听到)并没有被实际验证过.软件开发者比其他任何人更不喜欢无用的工作.当优秀的,易于宣传的和容易理解的可复用解决方可以被使用时,它就会被复用.

 

Consider the typical case of lexical and syntactic analysis. Using parser generators such as the Lex-Yacc combination, it is much easier to produce a parser for a command language or a simple programming language than if you must program it from scratch. The result is clear: where such tools are available, competent software developers routinely reuse them. Writing your own tailor-made parser still makes sense in some cases, since the tools mentioned have their limitations. But the developers’ reaction is usually to go by default to one of these tools it is when you want to use a solution not based on the reusable mechanisms that you have to argue for it. This may in fact cause a new syndrome, the reverse of NIH, which we may call HIN (Habit Inhibiting Novelty): a useful but limited reusable solution, so entrenched that it narrows the developers’ outlook and stifles innovation, becomes counter-productive. Try to convince some Unix developers to use a parser generator other than Yacc, and you may encounter HIN first-hand.

考虑一下词汇语法分析的典型情况.使用如Lex-Yacc组合这样的解析生成器,对一个命令语言或一个简单的程序语言产生一个解析器(parser),比您必须从头开发它更加容易.结果很清楚:当能利用这样的工具时,能干的软件开发者就会照例复用它们.由于这些所提及的工具有其局限性,写您自己度身订做的解析器在一些情况下仍然是有道理的.但是开发者通常是这些工具没有替代产品才会去做;而且这是当您使用了一个并不基于复用机制的解决方案的时候,您也不得不同意. 事实上这可能引起一种新的并发症,和NIH相反,我们可以称之为HIN(Habit Inhibiting Novelty墨守成规):一种有用但是有限的复用解决方案,如此难以改变导致了开发者的视野狭窄并扼杀革新,成为反生产力.试着让一些Unix开发者除了Yacc之外去使用另一个解析器,您也许就会直径遇到HIN.

[注] LexYaccUnix/Linux上的词法语法分析代码生成工具,可以用来编写编译程序和解释程序,同时也可用于其它需要对结构化输入生成解析工具的场合。

 

Something which may externally look like NIH does exist, but often it is simply the developers’ understandably cautious reaction to new and unknown components. They may fear that bugs or other problems will be more difficult to correct than with a solution over which they have full control. Often such fears are justified by unfortunate earlier attempts at reusing components, especially if they followed from a management mandate to reuse at all costs, not accompanied by proper quality checks. If the new components are of good quality and provide a real service, fears will soon disappear.

可能从外表看起来NIH好象并不存在,但是通常它只是开发者对新的和未知的组件的一种可理解的谨慎的反应.相比一个他们能完全控制的解决方案而言,他们可能害怕修改错误或其它的问题会更加困难.通常这样的担心在先前尝试复用组件时被不幸地证明了,尤其是如果他们听从一个管理命令不惜任何代价的去复用, 同时却不做正确的品质检查.但如果新组件是有良好的品质并且提供确实的服务,那么恐惧就会很快地消失掉.

 

What this means for the producer of reusable components is that quality is even more important here than for more ordinary forms of software. If the cost of a non-reusable, one-of-a-kind solution is N, the cost R of a solution relying on reusable components is never zero: there is a learning cost, at least the first time developers may have to bend their software to accommodate the components and they must write some interfacing software, however small, to call them. So even if the reusability savings

                          R

r =    ------

           N

and other benefits of reuse are potentially great, you must also convince the candidate reusers that the reusable solution’s quality is good enough to justify relinquishing control.

在这里,对可复用组件的生产者意谓着,品质比一般的软件形式更为重要.如果一个不可复用的,与众不同的解决方案费用为N,使用可复用组件的解决方案的费用为R且不为零:这里有一个学习的成本,至少第一次会有开发者可能不得不修改他们的软件以适应组件并且他们必须写一些小型的接口软件去调用组件.因此即使复用性节省了

                          R

r =    ------

           N

其它复用的利益可能很大,那么您也一定要使潜在的复用者相信,可复用的解决方案的品质已经足够好来证明放松控制的正确性.

 

This explains why it is a mistake to target a company’s reusability policy to the potential reusers (the consumers, that is to say the application developers). Instead you should put the heat on the producers, including people in charge of acquiring external components, to ensure the quality and usefulness of their offering. Preaching reuse to application developers, as some companies do by way of reusability policy, is futile: because application developers are ultimately judged by how effectively they produce their applications, they should and will reuse not because you tell them to but because you have done a good enough job with the reusable components (developed or acquired) that it will be profitable for their applications to rely on these components.

这解释了为什么把公司的复用性政策对准潜在的复用者(消费者,也就是应用程序开发者)是个错误.相反的,您应该把精力放在生产者身上以确定他们所提供的品质和有效性,这包括掌管获取外部组件的人.对应用程序开发者鼓吹复用是没有效果的,就如一些公司复用性政策所做的: 因为他们编写的应用程序的有效性才对应用程序开发者作出最终判断,他们应该并将会采取复用,不是因为您告诉他们要用而是因为您利用可复用的组件(自己开发的或从外面获得的)完成了一个相当出色的工作,要是把他们的应用程序建立在这些组件之上会是有利可图的.

 

The economics of procurement

采购经济学

 

A potential obstacle to reuse comes from the procurement policy of many large corporations and government organizations, which tends to impede reusability efforts by focusing on short-term costs. US regulations, for example, make it hard for a government agency to pay a contractor for work that was not explicitly commissioned (normally as part of a Request For Proposals). Such rules come from a legitimate concern to protect taxpayers or shareholders, but can also discourage software builders from applying the crucial effort of generalization to transform good software into reusable components.

复用的一个潜在的障碍来自许多大的公司和政府机构的采购政策,因关注短期的费用而妨碍了复用性的成果.例如,美国法规使政府机关对没被明确委任工作的承包商支付费用很困难(通常为征求建议书(Request For Proposals, RFP)的一部份).这样的规则来自于对保护纳税人或股东的合法考虑,但是也阻止了软件构建者应用至关重要的泛化(generalization)成果把好的软件转变成可复用的组件.

 

On closer examination this obstacle does not look so insurmountable. As the concern for reusability spreads, there is nothing to prevent the commissioning agency from including in the RFP itself the requirement that the solution must be general-purpose and reusable, and the description of how candidate solutions will be evaluated against these criteria. Then the software developers can devote the proper attention to the generalization task and be paid for it.

在最近的研究中,这个障碍看起来并不是不能克服的.当对复用性的关注更广泛时,可以把佣金代理包括在RFP本身的需求和描述中,其中,需求包括解决方案一定要可以被广泛使用和复用,描述包括候选方案将会如何评估这些标准.然后软件开发者才能专心于泛化工作并得到相应的报酬.

 

Software companies and their strategies

软件公司及其策略

 

Even if customers play their part in removing obstacles to reuse, a potential problem remains on the side of the contractors themselves. For a software company, there is a constant temptation to provide solutions that are purposely not reusable, for fear of not getting the next job from the customer — because if the result of the current job is too widely applicable the customer may not need a next job!

即使客户在消除复用障碍方面起到一定作用,但一个潜在的问题还在承包商自己这边.对于一家软件公司来说,有一个经常性的诱惑是故意提供可复用的解决方案,惟恐从客户那里得不到下一个定单-因为如果当前工作的结果可以广泛地适用,那么客户可能不再需要下一个任务!

 

I once heard a remarkably candid expose of this view after giving a talk on reuse and object technology. A high-level executive from a major software house came to tell me that, although intellectually he admired the ideas, he would never implement them in his own company, because that would be killing the goose that laid the golden egg: more than 90% of the company’s business derived from renting manpower — providing analysts and programmers on assignment to customers — and the management’s objective was to bring the figure to 100%. With such an outlook on software engineering, one is not likely to greet with enthusiasm the prospect of widely available libraries of reusable components.

在一次关于复用和对象技术的演讲之后,对于这个观点我听到了非常坦白的陈述.来自一个主要的软件机构的高层主管告诉我,因为那会杀害了生金蛋的鹅,所以虽然他赞同这个演讲的观念,但是他无法在自己的公司中实现:超过90%的公司生意得自于人力收益-根据客户的任务提供分析师和程序员-并且管理层的目标是要带来100%的预期.在这种软件工程的观点上,对广泛有效的可复用组件库的热衷是不可能接受的.

 

The comment was notable for its frankness, but it triggered the obvious retort: if it is at all possible to build reusable components to replace some of the expensive services of a software house’s consultants, sooner or later someone will build them. At that time a company that has refused to take this route, and is left with nothing to sell but its consultants’ services, may feel sorry for having kept its head buried in the sand.

对它的坦白之评价是正面的,但是它也引起了明显的反驳:如果全然可能去建立可复用组件代替软件机构中顾问的昂贵服务,迟早人们会建立它们.到那时拒绝接受变化并且除了顾问服务以外什么也没有的公司,只能自己骗自己罢了.

 

It is hard not to think here of the many engineering disciplines that used to be heavily labor-intensive but became industrialized, that is to say tool-based — with painful economic consequences for companies and countries that did not understand early enough what was happening. To a certain extent, object technology is bringing a similar change to the software trade. The choice between people and tools need not, however, be an exclusive one. The engineering part of software engineering is not identical to that of mass-production industries humans will likely continue to play the key role in the software construction process. The aim of reuse is not to replace humans by tools (which is often, in spite of all claims, what has happened in other disciplines) but to change the distribution of what we entrust to humans and to tools. So the news is not all bad for a software company that has made its name through its consultants. In particular:

在这里,很容易地联想到过去一直是重劳力密集的许多工程产业都变成工业化了,更确切的说,工具化了-那些不能及早了解世间变化的公司和国家正在承受着棘手的经济结果.一定程度上,对象技术正对软件工业带来了相似的变化.在人和工具之间的选择并不是必须的,然而,却是唯一的.软件工程的工程部份并不等同于大规模生产的工业;人或许会在软件构造过程中继续扮演着关键的角色.复用的目标不仅仅是用工具(常常是这样,尽管所有的要求都已经在其它的产业中发生过)取代人而且是改变我们委派给人和给工具之间的分配.对一家以顾问闻名的软件公司来说,这样的新闻并不总是坏事.尤其:

 

• In many cases developers using sophisticated reusable components may still benefit from the help of experts, who can advise them on how best to use the components. This leaves a meaningful role for software houses and their consultants.

在许多情况中,使用复杂的可复用组件的开发者还可以受益于专家的帮助,专家能够建议如何最有效地使用组件.这为软件机构和他们的顾问留下了一个有意义的角色.

 

• As will be discussed below, reusability is inseparable from extendibility: good reusable components will still be open for adaptation to specific cases. Consultants from a company that developed a library are in an ideal position to perform such tuning for individual customers. So selling components and selling services are not necessarily exclusive activities a components business can serve as a basis for a service business.

在下面讨论中,复用性和扩充性是联系在一起的:对于特定情况下地改编,良好的可复用组件仍始终保持着开放性.在一家开发库的公司里,顾问们是在一个理想的形式中为个别的客户完成这样的调整.因此销售组件和销售服务并不是独立的活动;组件生意可视为服务生意的一种基础.

 

• More generally, a good reusable library can play a strategic role in the policy of a successful software company, even if the company sells specific solutions rather than the library itself, and uses the library for internal purposes only. If the library covers the most common needs and provides an extendible basis for the more advanced cases, it can enable the company to gain a competitive edge in certain application areas by developing tailored solutions to customers’ needs, faster and at lower cost than competitors who cannot rely on such a ready-made basis.

更一般的,在一个成功的软件公司的策略中,一个优秀的可复用库能够扮演一个站略上的角色,即便公司销售的是特定的解决方案而并非库本身,并且只在内部使用库.如果库包含了最普遍的需求而且提供了对更高阶情形的扩充基础,那么通过开发适应客户需求的解决方案,比不具备这样的现成基础的竞争者更快速并花费更低成本,这样能够使公司在确定的应用领域中获得竞争优势.

 

Accessing components

存取访问

 

Another argument used to justify skepticism about reuse is the difficulty of the component management task: progress in the production of reusable software, it is said, would result in developers being swamped by so many components as to make their life worse than if the components were not available.

常用来对有关复用的怀疑进行验证的另一个论据,是组件管理工作的困难性: 据说在可复用的软件产品的发展中,导致开发者陷入困境的是有太多的组件使他们变得更糟,而不是组件无法使用.

 

Cast in a more positive style, this comment should be understood as a warning to developers of reusable software that the best reusable components in the world are useless if nobody knows they exist, or if it takes too much time and effort to obtain them. The practical success of reusability techniques requires the development of adequate databases of components, which interested developers may search by appropriate keywords to find out quickly whether some existing component satisfies a particular need. Network services must also be available, allowing electronic ordering and immediate downloading of selected components.

用一种较积极的态度来说,对于可复用的软件开发者,应该把这个评论当成一个警告: 如果没人知道它们的存在,或花了过多的时间和努力来获取它们,那么就算是世界上最好的可复用组件也根本无用.复用性技术的实际成功表明,这需要发展足够的组件数据库,让感兴趣的开发者可以通过适当的关键字快速查找以发现是否有存在的组件满足特定的需求.网络服务也应该可以利用,允许电子订购并立即下载所挑选的组件.

 

These goals do raise technical and organizational problems. But we must keep things in proportion. Indexing, retrieving and delivering reusable components are engineering issues, to which we can apply known tools, in particular database technology there is no reason why software components should be more difficult to manage than customer records, flight information or library books.

这些目标引起了技术上和组织上的问题.但是我们必须保持一定的比例.索引,检索和发布可复用组件给那些我们能够应用的已知工具,特别是数据库技术方面,这是工程上的主题;这里没有说明为什么管理软件组件应该比处理客户记录,航班信息或图书馆藏书更困难.

 

Reusability discussions used to delve forever into the grave question “how in the world are we going to make the components available to developers?”. After the advances in networking of the past few years, such debates no longer appear so momentous. With the World-Wide Web, in particular, have appeared powerful search tools (AltaVista, Yahoo¼) which have made it far easier to locate useful information, either on the Internet or on a company’s Intranet. Even more advanced solutions (produced, one may expect, with the help of object technology) will undoubtedly follow. All this makes it increasingly clear that the really hard part of progress in reusability lies not in organizing reusable components, but in building the wretched things in the first place.

在复用性的讨论中,过去常常深入研究一个重大的问题是"我们究竟如何使开发者有效地使用组件?.在过去数年中网络发展之后,这样的讨论已不再显得那么紧要了.特别是随着WWW已经出现了强有力的搜索工具(AltaVista,Yahoo),这已经能非常容易的在英特网或公司内部网络上找出有用的信息.甚至更先进的解决方案(可能期待的是借助对象技术而产生)也将会毫无疑问地随之而来.所有这些清楚地表明了,复用性过程中真正困难的部份不仅仅是在组织可复用组件方面,而且在开始就构建了糟糕的程序方面.

 

A note about component indexing

有关组件索引

 

On the matter of indexing and retrieving components, a question presents itself, at the borderline between technical and organizational issues: how should we associate indexing information, such as keywords, with software components?

在索引和检索组件的内容上,一个问题出现在技术和组织的论点之间的分界线上: 我们如何应该关联像关键字这样的索引信息和软件组件?

 

The Self-Documentation principle suggests that, as much as possible, information about a module — indexing information as well as other forms of module documentation — should appear in the module itself rather than externally. This leads to an important requirement on the notation that will be developed in part C of this book to write software components, called classes. Regardless of the exact form of these classes, we must equip ourselves with a mechanism to attach indexing information to each component.

自包含文档原则建议了,尽可能多的有关一个模块的信息-索引信息和其它形式的模块文档-应该出现在模块本身中,而不是在外部.这导致了一个编写软件组件的一个重要需求,在符号上叫做类,在本书的C部份中将会被介绍.不管这些类的形式正确与否,我们必须使用某种机制以便把索引信息附在每个组件上.

 

The syntax is straightforward. At the beginning of a module text, you will be invited to write an indexing clause of the form

indexing

index_word1: value, value, value¼

index_word2: value, value, value¼

¼

¼ Normal module definition (see part C) ¼

 

Each index_word is an identifier each value is a constant (integer, real etc.), an identifier, or some other basic lexical element.

这个语法简单易懂. 在模块代码的开头,您要先声明索引子句(indexing clause)

indexing

index_word1: value, value, value¼

index_word2: value, value, value¼

¼

¼ Normal module definition (see part C) ¼

每个index_word是一个标识符; 每个value是一个常量(整数,实数等等), 标识符,或其它的基本语法元素.

 

There is no particular constraint on index words and values, but an industry, a standards group, an organization or a project may wish to define their own conventions. Indexing and retrieval tools can then extract this information to help software developers find components satisfying certain criteria.

在索引命令和数值上没有特别的限制,但是一种产业,一个一流团队,一个组织或一个项目可能希望定义他们自己的标准.索引和检索工具于是能抽取这个信息,来帮助软件开发者找到符合特定标准的组件.

 

As we saw in the discussion of Self-Documentation, storing such information in the module itself — rather than in an outside document or database — decreases the likelihood of including wrong information, and in particular of forgetting to update the information when updating the module (or conversely). Indexing clauses, modest as they may seem, play a major role in helping developers keep their software organized and register its properties so that others can find out about it.

如我们在自包含文档的讨论中所看到的,在模块的自身中储存这些信息-胜于储存在外面文件或数据库中-减少了包括错误信息的可能性,特别是当更新模块(或相反)时忘记了更新信息.如其所示,适度的索引子句,在帮助开发者组织他们的软件和记录软件属性中起着重要的作用,这样便于其他人的查找.

 

Formats for reusable component distribution

可复用组件分配的格式

 

Another question straddling the technical-organizational line is the form under which we should distribute reusable components: source or binary? This is a touchy issue, so we will limit ourselves to examining a few of the arguments on both sides.

横跨在技术-组织的界线上的另外一个问题是我们所发布的可复用组件的格式: 源代码或二进制码? 这是一个敏感的话题,因此我们将有限地讨论两方中的一些论点.

 

For a professional, for-profit software developer, it often seems desirable to provide buyers of reusable components with an interface description (the short form discussed in a later chapter) and the binary code for their platform of choice, but not the source form.This protects the developer’s investment and trade secrets.

对于一个专业的,非盈利的软件开发者来说,提供给买主的可复用组件具有一个接口描述(简易格式(short form),在稍后的章节中讨论)和相关平台的二进制代码,而不是源代码形式,这通常看上去是很合理的.这保护了开发者的投资和商业秘密.

 

Binary is indeed the preferred form of distribution for commercial application programs, operating systems and other tools, including compilers, interpreters and development environments for object-oriented languages. In spite of recurring attacks on the very idea, emanating in particular from an advocacy group called the League for Programming Freedom, this mode of commercial software distribution is unlikely to recede much in the near future. But the present discussion is not about ordinary tools or application programs: it is about libraries of reusable software components. In that case one can also find some arguments in favor of source distribution.

对于商业应用程序,操作系统和其它的工具,包括面向对象语言的编译器,解释器和开发环境而言,二进制代码的确是发布的首选形式.尽管遭到不断的抨击,特别是来自一个被称为自由编程协会(League for Programming Freedom)的拥护组织,但这个商业软件发布的形式在不久的将来不太可能会改变.但是目前的讨论并不涉及通常的工具或是应用程序:它是有关于可复用的软件组件库.在那种情况下也能找到一些论据来支持源代码发布.

 

[注] 自由编程协会(League for Programming Freedom) 是一民间组织,由教授,学生,经商者,程序员,用户和软件公司组成,献身于重新得到编写程序的自由.该协会并不反对议会所希望的法律系统一一个体程序的版权。该协会的目标是扭转由特殊利益引起的判决所造成的变化(有关软件的版权).

 

For the component producer, an advantage of source distribution is that it eases porting efforts. You stay away from the tedious and unrewarding task of adapting software to the many incompatible platforms that exist in today’s computer world, relying instead on the developers of object-oriented compilers and environments to do the job for you. (For the consumer this is of course a counter-argument, as installation from source will require more work and may cause unforeseen errors.)

对于组件作者,发布源代码的一个好处是能够减轻移植的消耗.您可以从为计算机领域中现存的许多不相容的平台而修改软件中脱离出来,改为依靠面向对象的编译器和环境的开发者为您做这些乏味无聊的工作.(对消费者而言,这当然是一个驳论,因为安装源代码将会需要更多的工作,并可能引起无法预料的错误.)

 

Some compilers for object-oriented languages may let you retain some of the portability benefit without committing to full source availability: if the compiler uses C as intermediate generated code, as is often the case today, you can usually substitute portable C code for binary code. It is then not difficult to devise a tool that obscures the C form, making it almost as difficult to reverse-engineer as a binary form.

一些面向对象语言的编译器可以在不用提交完整代码的情况下让您保留一些移植性上的好处:正如如今的一种惯例,如果编译器使用C作为介质以产生代码,那么您通常能用可移植的C代码代替二进制代码.然后这很容易设计一个的工具用以加密C的结构,使其几乎不能反编译成一种二进制形式.

 

Also note that at various stages in the history of software, dating back to UNCOL (UNiversal COmputing Language) in the late fifties, people have been defining low-level instruction formats that could be interpreted on any platform, and hence could provide a portable target for compilers. The ACE consortium of hardware and software companies was formed in 1988 for that purpose. Together with the Java language has come the notion of Java bytecode, for which interpreters are being developed on a number of platforms. But for the component producer such efforts at first represent more work, not less: until you have the double guarantee that the new format is available on every platform of interest and that it executes target code as fast as platform-specific solutions, you cannot forsake the old technology, and must simply add the new target code format to those you already support. So a solution that is advertized as an end-all to all portability problems actually creates, in the short term, more portability problems.

同时也要注意在软件历史的各种不同阶段中,远在五十年代的UNCOL时期(通用计算语言UNiversal COmputing Language),人们就已经定义了低级指令格式以便能在任何的平台上解释,想从此可以对编译器提供一个可移植的标准.为了这个目的,1988年成立了包括硬件和软件公司在内的ACE联盟.加之JAVA语言带来了JAVA字节码的观念,解释器正在许多的平台上被开发.但对于组件作者,这样的话在开始会需要做更多的工作,而非减少:除非您加倍保证新格式在每个重要的平台上都同样有效,并且运行目标代码就像在特定平台的解决方案一样快速,那么在此之前,您就不能放弃旧有的技术,还必须能轻松地把新的目标代码格式加入到您已经支持的平台上.因此,就眼前来说,一个号称能解决所有的移植性问题的解决方案实际上可能产生更多的移植性问题.

 

[注]60年代,计算机界有过面向通用计算机的统一语言(Universal Computer Oriented Language,UNCOL)用虚拟机实现统一编译的思想,即各种语言都编译到UNCOL,然后在本地机上实现UNCOL,但后来没有流行起来.现在一般还都是针对具体机器、具体的操作系统研制特定语言的编译系统.

 

Perhaps more significant, as an argument for source code distribution, is the observation that attempts to protect invention and trade secrets by removing the source form of the implementation may be of limited benefit anyway. Much of the hard work in the construction of a good reusable library lies not in the implementation but in the design of the components’ interfaces and that is the part that you are bound to release anyway. This is particularly clear in the world of data structures and algorithms, where most of the necessary techniques are available in the computing science literature. To design a successful library, you must embed these techniques in modules whose interface will make them useful to the developers of many different applications. This interface design is part of what you must release to the world.

作为一个对源代码发布的意见,也许更重要一点是,观察表明通过去掉实现中的源代码来保护发明和商业秘密的行为无论如何其利益都是有限的.在一个优秀的可复用库的构造中,许多艰苦的工作不是存在实现中,而是在组件接口的设计中;那是您无论如何都得要发布的一部份.这在数据结构和算法的领域中尤其清楚,在计算科学文献中大部份必需的技术在其中都有效.为了要设计一个成功的库,您一定要在模块中嵌入这些技术,这些模块的接口会有用于许多不同的应用程序开发者.这个接口设计是您必须发布出去的一部份.

 

Also note that, in the case of object-oriented modules, there are two forms of component reuse: as a client or, as studied in later chapters, through inheritance. The second form combines reuse with adaptation. Interface descriptions (short forms) are sufficient for client reuse, but not always for inheritance reuse.

也要注意,在面向对象模块的情况下,有二种组件复用的形式:客户端复用或经由继承复用,后者在稍后的章节中学到.第二种形式结合了复用和修改.接口描述 (简易格式)对客户端复用是足够了的,但对继承复用却不.

 

Finally, the educational side: distributing the source of library modules is a good way to provide models of the producer’s best engineering, useful to encourage consumers to develop their own software in a consistent style. We saw earlier that the resulting standardization is one of the benefits of reusability. Some of it will remain even if client developers only have access to the interfaces but nothing beats having the full text.

最后,具有教育意义的一面是:要提供最好的工程模型,发布库模块的源代码是一个好方法,这有利于鼓励用户以一致风格去开发他们自己的软件.我们早就看到结果标准化是复用性的优点之一.其中的一些将会保留,即使客户端开发者只能使用接口;但拥有全部源代码更好.

 

Be sure to note that even if source is available it should not serve as the primary documentation tool: for that role, we continue to use the module interface.

注意,即使可以利用源代码,它也不应该视为主要的文档工具:对此,我们继续使用模块接口.

 

This discussion has touched on some delicate economic issues, which condition in part the advent of an industry of software components and, more generally, the progress of the software field. How do we provide developers with a fair reward for their efforts and an acceptable degree of protection for their inventions, without hampering the legitimate interests of users? Here are two opposite views:

这个讨论已经略微提及了一些微妙的经济议题,即软件组件工业出现的部份条件,更概括的讲,是软件领域进步的部份条件.我们如何提供给开发者一个公平的报答,对他们所做的努力,并以一种可接受的程度保护他们的发明,而不阻碍用户的合法兴趣? 这里有二个对立的观点:

 

• At one end of the spectrum you will find the positions of the League for Programming Freedom: all software should be free and available in source form.

在其中的一方,您可以找到自由编程协会的态度: 所有软件应该是免费的并能得到源代码形式.

 

• At the other end you have the idea of superdistribution, advocated by Brad Cox in several articles and a book. Superdistribution would allow users to duplicate software freely, charging them not for the purchase but instead for each use. Imagine a little counter attached to each software component, which rings up a few pennies every time you make use of the component, and sends you a bill at the end of the month. This seems to preclude distribution in source form, since it would be too easy to remove the counting instructions. Although JEIDA, a Japanese consortium of electronics companies, is said to be working on hardware and software mechanisms to support the concept, and although Cox has recently been emphasizing enforcement mechanisms built on regulations (like copyright) rather than technological devices, superdistribution still raises many technical, logistic, economic and psychological questions.

在另一方,您会得到一个超发布(superdistribution)的观念,这是Brad Cox在一些文章和书中所主张的.超发布允许用户免费地复制软件,在每次使用时付费而不是在购买时.设想一个小的计数器附在每个软件组件上,每一次在您使用组件时记入一些美分,到月底时送您一份帐单.由于发布源代码很容易让人删除计数指令,所以这似乎排除了这种形式.虽然JEIDA,一个日本电子公司协会,据称正在以硬件软件结合的机制支持这种观念,并且Cox最近一直在强调执行机制建立在规则上(类似版权)而非技术装置上,但是超发布仍然引起了许多技术上的,逻辑上的,经济上的和心理学上的问题.

 

An assessment

评估

 

Any comprehensive approach to reusability must, along with the technical aspects, deal with the organizational and economical issues: making reusability part of the software development culture, finding the right cost structure and the right format for component distribution, providing the appropriate tools for indexing and retrieving components. Not surprisingly, these issues have been the focus of some of the main reusability initiatives from governments and large corporations, such as the STARS program of the US Department of Defense (Software Technology for Adaptable, Reliable Systems) and the “software factories” installed by some large Japanese companies.

任何复用性的综合方案,连同技术方面一起,都会涉及组织和经济方面的议题:使复用性成为软件开发文化的一部分,找出组件发布的合理费用结构和正确格式,为索引和检索组件提供适当的工具.并不令人惊讶的是,这些议题已经是一些主要的复用性行动的中心,其来自于政府和大型公司,像是美国国防部的STARTS程序(可适应的,可靠的系统之软件技术Software Technology for Adaptable, Reliable Systems)和被一些大型日本公司建立的"软件工厂".

 

Important as these questions are in the long term, they should not detract our attention from the main roadblocks, which are still technical. Success in reuse requires the right modular structures and the construction of quality libraries containing the tens of thousands of components that the industry needs.

以长远的观点来看这些问题,重要的是,他们不应该从主要的障碍中转移我们的注意力.这些障碍仍旧是技术上的.复用的成功需要良好的模块结构和高品质库的构造,这些库中包含了数万个工业所需要的组件.

 

The rest of this chapter concentrates on the first of these questions it examines why common notions of module are not appropriate for large-scale reusability, and defines the requirements that a better solution — developed in the following chapters — must satisfy.

本章的其余部分专注于这些问题的第一条;它分析了通常的模块概念为什么不适用于大规模的复用性,同时定义了一个更好的解决方案所必须满足的需求,在下面的章节中将规划这个方案.

 

4.5 THE TECHNICAL PROBLEM

4.5 技术问题

 

What should a reusable module look like?

一个可复用的模块看上去象什么?

 

Change and constancy

改变和恒定

 

Software development, it was mentioned above, involves much repetition. To understand the technical difficulties of reusability we must understand the nature of that repetition.

上面所提及的软件开发中包括了大量的重复.要理解复用性上的技术困难,我们必须要理解重复的性质.

 

Such an analysis reveals that although programmers do tend to do the same kinds of things time and time again, these are not exactly the same things. If they were, the solution would be easy, at least on paper but in practice so many details may change as to defeat any simple-minded attempt at capturing the commonality.

某个分析表明了,虽然程序设计者一次又一次的做着相同类型的事,但却并不是完全地相同.如果相同的话,至少在名义上,解决方案就会变得容易的多;但是在实际上,大量的细节可能会被改变,这导致在捕捉共性上任何头脑简单的尝试都会遭到失败.

 

A telling analogy is provided by the works of the Norwegian painter Edvard Munch, the majority of which may be seen in the museum dedicated to him in Oslo, the birthplace of Simula. Munch was obsessed with a small number of profound, essential themes: love, anguish, jealousy, dance, death¼ He drew and painted them endlessly, using the same pattern each time, but continually changing the technical medium, the colors, the emphasis, the size, the light, the mood.

一个生动的类比是由挪威画家Edvard Munch的作品所提供的,其中大多数在奥斯陆的博物馆中能看到,这也是Simula的诞生地. Munch迷于少数深刻,本质的主题: 爱,苦闷,妒忌,跳舞,死亡他不断地汲取和绘画它们,在每段时间内使用相同的图案,但是不断地变更技术媒介,颜色,重点,大小,光,情绪等等.

 

Such is the software engineer’s plight: time and again composing a new variation that elaborates on the same basic themes.

这是软件工程师的情况:反复构成了一种新的变化,这种新变化描述了相同的基本主题.

 

Take the example mentioned at the beginning of this chapter: table searching. True, the general form of a table searching algorithm is going to look similar each time: start at some position in the table t then begin exploring the table from that position, each time checking whether the element found at the current position is the one being sought, and, if not, moving to another position. The process terminates when it has either found the element or probed all the candidate positions unsuccessfully. Such a general pattern is applicable to many possible cases of data representation and algorithms for table searching, including arrays (sorted or not), linked lists (sorted or not), sequential files, binary trees, B-trees and hash tables of various kinds.

举一个在本章开头提到的例子:表查询.表查询算法的通式每次看上去都很相似:在表t的某些位置开始;然后从那个位置开始扫描,每次在当前的位置都检查是否发现被寻找的元素,如果没有,移到下一个位置.当发现了元素或在所有的预定范围内都无所斩获时程序结束.这样一个表查询的通用模式可以应用在数据表示法和算法中的许多可能的情况,包括各种不同类型的数组(排序或未排序),链表(排序或未排序),顺序文件,二进制树,B树和哈希表.

 

It is not difficult to turn this informal description into an incompletely refined routine:

将非正式的描述变成一个并不完全精确的程序并不困难:

 

has (t: TABLE, x: ELEMENT): BOOLEAN is

-- Is there an occurrence of x in t?

local

pos: POSITION

do

from

pos := INITIAL_POSITION (x, t)

until

EXHAUSTED (pos, t) or else FOUND ( pos, x, t)

loop

pos := NEXT (pos, x, t)

end

Result := not EXHAUSTED (pos, t)

end

 

(A few clarifications on the notation: from ¼ until ¼ loop ¼ end describes a loop, initialized in the from clause, executing the loop clause zero or more times, and terminating as soon as the condition in the until clause is satisfied. Result denotes the value to be returned by the function. If you are not familiar with the or else operator, just accept it as if it were a boolean or.)

(符号中的一些声明: from ¼ until ¼ loop ¼ end描述了一个循环,from子句开始,执行loop子句零次或多次,直到条件满足until子句结束. Result指定了函数返回值.如果您不熟悉or else运算符,就当它是一个布尔类型的or好了.)

 

Although the above text describes (through its lower-case elements) a general pattern of algorithmic behavior, it is not a directly executable routine since it contains (in upper case) some incompletely refined parts, corresponding to aspects of the table searching problem that depend on the implementation chosen: the type of table elements (ELEMENT), what position to examine first (INITIAL_POSITION), how to go from a candidate position to the next (NEXT), how to test for the presence of an element at a certain position (FOUND), how to determine that all interesting positions have been examined (EXHAUSTED).

虽然上述的文字描述了(以它的小写元素)一个算法行为的通用模式,但是由于它包含了(大写部分)一些不完全精确的部份,它并不是一个直接可运行的程序,相应的表查询方面的问题依赖于被选择的具体实现:表元素类型(ELEMENT),开始查询的位置(INITIAL_POSITION),如何从一个选定的位置移到下一个(NEXT),该如何在一个特定位置检测元素的存在(FOUND),该如何确定所有的指定位置都已经被检测过了(EXHAUSTED).

 

Rather than a routine, then, the above text is a routine pattern, which you can only turn into an actual routine by supplying refinements for the upper-case parts.

那么,上述的本文并非一个程序,而是一个程序模式,您只能通过提供大写部分所对应的精确语句转变成一个真实的程序.

 

The reuse-redo dilemma

复用重做的难题

 

All this variation highlights the problems raised by any attempt to come up with general-purpose modules in a given application area: how can we take advantage of the common pattern while accommodating the need for so much variation? This is not just an implementation problem: it is almost as hard to specify the module so that client modules can rely on it without knowing its implementation.

所有的这一变化突出了一个问题,在特定的应用程序领域中,尝试着去找到通用的模块的行为引发了这个问题:当需要适应这么多变化的时候,我们如何能够利用通用模式?这不单单是一个实现的问题:它几乎如此严密地详细指明了模块以至于客户端模块能在不知道其实现的情况下使用它.

 

These observations point to the central problem of software reusability, which dooms simplistic approaches. Because of the versatility of software — its very softness — candidate reusable modules will not suffice if they are inflexible.

这些观察指出了软件复用性的核心问题,即注定是过分单纯化的方法.由于软件的多功能性-其十足的柔韧性-如果备选的可复用的模块不具有灵活性,那么它们就满足不了.

 

A frozen module forces you into the reuse or redo dilemma: reuse the module exactly as it is, or redo the job completely. This is often too limiting. In a typical situation, you discover a module that may provide you with a solution for some part of your current job, but not necessarily the exact solution. Your specific needs may require some adaptation of the module’s original behavior. So what you will want to do in such a case is to reuse and redo: reuse some, redo some — or, you hope, reuse a lot and redo a little. Without this ability to combine reuse and adaptation, reusability techniques cannot provide a solution that satisfies the realities of practical software development.

一个不可改变的模块迫使您进入了复用或重做的难题之内: 照现在的样子完全地复用模块,否则全部重做.这时常有太多的限制.在一种典型的情形中,您发现一个模块可能为您的目前的部份工作的提供了解决方案,但却不是完全的符合.您的特定需求可能需要改写模块原来的行为.因此,在这种情况下您所想做的是复用重做:一部分复用,一部分重做-或者,如您所愿,大部分复用,小部分重做.没有结合复用和改写这两者的能力,复用性技术就不能够提供一种解决方案来满足现实软件开发中的真实性.

 

So it is not by accident that almost every discussion of reusability in this book also considers extendibility (leading to the definition of the term “modularity”, which covers both notions and provided the topic of the previous chapter). Whenever you start looking for answers to one of these quality requirements, you quickly encounter the other.

因此,这并不是偶然的现象,在本书中每次复用性的讨论也同时考虑了扩充性(术语"模块性的定义包括了这两个观念,在之前的章节中已介绍了).只要您开始寻找这两个品质需求中的某个时,您很快就会遇到另一个.

 

This duality between reuse and adaptation was also present in the earlier discussion of the Open-Closed principle, which pointed out that a successful software component must be usable as it stands (closed) while still adaptable (open).

在先前的开闭原则的讨论中,复用和改写之间的二元性也同时介绍了.这个讨论指出了一个成功的软件组件一定是一直可用的,既使处在修改(开放)的状态时也维持不变(关闭).

 

The search for the right notion of module, which occupies the rest of this chapter and the next few, may be characterized as a constant attempt to reconcile reusability and extendibility, closure and openness, constancy and change, satisfying today’s needs and trying to guess what tomorrow holds in store.

对模块的正确观念的研究,占用了本章的余下部分和下一个章的部分内容,这可以称为一个持续的尝试,用以调协复用性和扩充性,开放和关闭,恒定和变化,满足今天的需求和试着去猜测明天会发生什么.

 

4.6 FIVE REQUIREMENTS ON MODULE STRUCTURES

4.6 模块结构上的五个需求

 

How do we find module structures that will yield directly reusable components while preserving the possibility of adaptation?

我们如何找出一种模块结构,使其在直接地产生可复用组件的同时保留更改的可能性?

 

The table searching issue and the has routine pattern obtained for it on the previous page illustrate the stringent requirements that any solution will have to meet. We can use this example to analyze what it takes to go from a relatively vague recognition of commonality between software variants to an actual set of reusable modules. Such a study will reveal five general issues:

• Type Variation.

• Routine Grouping.

• Implementation Variation.

• Representation Independence.

• Factoring Out Common Behaviors.

在前页中的表查询议题和has例程模式阐明了任何解决方案都会遇到的迫切的需求.我们能使用这个例子来分析,从软件变体到一组实际的可复用模块之间的模糊不清的共通性.这种研究提出了五个通用的议题:

Ÿ           类型变化

Ÿ           例程分组

Ÿ           实现变化

Ÿ           表示法独立

Ÿ           合并通用行为

 

Type Variation

类型变化

 

The has routine pattern assumes a table containing objects of a type ELEMENT. A particular refinement might use a specific type, such as INTEGER or BANK_ACCOUNT, to apply the pattern to a table of integers or bank accounts.

has例程模式假定一个表包含了一个类型为ELEMENT的对象.一个特别的细化可以使用一个特定的类型,像是整型(INTEGER)BANK_ACCOUNT,在整数或银行帐户的表中应用这个模式.

 

But this is not satisfactory. A reusable searching module should be applicable to many different types of element, without requiring reusers to perform manual changes to the software text. In other words, we need a facility for describing type-parameterized modules, also known more concisely as generic modules. Genericity (the ability for modules to be generic) will turn out to be an important part of the object-oriented method an overview of the idea appears later in this chapter.

但是这并不够.一个可复用的查询模块应该可以应用到许多不同的元素类型中,不需要复用者对软件代码进行手工改变.换句话说,我们需要一个描述参数化类型的模块工具,也要更简要的了解泛化(generic)模块.泛型(泛化模块的能力)将会成为面向对象方法的一个重要部份;本章稍后会介绍这个概念.

 

Routine Grouping

例程分组

 

Even if it had been completely refined and parameterized by types, the has routine pattern would not be quite satisfactory as a reusable component. How you search a table depends on how it was created, how elements are inserted, how they are deleted. So a searching routine is not enough by itself as a unit or reuse. A self-sufficient reusable module would need to include a set of routines, one for each of the operations cited — creation, insertion, deletion, searching.

即使类型已经被完全地细化和参数化, has例程模式也不能完全满足于当作一个可复用组件.您如何查找一个表要依赖于它被建立的方式,元素被插入的方式和被删除的方式.因此,一个查询例程单独作为一个单元或复用并不足够.一个独立的可复用模块需要包括一系列的例程,其中一组是运算引用,如创建,插入,删除,查找.

 

This idea forms the basis for a form of module, the “package”, found in what may be called the encapsulation languages: Ada, Modula-2 and relatives. More on this below.

这种思想构成了一种模块形式-"软件包"的基础,可以在被称之为封装语言中发现它:Ada,Modula-2和类似的语言.更多的将在下面介绍.

 

Implementation Variation

实现变化

 

The has pattern is very general there is in practice, as we have seen, a wide variety of applicable data structures and algorithms. Such variety indeed that we cannot expect a single module to take care of all possibilities it would be enormous. We will need a family of modules to cover all the different implementations.

has模式非常通用;如同我们已经看到的,它是在实践中可以广泛适用的数据结构和算法.如此真正的多样性使我们不能够指望一个单一模块就能涵盖所有的可能性;否则它就会非常巨大.我们需要一个模块系列来包含所有不同的实现.

 

A general technique for producing and using reusable modules will have to support this notion of module family.

产生并使用可复用模块的通用技术必须支持这个模块系列的观念.

 

Representation Independence

表示独立

 

A general form of reusable module should enable clients to specify an operation without knowing how it is implemented. This requirement is called Representation Independence. Assume that a client module C from a certain application system — an asset management program, a compiler, a geographical information system¼ — needs to determine whether a certain element x appears in a certain table t (of investments, of language keywords, of cities). Representation independence means here the ability for C to obtain this information through a call such as

present := has (t, x)

without knowing what kind of table t is at the time of the call. C’s author should only need to know that t is a table of elements of a certain type, and that x denotes an object of that type. Whether t is a binary search tree, a hash table or a linked list is irrelevant for him he should be able to limit his concerns to asset management, compilation or geography. Selecting the appropriate search algorithm based on t’s implementation is the business of the table management module, and of no one else.

一个可复用模块的通用形式应该使客户端能够使用一个运算而不必知道它是如何实现的.这个需求称之为表示法独立.假设一个来自某个应用程序系统的客户端模块C-一个资产管理程序,一个编译器,一个地理信息系统-需要确定某个元素x是否出现在表t中(投资表,语言关键字表,城市表).在这里,表示法独立意谓着,通过如 present := has (t, x) 这样的调用C获得信息的能力,在调用的时候不需要知道表t的类型.C的作者应该只需要知道t是具有某种类型元素的一个表,而x表示那个类型的一个对象.是否t是一个二进制查询树,一个哈希表或一个链表对他来说无关紧要;他应该能够把他的重点放在资产管理,编译或地理学上.基于t的实现选择适当的查寻算法是表管理模块的事务,而和其它模块无关.

 

This requirement does not preclude letting clients choose a specific implementation when they create a data structure. But only one client will have to make this initial choice after that, none of the clients that perform searches on t should ever have to ask what exact kind of table it is. In particular, the client C containing the above call may have received t from one of its own clients (as an argument to a routine call) then for C the name t is just an abstract handle on a data structure whose details it may not be able to access.

当客户端创建一个数据结构的时候,这个需求不能排除让客户端选择一个特定的实现.但是只会有一个客户端不得不作出初始的选择;在那之后,在t上进行查询的客户端不再需要了解表的精确类型.特别地,包含上述调用的客户端C从它自己的客户端中可能已经接收了t(作为例程调用的参数);然后,对C来说,名字t只是一个数据结构上的抽象句柄,其细节不能够被访问.

 

You may view Representation Independence as an extension of the rule of Information Hiding, essential for smooth development of large systems: implementation decisions will often change, and clients should be protected. But Representation Independence goes further. Taken to its full consequences, it means protecting a module’s clients against changes not only during the project lifecycle but also during execution — a much smaller time frame! In the example, we want has to adapt itself automatically to the run-time form of table t, even if that form has changed since the last call.

您可以把表示法独立看成是信息隐藏规则的一个扩展,对大系统的平滑开发很有必要: 实现的结果将会经常被改变,而且客户端应该被保护.但是表示法独立更进一步.利用其全面的作用,这意味着保护模块的客户端免于变化,不只有在项目周期期间而且也在执行期间-一个更加小的时间范围! 在这个例子中,我们希望has对表t的运行时形式能自动地自适应,即使那种形式由于上一个调用后已经改变了.

 

Satisfying Representation Independence will also help us towards a related principle encountered in the discussion of modularity: Single Choice, which directed us to stay away from multi-branch control structures that discriminate among many variants, as in

满足表示法独立也将会帮助我们使用一项相关原则,这就是我们在模块性的讨论中遇到的: 单选(Single Choice),它指导我们避免在许多变体之间作出区分的多分支控制结构, 如

 

if t is an array managed by open hashing” then

“Apply open hashing search algorithm”

elseif t is a binary search tree” then

“Apply binary search tree traversal”

elseif

(etc.)

end

 

It would be equally unpleasant to have such a decision structure in the module itself (we cannot reasonably expect a table management module to know about all present and future variants) as to replicate it in every client. The solution is to hide the multi-branch choice completely from software developers, and have it performed automatically by the underlying run-time system. This will be the role of dynamic binding, a key component of the object-oriented approach, to be studied in the discussion of inheritance.

至于在每个客户端中重复它,在模块本身中有这样的一个选择结构会相当地令人不愉快(我们不能够期待一个表的管理模块知道所有的已有的和将来的变体). 解决方案要对软件开发者完全地隐藏多分支选择,而且内在的运行时系统会自动地完成这种选择.这将是动态绑定的任务,其是面向对象方式的一个关键组件,这会在继承的讨论中学习到.

 

Factoring Out Common Behaviors

合并通用行为

 

If Representation Independence reflects the client’s view of reusability — the ability to ignore internal implementation details and variants –, the last requirement, Factoring Out Common Behaviors, reflects the view of the supplier and, more generally, the view of developers of reusable classes. Their goal will be to take advantage of any commonality that may exist within a family or sub-family of implementations.

如果表示法独立反映了客户端复用性的观点-忽略内在的实现细节和变体的能力-那么最后一个需求,合并通用行为,则反映了供应者的观点,更通常的是可复用类的开发者的观点.他们的目标是要利用任何可能在一个实现系列或子系列里存在共通性.

 

The variety of implementations available in certain problem areas will usually demand, as noted, a solution based on a family of modules. Often the family is so large that it is natural to look for sub-families. In the table searching case a first attempt at classification might yield three broad sub-families:

如您所知,在特定问题领域中,有效实现的多样性通常要求一个基于模块系列的解决方案.这个系列常常是非常庞大的,以致于总是要借助于子系列.在表查询的情况中,第一次分类尝试就可能产生三个主要的子系列:

 

• Tables managed by some form of hash-coding scheme.

• Tables organized as trees of some kind.

• Tables managed sequentially.

Ÿ           由一些哈希码方案结构所处理的表

Ÿ           由几种树类型所组织的表

Ÿ           顺序处理

 

Each of these categories covers many variants, but it is usually possible to find significant commonality between these variants. Consider for example the family of sequential implementations — those in which items are kept and searched in the order of their original insertion.

这些种类的每一个都包括许多变体,但是在这些变体之间通常能找到显著的共通性.考虑一个顺序实现系列的例子-那些记录以最初插入的顺序被存储和查寻.

 

 


 

Possible representations for a sequential table include an array, a linked list and a file. But regardless of these differences, clients should be able, for any sequentially managed table, to examine the elements in sequence by moving a (fictitious) cursor indicating the position of the currently examined element. In this approach we may rewrite the searching routine for sequential tables as:

一个顺序表的表示法可能包括一个数组,一个链表和一个文件.但是不考虑这些不同,在任何顺序处理的表中,客户端应该能够通过移动一个(虚拟的)光标(cursor)来依次检查元素,这个光标指示了当前检查元素的位置.在这方式中,我们可以对顺序表重写查询例程:

 

has (t: SEQUENTIAL_TABLE x: ELEMENT): BOOLEAN is

-- Is there an occurrence of x in t?

do

from start until

after or else found (x)

loop

forth

end

Result := not after

end

 

This form relies on four routines which any sequential table implementation will be able to provide:

start, a command to move the cursor to the first element if any.

forth, a command to advance the cursor by one position. (Support for forth is of course one of the prime characteristics of a sequential table implementation.)

after, a boolean-valued query to determine if the cursor has moved past the last element this will be true after a start if the table was empty.

found (x), a boolean-valued query to determine if the element at cursor position has value x.

这段结构使用了四个例程,任何的顺序表实现都要能够提供:

·        start,一个移动光标至第一个元素的命令

·        forth ,一个移动光标前进至下一个元素的命令(支持forth当然是一个顺序表实现的首要特性)

·       
after,一个布尔值,其值决定于是否移动光标经过了最后一条元素.如果表是空的,那么在start之后其值为真.

·        found (x),一个布尔值,其值决定于是否光标所在位置的元素含有值x.

 

 

 

At first sight, the routine text for has at the bottom of the preceding page resembles the general routine pattern used at the beginning of this discussion, which covered searching in any table (not just sequential). But the new form is not a routine pattern any more it is a true routine, expressed in a directly executable notation (the notation used to illustrate object-oriented concepts in part C of this book). Given appropriate implementations for the four operations start, forth, after and found which it calls, you can compile and execute the latest form of has.

乍一看,在前一页的has例程代码好似最初讨论所采用的通用例程模式,其复盖了在任何表中的查询(不仅仅是顺序表).但是新的形式不再是一个例程模式;它是一个真实的例程,直接地表示了可执行符号(这些符号在本书的C部份用来描述面向对象的概念).对所调用的四个运算start, forth, afterfound,给定适当的实现后,您就能编译而且执行has最后的形式.

 

For each possible sequential table representation you will need a representation for the cursor. Three example representations are by an array, a linked list and a file.

对于每个可能的顺序表表示法,您都会需要一个光标的表示法.一个数组,一个链表和一个文件是表示法的三个例子.

 

The first uses an array of capacity items, the table occupying positions 1 to count. Then you may represent the cursor simply as an integer index ranging from 1 to count + 1. (The last value is needed to represent a cursor that has moved “after” the last item.)


第一个使用了一个 capacity项的数组,表的位置是从1count. 您可以用index简单的表示光标,它是一个从1到count + 1的整数.(最后的整数值表示移动光标到最后一条之后).

 

 

The second representation uses a linked list, where the first cell is accessible through a reference first_cell and each cell is linked to the next one through a reference right. Then you may represent the cursor as a reference cursor.

第二个表示法使用了一个链表,通过一个引用first_cell访问第一个单元,并且每一个单元通过引用right链接到下一个.您可以用引用cursor来表示光标.

 


The third representation uses a sequential file, in which the cursor simply represents the current reading position.

第三个表示法使用一个顺序文件,其光标仅仅表示当前的位置.

The implementation of the four low-level operations start, forth, after and found will be different for each variant. The following table gives the implementation in each case. (The notation t @ i denotes the i-th element of array t, which would be written t [i] in Pascal or C Void denotes a void reference the Pascal notation f­, for a file f, denotes the element at the current file reading position.)

这四个底层的操作start, forth, afterfound,其实现对每一个变体来说都是不同的.下表给出了它们的实现.(符号t @ i表示数组ti个元素,PascalC中写作t [i]Void表示一个空引用;对于文件fPascal符号f­指示了在当前文件中读位置上的元素.)

 

 


The challenge of reusability here is to avoid unneeded duplication of software by taking advantage of the commonality between variants. If identical or near-identical fragments appear in different modules, it will be difficult to guarantee their integrity and to ensure that changes or corrections get propagated to all the needed places once again, configuration management problems may follow.

在这里,复用性的挑战是要利用在变体之间的共通性来避免不需要的软件重复.如果相同或几乎相同的片段出现在不同的模块中,那么这将很难保证它们之间的完整性,也不能确保变化或校正会涉及到所有可能的地方;再一次,配置管理问题也将随之而来.

 

All sequential table variants share the has function, differing only by their implementation of the four lower-level operations. A satisfactory solution to the reusability problem must include the text of has in only one place, somehow associated with the general notion of sequential table independently of any choice of representation. To describe a new variant, you should not have to worry about has any more all you will need to do is to provide the appropriae versions of start, forth, after and found.

所有的顺序表变体共享has函数,只是四个底层运算的实现不同而已.对复用性问题而言,满意的解决方案必须只在一处包含有has代码,以某种方式与顺序表的通用观念关联,这些通用的观念独立于表示法的任何一种选择.为了要描述一个新的变体,您应该不再需要考虑has;您所需要的只是提供start,forth,afterfound合适的版本.

阅读更多
上一篇面向对象软件构造(第2版)-第4章 复用性方法Approaches to reusability (上)
下一篇面向对象软件构造(第2版)-第4章 复用性方法Approaches to reusability (下)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭