《软件工程》第7章设计和实现

    软件设计和实现是软件工程过程中的一个阶段,在此阶段中会开发一个可执行的软件系统。对于一些简单的系统,软件工程意味着软件设计和实现,而所有其他软件工程活动都被合并到这个过程中了。然而,对于大型系统而言,软件设计和实现只是一系列软件工程过程中的一个。

    软件设计和实现活动一般总存在重叠。软件设计是一个创造性的活动,在此活动中需要基于客户需求识别软件构件及其关系。实现是将设计实现为一个程序的过程。有时候会有一个独立的设计阶段,其中的设计会被建模和文档化。而其他时候设计会存在于程序员的脑海中,或只是在白板或纸上大致地用草图画一下。设计是关于如何解决一个问题,因此总是有一个设计过程。然而,并不总是有必要或者适合用UML或其他设计描述语言详细描述设计。

    设计和实现密切联系在一起,考虑一个设计时通常都应该将实现问题考虑进来。如第3章中所提到的,敏捷方法通常是在非正式的设计草图基础上工作的,设计决策都留给了程序员。

    在一个软件项目的早期阶段必须做出的一个最重要的决策是,确定自己构建还是购买应用软件。采用购买按照用户需求进行适应性调整和裁剪的成品应用系统的方法通常比传统开发一个新系统更加便宜也更快。

    当通过复用一个成品软件产品开发一个应用系统时,设计过程关注如何配置该系统产品以满足应用需求,而不需要开发系统的设计模型。

§7.1使用UML的面向对象设计

    一个面向对象系统由相互交互的对象组成,这些对象保持自己的本地状态同时基于状态提供相应的操作。状态的表示是私有的,无法从该对象的外部直接访问。面向对象设计过程包括设计对象类以及这些类之间的关系。这些类定义了系统中的对象以及它们的交互。当设计被实现为执行程序时,对象会在这些类定义的基础上被动态创建出来。

    对象同时包括数据以及操纵这些数据的操作。因此,它们可以作为独立的实体进行理解和修改。改变一个对象的实现或者增加服务不应该影响其他系统对象。因为对象与事务相关联,现实世界实体和它们在系统中的控制对象之间经常存在清晰的映射。这改进了设计的可理解性,因此也有利于可维护性。

    为了开发一个系统设计(从概念到详细的面向对象设计),你需要:

    1.理解并定义上下文以及与系统外部的交互;

    2.设计系统体系结构;

    3.识别系统中的主要对象;

    4.开发设计模型;

    5.刻画接口。

    像所有创造性活动一样,设计不是一个清晰的顺序性过程。在开发一个设计的过程中会获得想法,提出解决方案,再逐步求精。当出现问题的时候,不可避免地需要进行回溯重新尝试。有时候要详细探索各种选项看它们是否奏效;而其他时候则会忽略细节指导过程中的后期。有时候使用UML等建模表示法来精确地阐明设计的各个方面;而其他时候,则可以以非正式的方式使用一些表示法来激发讨论。

    7.1.1系统上下文和交互

    任何软件设计过程的第一个阶段都是理解所设计的软件与它的外部环境之间的关系。这是很重要的,因为可以据此决定如何提供所需要的系统功能,以及如何对系统进行组织从而与环境进行通信。

    设定系统边界帮助开发人员决定哪些特征在所设计的系统中实现,以及哪些特征在其他相关联的系统中实现。系统上下文模型和交互模型所呈现的关于系统及其环境之间关系的视图是互补的。

    1.系统上下文模型是一种结构化模型,其中展示了所开发的系统的环境中的其他系统。

    2.交互模型是一种动态模型,其中显示系统在使用时如何与环境进行交互。

    一个系统的上下文模型可以使用关联来表示。关联只是显示关联中所包含的实体之间存在某些关系。可以使用简单的框图来描述系统的环境,显示系统中的实体以及它们之间的关联关系。

    当对系统与其环境之间的交互进行建模时,应当使用一种不包含太多细节的抽象的方法。其中一种方法是使用用况模型。每种可能的交互都被表示为一个椭圆并进行命名,参与交互的外部实体由一个线条人形来表示。

    这些用况中的每一个都应当使用结构化自然语言进行描述。这有助于设计人员识别系统中的对象并让他们理解系统意图要做什么。

    7.1.2体系结构设计

    软件系统和系统环境之间的交互定义好之后,就可以以此为基础来设计系统体系结构。当然,设计人员需要将这一知识与自身关于体系结构设计原则的通用知识以及更加详细的领域知识相结合。需要识别构成系统的主要构件以及它们之间的交互,然后要使用一种体系结构模式(例如,分层或客户-服务器模型)来设计系统的组织结构。

    “监听器模型”是一种广泛使用的分布式系统体系结构风格,当通信子系统收到一个控制命令(例如关闭)时,其他每个子系统也将获得该命令,这些子系统接收者会执行命令(例如,按照正确的方式关闭自身)。这一体系结构的关键优点是很容易支持不同的子系统配置,因为一条消息的发送者不需要指定接收该消息的特定子系统。

    7.1.3对象类识别

    在设计过程的这个阶段之前,关于你所设计的系统中所包含的重要对象你应该已经有了一些想法。随着你对设计的理解进一步加深,要对这些关于系统对象的想法进行精化。用况描述帮助你识别系统中的对象和操作。通常你还会需要一个高层的系统对象或者用来封装用况中所定义的系统交互的对象。脑海中有了这些对象之后,便可以开始识别系统中的通用对象类。

    随着20世纪80年代的面向对象设计的发展,出现了不同的识别面向对象系统中对象类的方法,例如:

    1.对所要构建的系统的自然语言描述进行语法分析。

    2.使用应用领域中有形的实体或事物、角色、事件、交互、位置、组织单元等。

    3.使用一种基于场景的分析方法,其中依次识别并分析系统使用的各种场景。分析每个场景时,负责分析的团队必须识别所需要的对象、属性以及操作。

    在实践中,你必须使用多种知识源来发现对象类。最初从非正式的系统描述中所识别出的对象类、属性和操作可以成为设计的起点。接下来,来自应用领域知识或场景分析的信息可以用于精化和扩展初始的对象。这些信息可以从需求文档、与用户的讨论或者对现有系统的分析中收集到。除了表示系统外部实体的对象,还必须设计出用于提供通用服务(例如,搜索和正确性检查)的“实现对象”。

    在这个设计过程阶段中,你应当关注对象自身,不需要考虑这些对象要如何实现。一旦识别出这些对象后,可以再对这些对象设计进行精化。你会发现共性的特征,然后为系统设计继承层次。

    7.1.4设计模型

    设计或系统模型,展示了一个系统中的对象或者对象类,还展示了这些实体之间的关联和关系。这些模型是系统需求和系统实现之间的桥梁。它们必须是抽象的,以使得不必要的细节不会隐藏它们和系统需求之间的关系。然而,模型还必须包含足够的细节,以使得程序员可以做出实现决策。

    一个设计模型所需要的详细程度取决于开发人员所使用的设计过程。由于需求工程师、设计人员和程序员之间存在密切的联系,抽象模型可能就是所有所需要的东西。特定的设计决策可能会在系统实现时做出,其中的问题通过非正式的讨论来解决。与之相似,如果使用敏捷开发,在一个白板上画出概要的设计模型可能就足以提供所有所需要的信息。

    然而,如果使用的是一个基于计划的开发过程,你可能需要更详细的模型。如果需求工程师、设计人员和程序员之间仅有间接联系(例如,一个系统在一个组织的某个部门进行设计但在其他地方实现),那么需要详细的设计描述以便于沟通。此时要使用从高层的抽象模型中派生出来的详细模型,从而使所有的团队成员对于设计有一个共同的理解。

    因此,设计过程中的一个重要的步骤是决定所需要的设计模型以及这些模型所需要的详细程度。这取决于所开发的系统的类型。一个顺序性的数据处理系统与一个嵌入式实时系统就很不一样,因此你需要使用不同类型的设计模型。UML支持13种不同类型的模型,但是这些模型并没有得到广泛使用。尽量减少所产生的模型的数量可以降低设计的成本以及完成设计过程所需的时间。

    当使用UML来开发一个设计时,应当开发以下两类设计模型:

    1.结构模型,使用静态类及其关系描述系统的静态结构。这个阶段需要描述的重要的关系类型包括泛化(继承)关系、使用/被使用关系、组合关系。

    2.动态模型,描述了系统的动态结构并展示了所期望的系统对象之间的运行时交互。可以描述的交互包括对象发出的请求的序列以及由这些对象交互所触发的状态变化。

    以下3种UML模型对于增加用况和体系结构模型的细节特别有用。

    1.子系统模型,展示了如何对对象进行逻辑分组以构成内聚的子系统。这些可以使用一种类图的形式来表示,其中每个子系统表示为一个包含对象的包。子系统模型是结构模型。

    2.顺序模型,展示了对象的交互序列。这些可以使用UML顺序图或协作图来表示。顺序模型是动态模型。

    3.状态机模型,展示了对象如何在事件响应中改变自己的状态。这些可以使用UML状态图来表示。状态机模型是动态模型。

    子系统模型是一种有用的静态模型,展示了如何将一个设计组织为逻辑上相关的对象组。除了子系统模型,还可以设计详细的对象模型,展示系统中的对象以及它们的关联关系(继承、泛化、聚集等)。然而,进行太多的建模存在危险。不应当在此时做出关于实现的详细决策,这些决策最好留到系统实现时再考虑。

    顺序模型是动态模型,描述了每个交互模式下所发生的对象交互序列。当描述一个设计时,应当为每个有意义的交互产生一个序列模型。如果已经开发了一个用况模型,那么每一个所识别出的用况都应该有一个顺序模型。

     下图所示是一个顺序模型的例子,表示为一个UML顺序图。这个图展示了当一个外部系统向气象站请求汇总数据时发生的交互序列。顺序图要从上到下阅读。

    顺序图被用于一组对象的组合行为进行建模,但是你可能还想按照消息或事件对一个对象或子系统的行为进行总结。为此,可以使用一个状态机模型来展示对象实例如何根据所收到消息改变状态。

    下图所示是一个气象站系统的状态图,其中展示了该系统如何响应各种不同的服务请求。

    然而并不是系统中的所有的对象都需要一个状态图。一个系统中的许多系统对象都很简单,它们的操作可以很容易地在不使用状态模型的情况下进行描述。

    7.1.5接口规格说明

    设计过程的一个重要部分是设计中所包含的构件之间的接口的规格说明。你需要刻画接口的规格说明,以使得对象和子系统并行进行设计。一旦确定了一个接口的规格说明,其他对象的开发者可以假设该接口将会被实现。

    接口设计关注刻画一个对象或一组对象的接口的细节。这意味着要定义由一个对象或者一组对象所提供服务的型构(signature)和语义。接口在UML中可以用类图一样的表示法来刻画。然而,接口没有属性部分,而名称部分应当包含UML构造型(sterotype)《interface》。接口的语义可以使用对象约束语言(Object Constraint Language, OCL)来定义。

    接口设计不应当在一个接口设计中包含数据表示的细节,因为一个接口规格说明中并不会定义属性。然而,接口设计应当包含访问和更新数据的操作。由于数据表示被隐藏了,因此可以在不影响使用该数据的对象的情况下很容易地修改数据表示。这样产生的设计从内在上讲可以具有更好的可维护性。与之相对应的,一个对象模型中的属性通常都应当被暴露出来,因为这是描述对象的基本特性的一种最清楚的方式。

    对象与接口之间并不是简单的一对一关系。同一对象可以有多个接口,其中每个接口都是一个对于该对象所提供的方法的视角。同样地,一组对象也可以通过单个接口一起访问到。

§7.2设计模式

    模式是一种对于问题及其解决方案的本质的描述,从而使得解决方案可以在不同的环境中进行复用。模式不是一种详细的规格说明,应当将模式理解为一种对于逐渐积累的智慧和经验的描述,一种对某个共性问题的经过成功尝试的解决方案。

    模式和模式语言是描述最佳实践、好的设计的方式,其中捕捉了相关的经验,从而使其他人复用这些经验成为可能。

    模式对于面向对象软件设计已经产生了巨大的影响。除了作为针对共性问题的经过验证的解决方案之外,模式还已经成为一种谈论设计的词汇表。因此,可以通过描述是你所使用的模式来解释你的设计。

    模式是一种复用其他设计者的知识和经验的方式。设计模式通常与面向对象设计相关联。广泛发布的模式经常依赖于继承和多态等对象特征来提供通用性。然而,在模式中封装经验这一通用原则可以同样适用于任何类型的软件设计。例如,你可以拥有针对实例化可复用的应用系统的配置模式。

    设计模式的4个基本元素:

    1.一个名字,作为对模式的有意义的参照;

    2.一个问题域的描述,解释了该模式何时适用;

    3.一个对于设计解决方案的各个部分、它们之间的关系以及它们的职责的描述。这并不是一个具体的设计描述,这是一个设计解决方案的模板,可以以不同的方式进行实例化。模板经常可以通过图形化的方式进行表达,展示解决方案中的对象和对象类之间的关系。

    4.一个对效果的陈述——应用该模式的结果以及权衡。这有助于设计者理解一个模式是否可以用于某个特定的情形中。

    问题描述可以被分解为动机(对于模式为什么有用的一种描述)和实用性(对于该模式可以使用的情形的描述)。在解决方案的描述下,刻画了模式结构、参与者、协作以及实现。

    为了展示模式的描述,以观察者(Observer)模式作为例子进行介绍:

观察者模式

模式名称:观察者

描述:将一个对象的状态的呈现与对象本身分开,允许为对象提供不同的呈现方式。当对象状态变化时,所有的呈现都会自动得到通知并进行更新以反映变化。

问题描述:在很多情况下你都必须为状态信息提供多种呈现方式,例如,一个图形化呈现方式和一个表格呈现方式。这些呈现方式再对信息进行规格说明时并不都是已知的。所有不同的呈现方式都应该支持交互,在状态发生变化时所有呈现都必须更新。

    这个模式的使用情形是,状态信息需要不止一种呈现方式,并且维护状态信息的对象不需要知道所使用的特定的呈现格式。

解决方案描述:解决方案包括两个抽象对象Subject(主题,即被观察者)和Object(观察者),以及两个继承了相关抽象对象属性的具体对象ConcreteSubject(具体主题)和ConcreteObserver(具体观察者)。抽象对象包括适用于所有情形的通用操作。需要呈现的状态在ConcreteSubject中进行维护,该对象继承了Subject的操作从而允许该对象增加和移除观察者(每个观察者对应一种呈现方式)以及在状态发生变化时发出通知。

ConcreteObserver维护了ConcreteSubject状态的一份拷贝,并且实现了Observer的Update()接口,该接口允许这些拷贝能够被同步更新。ConcreteObserver自动呈现状态并在任何时候当状态更新时自动反映变化。

该模式的UML模型如下图所示。

效果:主题对象只知道抽象的观察者对象,而不知道具体类的细节。因此,这些对象之间的耦合被最小化了。由于缺少这些知识,提高呈现性能优化可能无法实现。对主题对象的变化可能导致生成与之相关的针对观察者的一组更新,而其中一些可能并没有必要。

    这个模型可以用于需要以不同的方式展示一个对象的状态的情形。该模式将必须展示的对象与它的不同展示形式分离开了。

    为了在设计中使用模式,你需要认识到你所面对的任何设计问题都可能会有一个与之相关联、可以应用的模式。

【例】

    1.向多个对象告知一些其他对象的状态发生了变化(观察者模式)。

    2.整理面向一些相关的且经常是增量地开发出来的对象的接口(门面模式)。

    3.为一个合集(collection)中的元素提供一种标准的访问方式,不用考虑合集是如何实现的(迭代器模式)。

    4.允许在运行时扩展一个已有的类的功能(装饰者模式)。

    模式支持高层的概念复用。当试图复用可执行的构件时,不可避免地会受到这些构件的实现中所做出的详细设计决策的约束和限制。这些决策范围很广,从已经用于实现这些构件的特定算法到构件接口中的对象和类型。当这些设计决策与需求相冲突时,可能无法复用该构件了,或者会在复用中引入问题。使用模式意味着对思想进行复用,但可以对实现进行调整以适应正在开发的系统。

    当开始设计一个系统时,很难提前知道是否会需要某个特定的模式。因此,在设计过程中使用模式经常要经过开发设计、体验问题、然后认识到可以使用某个模式的过程。

    模式是伟大的思想,但是为了有效地使用它们还需要一些软件设计经验。你必须能够认识到一个模式可以被应用的情形。没有经验的程序员,即使他们已经读过模式的书,也总是会发现很难决定是否可以复用某个模式或者是否需要开发一个特殊目的的解决方案。

§7.3实现问题

    软件工程包括软件开发中所包含的所有活动,从最初的系统需求直到部署后的系统维护和管理。这个过程中的一个关键阶段当然是系统实现,其中会创建软件的一个可执行版本。实现可能会包括:使用高层或底层编程语言开发程序,或者对通用的成品系统进行裁剪和适配以满足一个组织的特定需求。

    7.3.1复用

    从20世纪60年代到20世纪90年代,大多数新软件都是从头开始开发的,一般都是通过使用某种高级编程语言编写所有代码。唯一显著的软件复用是对编程语言库中的功能和对象的复用。然而,成本和进度压力使这一方法越来越不可行,特别是对于商业系统和基于互联 的系统。因此,基于复用已有软件的开发方法现在已经成为许多不同类型系统开发的基本准则。基于复用的方法现在已经在很多领域得到广泛使用,包括所有类型的基于Web的系统、科学软件,以及越来越多的嵌入式系统软件。

    软件复用可以在多个不同的级别上发生,如下图所示。

    1.抽象级。在这个级别上,并不是直接复用软件而是在软件的设计中使用关于一些成功的抽象的知识。

    2.对象级。在这个级别上,直接复用来自库中的对象而不是自己写代码。

    3.构件级。构件是对象和对象类的合集,它们一起运行以提供相关的功能和服务。

    4.系统级。在这个级别上,复用整个应用系统。

    通过复用已有的软件,可以更快地开发新系统,而且风险和成本更低。由于被复用的软件已经在其他应用中得到了验证,它们应该会比新软件更可靠。然而,还是会有一些与复用相关的成本。

    1.寻找可复用的软件以及评价其是否满足需要所花费的时间成本。你可能还必须对软件进行测试以确保它可以在你的环境中工作,特别是该环境与软件的开发环境不一样的时候。

    2.在适用的情况下,购买可复用软件的成本。对于大型的成品系统,这些成本可能会很高。

    3.适配和配置可复用软件构件或系统以反映正在开发的系统的需求的成本。

    如何复用已有的知识和软件应当是在开始一个软件开发项目时要考虑的第一件事情。应当在详细设计软件之前考虑复用的可能性,因为你可能要对自己的设计进行调整以适应对已有软件资产的复用。

    7.3.2配置管理

    在软件开发中,变化总是在不断发生,因此变更管理绝对是很重要的。当多个人参与软件系统开发时,必须确保团队成员不会干扰其他人的工作。也就是说,如果两个人都在开发一个构件,那么他们的修改必须进行协调,否则一个程序员所做的修改可能会覆盖其他人的工作。此外,还要确保每个人都可以访问到软件构件的最新版本,否则开发人员可能要重做已经做过的工作。当一个系统的新版本出现问题时,必须能够回到该系统或构件此前的一个可以工作的版本上。

    顾名思义,配置管理是管理一个不断变化的软件系统的一般过程。配置管理的目的是支持系统集成过程以使所有的开发者都可以以一种受控的方式访问项目的代码和文档,找出代码和文档做了哪些修改,以及对构件进行编译和链接来创建一个系统。如下图所示,有以下4种基本的配置管理活动。

    1.版本管理,为保持对软件构件的不同版本的追踪提供支持。版本管理系统包括一些手段来协调多个程序员之间的开发。这些方法会阻止一个开发人员覆盖别人提交到系统中的代码。

    2.系统集成,为帮助开发人员定义用于创建每一个系统版本的构件的版本提供支持。然后,这一描述被用于通过编译和链接所需要的构件来自动构建一个系统。

    3.问题追踪,为用户 告bug和其他问题提供支持,为所有开发人员查看谁在处理这些问题以及问题何时被修复提供支持。

    4.问题追踪,会向客户发布一个软件系统的新版本。发布管理关注规划新发布的功能并为了分发而对软件进行组织。

    软件配置工具支持以上每一个活动。这些工具通常安装在一个集成开发环境中。版本管理可以使用一个版本管理系统来支持,例如Subversion或者Git,它们可以支持多点、多团队的开发。系统集成支持可以被构建到语言里面或者依赖于一个独立的工具集(例如GNU的构建系统)。bug追踪(bug tracking)或问题追踪(issue tracking)系统(例如Bugzilla)用于 告bug和其他问题,并且对它们是否被修复保持追踪。

    7.3.3宿主机—目标机开发

    大多数专业化的软件开发都是基于宿主机—目标机模型的。软件在一台计算机(宿主机)上开发,但是在另一台机器(目标机)上运行;更泛化一些的话,可以说一个开发平台(宿主机)和一个执行平台(目标机)。一个平台不仅仅是硬件,还包括所安装的操作系统和其他支持性的软件(例如数据库管理系统);或者对于开发平台而言,一个交互式的开发环境。

    有时候,开放平台和执行平台是一样的,这使软件的开发和测试可以在同一台机器上进行。然而,特别是对于嵌入式系统和移动系统,开发和执行平台是不一样的,需要将所开发的软件移动到执行平台上进行测试,或者在开发机上运行一个模拟器。

    模拟器经常在开发嵌入式系统时使用,对硬件设备(例如传感器)以及系统将被部署的环境中的事件进行模拟。模拟器加快了嵌入式系统的开发过程,因为每个开发人员都可以有自己的执行平台,而不需要将软件下载到目标硬件上。然而,模拟器的开发很昂贵,因此可用的模拟器通常都是那些针对最流行的硬件体系结构的。

    如果目标系统已经安装了需要使用的中间件或其他软件,那么要能够使用这些软件来测试系统。有时候在开发机上安装这些软件是不现实的,即使开发机和目标平台是一样的,也可能因为许可证的限制而无法实现这一目的。如果是这种情况,那么需要将所开发的代码转移到执行平台上,从而对系统进行测试。

    软件开发平台应当提供一系列工具来支持软件工程过程。这些可能会包括:

    2.一个语言调试系统;

    4.可以自动在程序的新版本上运行一组测试的测试工具,例如JUnit;

    5.支持重构和程序可视化的工具;

    6.管理源代码版本以及集成和构建系统的配置管理工具。

    除了这些标准化的工具,开发系统还可以提供更加专业的工具,例如静态分析器。通常,面向团队的开发环境还会包括一个运行变更和配置管理系统的共享服务器,还可能会有一个支持需求管理的系统。

    软件开发工具现在通常会安装在一个集成开发环境中(Intergrated Development Environment,IDE)。一个集成开发环境是一组位于一些公共框架和用户界面中的支持软件开发的不同方面的软件工具。一般而言,集成开发环境都是支持使用特定编程语言(例如Java)的开发。针对特定语言的集成开发环境可以是特别开发的,也可以在通用集成开发环境基础上加入特定的语言支持工具。

    一个通用的集成开发环境是一个为所开发的软件提供数据管理设施以及允许各种工具一起工作的集成机制的框架,可以容纳各种软件工具。最广为人知的通用集成开发环境是Eclipse环境。这个环境基于一个插件体系结构,从而使其可以面向不同的语言(例如Java)和应用领域进行定制。因此,你可以安装Eclipse,并且通过增加插件来按照自己的特定目的对其进行裁剪。

    作为开发过程的一部分,需要针对所开发的软件将如何在目标平台上部署做出决策。这对于嵌入式系统是很直观的,其中目标机通常是单台计算机。然而,对于分布式系统而言,需要决定相关构件部署在哪些特定的平台上。在做出这一决策时必须考虑如下问题。

    1.一个构件的硬件和软件需求。如果一个构件是为一个特定的硬件体系结构而设计的,或者依赖于其他一些软件系统,那么很明显该构件要被部署到提供所需要的硬件和软件支持的平台上。

    2.系统的可用性需求。高可用性的系统可能要求将构件部署到多个平台上,这意味着如果发生平台失效,那么该构件的其他实现是可用的。

    3.构件通信。如果有许多构件间通信,那么最好将这些构件部署在同一平台上或者部署在物理上相互接近的多个平台上。这样做降低了通信延迟,即一个消息由一个构件发出到另一个构件收到消息之间的延迟。

    可以使用UML部署图来描述你对于硬件和软件部署的决策,其中可以显示软件构件如何分布在不同的硬件平台之上。

    如果你正在开发一个嵌入式系统,那么你可能不得不考虑目标机的特性,例如,它的物理大小、电量、对于传感器事件的实时响应要求、效用的物理特性以及它的实时操作系统。

§7.4开源开发

    开源开发是一种软件开发方法,其中软件系统的源代码被公开并邀请志愿者参加开发过程。开源开发源于自由软件基金会,他们主张源代码不应该是私有的,而应该总是面向用户开放,使他们可以按照自己的意愿检查并修改代码。其中有一个假设,代码将由一个小的核心小组而不是代码的用户进行控制和开发。

    开源软件通过使用互联 来招募更大规模的志愿者开发人员扩展了这一思想。他们中的许多人本身也是代码的用户。至少在原则上,一个开源项目的任何贡献者都可以 告和修复bug,并提出新的特征和功能建议。然而,在实践中,成功的开源系统仍然依赖于一个核心开发人员小组来控制软件的变更。

    开源软件是互联 和软件工程的支柱。获取开源软件通常很便宜甚至是免费的,你通常可以免费下载开源软件。然而,如果想获得文档和相应的支持,那么你可能必须要为此付费,但是成本通常相当低。使用开源产品的另一个关键的优势是广泛使用的开源系统非常稳定。这些系统有大量用户自愿修复软件中的问题,而不是把这些问题 告给开发者并等待系统新的发布版本。bug的发现和修复通常要比私有软件要快。

    对于参与软件开发的公司而言,有两个关于开源的问题是必须要考虑的。

    1.正在开发的产品应该利用开源构件吗p>

    对于这些问题的回答取决于所开发的软件的类型以及开发团队的背景和经验。如果正在开发一个用于销售的软件产品,那么上市时间和降低成本是很重要的。如果正在一个存在可用的高质量开源系统的领域中开发软件,那么可以通过使用这些系统来节省时间和费用。然而,如果你正在针对一组特定的组织需求开发软件,那么使用开源构件可能不是一个可行的选项。你可能必须要将你的软件和已有的与可用的开源系统不兼容的系统相集成。然而,即使这样,修改开源系统也比重新开放所需要的功能更快和更便宜。

    许多软件公司现在都在使用开源方法来开发,特别是针对专业的系统。他们的业务模型并不依赖于销售软件产品,而是提供对于该产品的服务。他们认为将开源 区纳入进来会使软件开发更快同时更加便宜,并且将为该软件创造一个用户 区。

    一些公司认为开源方法会将机密的业务知识透露给他们的竞争对手,因此不愿意采用这一开发模型。然而,如果你在一个小公司工作并将自己的软件开源,那么你可以请客户放心,因为如果你的公司歇业了,那么他们可以自己支持该软件。

    发布一个系统的源代码并不意味着来自更大范围内的 区的人们将要帮助进行开发。大多数成功的开源产品都是平台产品而不是应用系统。可能对专业的应用系统感兴趣的开发者数量有限。让一个软件系统开源并不能够保证 区的参与度。

    7.4.1开源许可证

    虽然开源软件开发的一个基本原则是,源代码应当是免费提供的,但是这并不意味着任何人都可以随心所欲地处置这些代码。从法律意义上讲,代码的开发者拥有代码。他们可以通过在一个开源软件许可证中包含法律约束条件来对代码如何使用加以限制。一些开源开发者认为如果一个开源构件被用于开发一个新系统,那么该系统也应当是开源的。其他人则愿意让别人在没有限制的情况下使用他们的代码。所开发的系统可以是私有的并作为闭源系统出售。

    大多数开源许可证都是以下3个通用模型中某一个的变体。

    1.自由软件基金会(GNU)通用公共许可证(General Public License,GPL)。这是一个所谓的互惠许可证,可以简单理解为,如果你使用GPL许可证下的开源软件,那么你必须让你的软件开源。

    2.自由软件基金会(GNU)宽通用公共许可证(Lesser General Public License,LGPL)。这是GPL许可证的一个变体,按照该许可证你可以编写链接到开源代码的构件而不用发布这些构件的源代码。但是,如果你修改了受许可证保护的构件,那么你必须将其发布作为开源软件。

    3.伯克利标准分发(Berkley Standard Distribution,BSD)许可证。这是一个单向的许可证,意味着你没有责任重新发布任何对于开源代码所做出的修改。你可以在所销售的私有系统中包含这些代码。如果你使用了开源构件,你必须承认这些代码最初的创造者。MIT许可证是BSD许可证的一个变体,条款相似。

    许可证的问题很重要,因为如果你在一个软件产品中使用开源软件,那么你可能会被强制要求服从许可证条款来使你自己的产品开源。如果你试图销售自己的软件,你可能希望对其保密。这意味着你可能会希望避免在开发中使用GPL许可证的开源软件。

    如果你在构造运行在开源平台上的软件,但是并没有复用开源构件,那么许可证不是个问题。然而,如果你将开源软件嵌入你的软件中,那么你需要建立相应的过程和数据库来保持对已经使用的开源代码及其许可证条件的追踪。

    1.建立一个系统来维护关于所下载和使用的开源构件的信息。你必须针对每一个构件保存一个在使用构件时有效的许可证的副本。

    2.了解不同类型的许可证,并理解一个构件在使用前是如何确定许可证的。你可能会决定在某个系统中使用一个构件而不在另一个系统中使用它,因为你计划以不同的方式使用这些系统。

    3.了解构件的演化路径。你需要知道一点关于开发构件的开源项目的事情以理解这些构件未来会如何变化。

    4.进行关于开源软件的教育。仅仅建立规程来确保符合许可证条款是不够的,还需要对开发人员进行关于开源软件以及开源许可证的教育。

    5.建立审计系统。处于严格的交付期限压力下的开发人员可能会试图违反许可证条款。如果可能的话,应当使用软件来侦测违反许可证条款的情况并进行阻止。

    6.参与开源 区。如果你依赖于开源产品,那么你应当参与相关的 区并帮助支持他们的开发。

    开源开发方法是几种软件商业模型之一。在这种模型中,公司发布他们的软件的源代码并且提供收费的附加服务以及与此相关的建议。他们还可以销售基于云的软件服务,对于那些不具有管理自己的开源系统以及系统的专业版本的用户来说,这是一种很有吸引力的选项。因此,开源很有希望在开发和分发软件方面发挥越来越大的作用。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年5月4日
下一篇 2020年5月4日

相关推荐