软件接口设计指南
软件接口设计指南

软件接口设计指南拟制人日期审核人日期批准人日期目录1目的 (1)2适用围 (1)3参考文件 (1)4定义和缩写 (1)5规定 (1)5.1JAVA接口设计方法 (1)5.2C++接口设计方法 (5)5.3接口设计对软件性能的影响 (7)5.4面向对象设计中,接口设计的一般原则 (10)6附件 (10)1目的为大家在进行软件接口设计时提供一些指导,以帮助大家更好的理解软件接口设计的方法和原则。
2适用围适用于公司软件开发的接口设计过程。
3参考文件本过程文件中的过程裁剪应依据《组织标准过程裁剪指南》的规定。
4定义和缩写本过程文件的编写依据是美国软件工程研究院(SEI)的集成成熟度模型软件分支1.2版本(CMMI-DEV V1.2)。
5规定5.1JAVA接口设计方法我们在设计系统接口时,经常会遇到这样的问题:我们的接口应该提供多少方法才合适?我们的接口应该提供"原子方法"还是"复合方法"?我们的接口是否应该封装(或者,能否封装)所有的细节?接口的设计需要考虑用户的使用习惯、使用的方便程度、使用的安全程度,根据我的编程经验,下面会详细讨论接口设计的2个需要权衡的方面:接口的单一化 & 复合化。
接口接口提供了不同系统之间或者系统不同组件之间的界定。
在软件中,接口提供了一个屏障,从而从实现中分离目标,从具体中分离抽象,从作者中分离用户。
站在用户的角度看,一个接口建立并命名了一个目标对象的使用方法。
一些约束(例如:编译时的类型系统、运行时的异常机制及返回值)使得类作者的目的得以体现和加强。
供给(affordances)指事物的被感知的真实的属性,这些属性可以决定事物使用的可能方法,供给提供了对事物操作的线索。
类设计者的一个职责便是在接口中减小约束与供给之间的隔阂、匹配目标以及一定程度上的自由度,尽可能减小错误使用目标对象的可能。
封装对于封装来说,远不止数据私有那么简单。
软件接口设计方案

软件接口设计方案软件接口设计方案是指在软件开发中,为了实现模块之间的数据交换和功能调用,而定义的一套统一的接口规范。
一个好的接口设计方案应该具备可拓展性、易用性、高效性等特点。
下面是一个软件接口设计方案的示例,以便更好地说明接口设计的思路和步骤。
1. 需求分析:首先,我们需要对系统的需求进行分析,明确系统中各个模块之间的数据交换和功能调用的需求。
- 确定系统的功能模块:将系统划分为不同的功能模块,每个功能模块负责一个或多个相关的功能。
- 确定模块之间的接口:确定模块之间需要交换的数据和相互调用的方法。
2. 接口定义:根据需求分析的结果,我们可以开始定义接口。
- 定义数据交换接口:确定数据交换的格式和规范,包括数据结构和数据类型的定义。
- 定义功能调用接口:确定可供其他模块调用的方法,包括方法名、参数和返回值的定义。
3. 接口实现:接口定义完成后,我们可以开始实现接口。
- 实现数据交换接口:根据接口定义,编写代码实现数据的传递和交换。
- 实现功能调用接口:根据接口定义,编写代码实现方法的调用和返回值的处理。
4. 接口测试:在接口实现完成后,需要对接口进行测试,以验证接口的正确性和稳定性。
- 编写测试用例:根据接口的功能和使用场景,编写测试用例,包括输入数据和预期输出结果。
- 执行测试用例:执行测试用例,观察接口是否按照预期工作,如果发现问题,则进行调试和修复。
5. 接口文档和示例:完成接口测试后,我们可以编写接口文档和示例,以便其他开发人员使用接口。
- 编写接口文档:详细说明接口的使用方法和参数说明。
- 编写接口示例:提供一个简单明了的示例程序,展示如何使用接口进行数据交换和功能调用。
6. 接口维护:随着系统的需求演化,接口可能需要进行调整和扩展,我们需要进行接口的维护工作。
- 修改接口定义:根据新的需求,修改接口的定义,包括数据结构和方法的定义。
- 修改接口实现:根据修改后的接口定义,修改接口的实现代码。
接口设计说明书(软件设计文档范例)

接口设计说明书(软件设计文档范例)接口设计说明书(软件设计文档范例)1.引言1.1 文档目的本文档旨在描述软件系统的接口设计,提供开发人员进行开发和集成工作的指导。
1.2 读者对象本文档适用于软件开发团队、测试人员和其他与系统开发和集成相关的人员。
2.系统概述2.1 系统描述系统为一个类型的软件系统,主要功能包括但不限于、和。
2.2 系统架构系统采用了架构,主要包括以下模块和组件:- 模块1:描述模块1的功能和接口- 模块2:描述模块2的功能和接口-3.接口设计3.1 接口概述系统的接口主要分为内部接口和外部接口,用于不同模块之间的通信和数据传递。
3.2 内部接口3.2.1 模块1接口模块1提供以下接口供其他模块使用:- 接口1:描述接口1的功能和输入输出参数- 接口2:描述接口2的功能和输入输出参数-3.2.2 模块2接口模块2提供以下接口供其他模块使用:- 接口1:描述接口1的功能和输入输出参数- 接口2:描述接口2的功能和输入输出参数-3.3 外部接口3.3.1 数据输入接口系统支持以下数据输入接口:- 接口1:描述接口1的功能和输入参数格式- 接口2:描述接口2的功能和输入参数格式-3.3.2 数据输出接口系统支持以下数据输出接口:- 接口1:描述接口1的功能和输出数据格式- 接口2:描述接口2的功能和输出数据格式-4.接口标准4.1 接口命名规范- 内部接口:采用驼峰命名法,例如getUserName()- 外部接口:采用大写字母和下划线的形式,例如GET_USER_INFO4.2 接口参数规范- 参数类型:根据具体需求确定参数的类型,例如字符串、整数等- 参数命名:采用有意义的命名,易于理解和使用4.3 接口返回值规范- 返回值类型:根据具体需求确定返回值的类型,例如字符串、整数等- 返回值说明:对返回值的含义和可能取值进行详细说明5.附件本文档涉及的附件包括:- 附件1:x- 附件2:x-6.法律名词及注释6.1 法律名词1:定义1- 注释1:x6.2 法律名词2:定义2- 注释2:x7.全文结束。
软件接口设计指南

软件接口设计指南1. 引言本文档旨在提供一套全面的软件接口设计指南,以帮助开发者在设计和实现软件接口时遵循最佳实践。
遵循本指南有助于提高软件质量、易于维护、扩展性和用户体验。
本文档适用于接口设计者、开发者和测试人员。
2. 设计原则2.1 一致性- 遵循一致的设计风格和命名规范。
- 确保接口的返回值、参数、异常等具有一致的格式和命名。
- 保持接口的响应时间和数据格式的一致性。
2.2 简单性- 设计简洁直观的接口,避免复杂的业务逻辑。
- 精简接口的参数和返回值,避免过度封装。
- 采用标准的数据格式和通信协议,降低接口实现的复杂性。
2.3 通用性- 设计通用的接口,支持多种业务场景。
- 支持多种数据格式的输出,如JSON、XML等。
- 考虑跨平台、跨语言的兼容性,使用通用序列化、反序列化库。
2.4 可扩展性- 采用模块化设计,便于后续功能扩展。
- 支持参数的配置化,方便根据不同场景调整接口行为。
- 预留充足的注释和文档,方便后续维护和升级。
2.5 安全性- 实现用户认证和权限控制,确保接口的安全性。
- 对敏感数据进行加密处理,防止数据泄露。
3. 接口规范3.1 请求和响应- 请求和响应数据格式采用JSON或XML。
- 请求参数和返回结果应包含必要的元数据,如API版本、请求时间、响应状态等。
3.2 参数传递- 尽量采用查询参数、表单参数或JSON格式的请求体传递参数。
- 对于敏感或大容量数据,可采用文件上传方式。
- 参数名称和类型应具有明确的意义,避免使用缩写或模糊的命名。
3.3 状态码和错误处理- 对于业务错误,返回非2xx的状态码,并在响应体中包含错误信息。
- 提供详细的错误描述,方便客户端定位和处理问题。
3.4 数据验证- 对请求和响应数据进行严格的校验,确保数据格式和内容合法。
- 对于必填字段,缺少或格式不正确时,应返回错误信息。
- 对于数据范围、类型等限制,应在接口文档中明确说明。
3.5 性能优化- 优化接口的查询和业务逻辑,提高响应速度。
【软件工程】【CMMI】软件项目接口设计指南

【软件工程】【CMMI】软件项目接口设计指南在软件项目的开发过程中,接口设计是一个至关重要的环节。
一个良好的接口设计能够提高软件系统的可维护性、可扩展性和可重用性,从而大大提高软件开发的效率和质量。
本文将为您详细介绍软件项目接口设计的相关知识和指南。
一、接口设计的重要性接口是不同模块或系统之间进行交互和通信的桥梁。
它定义了模块之间的输入和输出规范,包括数据格式、调用方式、错误处理等。
如果接口设计不合理,可能会导致以下问题:1、模块之间的耦合度增加,使得一个模块的修改会影响到其他相关模块,从而增加了软件维护的难度和成本。
2、接口的不清晰和不一致会导致开发人员在使用接口时出现误解和错误,影响软件的功能和性能。
3、缺乏灵活性和可扩展性的接口会限制软件系统的升级和改进,无法满足不断变化的业务需求。
因此,合理的接口设计是软件项目成功的关键之一。
二、接口设计的原则1、简洁性接口应该尽量简单明了,避免过于复杂的参数和返回值。
简洁的接口能够降低开发人员的理解成本,提高开发效率。
2、一致性接口的命名、参数类型、返回值类型等应该保持一致,遵循统一的规范和标准。
这样可以提高代码的可读性和可维护性。
3、稳定性接口一旦定义并发布,应该尽量保持稳定,避免频繁的修改。
如果确实需要修改接口,应该考虑向后兼容,以减少对现有系统的影响。
4、灵活性接口应该具有一定的灵活性,能够适应不同的业务场景和需求。
例如,可以通过参数的配置来实现不同的功能。
5、安全性接口应该考虑安全性,对输入的数据进行有效的验证和过滤,防止恶意攻击和数据泄露。
三、接口设计的步骤1、需求分析首先,需要对软件系统的需求进行深入分析,明确各个模块之间的交互关系和数据流向。
了解业务流程和用户需求,确定接口的功能和性能要求。
2、定义接口根据需求分析的结果,定义接口的名称、参数、返回值、调用方式等。
在定义接口时,应该充分考虑接口的原则,确保接口的合理性和可用性。
3、设计数据格式确定接口传输的数据格式,如 XML、JSON、二进制等。
软件工程中的系统集成与接口设计指南

软件工程中的系统集成与接口设计指南在软件开发过程中,系统集成和接口设计是至关重要的步骤。
系统集成是将不同的软件组件整合在一起形成一个完整的系统的过程,而接口设计是定义不同组件之间的通信规范和交互方式。
本篇文章将介绍软件工程中的系统集成与接口设计的指南,帮助开发者们更好地进行软件开发和系统构建。
一、系统集成系统集成是将各个独立的软件组件整合到一个统一的系统中,使其协同工作以实现预期的功能和性能。
下面是一些系统集成的指南:1. 确定集成目标:在系统集成的开始阶段,需要明确集成的目标和期望的结果。
这包括确定系统的功能需求、性能要求以及交付时间等。
在明确目标的基础上,才能有针对性地进行系统集成。
2. 制定集成计划:制定一个详细的集成计划,明确每个组件的集成顺序和时间表。
确保各个组件的集成过程有条不紊,避免出现不必要的延误和冲突。
3. 进行接口测试:在组件集成之前,先进行接口测试。
接口测试是验证组件之间的交互是否符合设计规范的过程。
通过接口测试,可以提早发现和解决可能存在的问题,减少后期调试的工作量。
4. 集成测试:系统集成后,进行整个系统的测试。
这是为了验证整个系统的功能和性能是否满足需求。
在集成测试过程中,应该充分考虑各种可能的使用场景和异常情况,并进行充分的测试覆盖。
5. 错误处理和修复:在集成测试中可能会发现一些错误和缺陷。
及时记录和报告这些问题,并进行修复。
确保整个系统在正式交付之前是稳定可靠的。
二、接口设计接口设计是定义组件之间的通信规范和交互方式,确保各个组件能够顺利地进行信息交换和数据共享。
下面是一些建立良好接口设计的指南:1. 明确接口功能:在接口设计之前,需要先明确接口的功能和用途。
不同的接口可能有不同的功能需求,比如数据传输、服务调用等。
通过明确功能,可以更好地设计接口的数据结构和方法。
2. 规范命名和文档:为了提高接口的可读性和可维护性,需要规范命名和编写接口文档。
接口的命名应该简洁明了,能够准确反映其功能和用途。
设计好接口的方法总结(一)2024
设计好接口的方法总结(一)引言概述:设计好接口是软件开发中的重要环节之一。
一个良好设计的接口可以提高代码的可读性、可维护性和可扩展性。
本文将总结设计好接口的一些常用方法,以帮助开发人员更好地设计接口。
一、明确接口的功能和用途1. 确定接口的目标和使用场景2. 提供清晰的接口文档和示例3. 设计接口时考虑使用者的需求和使用习惯4. 定义合理的接口命名和参数命名规范5. 在设计接口时考虑功能的高内聚和低耦合二、提供必要的错误处理和异常机制1. 设计良好的错误码和异常类型2. 提供详细的错误信息和异常堆栈信息3. 提供合理的错误处理策略和异常处理机制4. 异常处理时遵循原则:Catch只捕获自己能处理的异常,Throw只抛出自己处理不了的异常5. 在接口文档中明确说明可能出现的错误和异常,并提供相应的处理方法三、设计灵活且易于扩展的接口1. 使用合适的设计模式,如工厂模式、策略模式等2. 使用接口继承和实现接口的方式,提高代码的灵活性3. 使用接口回调机制,允许接口实现类的替换和扩展4. 提供可配置的参数和选项,以满足不同需求和场景的变化5. 尽量避免使用过多的方法重载,使接口更加清晰和易于使用四、保证接口的稳定性和兼容性1. 遵循接口版本管理的原则2. 尽量避免对接口的大改动,以兼容老版本的使用者3. 提供良好的接口升级和兼容性处理策略4. 提供详细的更新文档和接口变动说明5. 及时修复已知的接口缺陷和问题五、进行有效的接口测试和评估1. 编写详细的测试用例和测试计划2. 使用专业的接口测试工具进行自动化测试3. 进行接口性能和负载测试,确保接口的稳定性和可靠性4. 接口上线前进行全面的功能和兼容性测试5. 定期对已上线接口进行评估和改进,解决潜在问题和风险总结:设计好接口是一项复杂而重要的任务,它直接影响到软件系统的稳定性和可扩展性。
通过明确接口的功能和用途、提供必要的错误处理和异常机制、设计灵活且易于扩展的接口、保证接口的稳定性和兼容性,并进行有效的接口测试和评估,可以帮助开发人员更好地设计接口,提高代码的质量和效率。
软件设计中的接口文档撰写指南
软件设计中的接口文档撰写指南在软件开发过程中,接口文档一直是至关重要的环节。
软件设计中的接口文档涉及到软件系统的接口、接口调用方法与参数、返回值等内容的规范和说明。
良好的接口文档对软件开发人员、产品经理以及最终用户都具有实际意义。
接下来,我们将为大家讲解软件设计中接口文档撰写的指南。
首先,在接口文档撰写之前,我们需要确立文档格式和内容方向。
根据文档的使用目的所在,可以分为内部文档和外部文档:内部文档主要面向开发人员和测试人员,提供程序实现细节及测试方案;外部文档主要针对终端用户和顾客,提供接口说明及用户调用方法。
再根据接口文档的类别,可分为数据接口文档和业务接口文档。
两者区别在于后者不但需要说明接口功能,还需注重说明用户如何通过业务接口来实现业务。
接口文档中,需要列出各接口对应的功能码,名称及具体描述。
接口功能码应该是一个独一无二的标识符,用于解析进来的数据报文。
名称应该简洁易懂,不得与其他接口重名。
具体描述应包含接口调用方式、参数及返回值等详细信息。
参数需尽可能清晰明了,避免出现不必要的歧义。
其次,在接口文档中需要遵循统一的文档格式和规范。
文档应该包含接口版本、变更记录、作者、审查及审核信息等常用段落,以便日后的沟通交流以及问题排查。
接口文档应该遵循一致性约定,包括命名约定、变量名约定以及方法名约定等,以便各个开发人员能够理解并遵循。
文档格式建议采用规范化格式,应有清晰的目录结构、层次分明的标题以及行之有效的代码例子等。
除此之外,还应该为接口文档添加足够的细节描述信息。
详细地表达接口参数及返回值类型、范围和限制、参数含义及格式等,以促进后续的接口测试和使用。
例如,输入的日期格式应遵循YYYY/MM/DD 的格式,其中年份为4位数,月份和日期为2位数字。
其次,接口描述中应该包含常规错误及异常处理方法,以保障接口的安全性。
例如,当输入参数小于等于0时,应返回错误码101并提示“输入参数无效”。
最后,接口文档应对已有接口及其变更进行管理,并随接口版本变更而同步更新。
(完整word版)软件工程过程资料-接口设计说明书
出参
备注
1
可说明提供方的相关信息
2
5
没有此接口方式可删除此章节目录。
5.1
如提供给银行的“查询电费"功能,一些需要说明的信息在此说明;如果功能比较复杂,可以根据需要设立下级子功能的目录结构。TUXDEO服务的使用表格描述。
5.1.1
如果功能简单,此级目录可以不要,使用TUXDEO服务表格描述。
TUXDO接口服务表格如下:
Webservice接口服务表格如下:
方法名称
说明服务的CODE和名称
描述
发布路径
输入参数
参数代码
参数名称
数据类型
参数说明
输出参数
参数代码
参数名称
数据类型
参数说明
错误信息
部署情况
示例
使用开发代码举例说明如何调用
7
7.1
说明传输文件的名称规则及格式,如MRDATA.DBF
7.2
根据需要,说明文件的列分割,行分割等条件,建议用表格方式。例如字段可以使用下列表格。
1.2
文档的适用范围,比如是在全公司适用还是在某个产品部适用等.预期的读者是哪些等。
1.3
列出本文件中用到的专门术语的定义,例如中间库在本项目中的的含义,如果没有需特别要说明的,可删除此章节
术语
解释
1.4
列出有关的参考资料
2
2.1
【说明本模块的基本设计概念,比如对需求是如何考虑的,为什么要把对应的需求转换成这样的设计处理,以及接口的概况性的描述、要求】
数据类型
参数说明
PORT
char
通讯端口号,参见标准代码PORT_NO
BAUDRATE
char
如何进行软件开发中的接口设计
如何进行软件开发中的接口设计在软件开发的过程中,接口设计是一个至关重要的环节。
接口设计的好坏直接决定了软件的稳定性和易用性。
下面将介绍如何进行软件开发中的接口设计。
一. 理解业务需求首先,在进行接口设计之前,我们必须深刻理解业务需求。
只有了解业务需求,我们才能更好的设计出适合的接口。
例如,如果我们需要设计一个电商平台的接口,我们需要了解电商平台的业务流程,包括商品展示、购物车、订单结算、地址管理等等。
二. 定义接口规范在了解业务需求的基础上,我们需要定义接口规范。
接口规范应该清晰明了、易于理解,包括接口名称、请求方法、请求参数、返回数据等等。
接口规范可以制定在API文档中,供开发人员参考。
三. 规范请求方式不同的接口有不同的请求方式,例如GET、POST等。
在设计接口的时候,我们需要根据实际情况来选择最合适的请求方式。
GET请求一般用于获取数据,POST请求一般用于提交数据。
如果请求数据包含敏感信息,我们应该选择更加安全的POST请求,同时对数据进行加密保护。
四. 定义参数格式接口所需的参数格式应该清晰明了,不同的接口可能需要不同的参数格式。
例如,一些接口需要传递JSON格式的参数,而另外一些接口需要传递XML格式的参数。
在定义参数格式的时候,我们应该考虑到客户端的兼容性和数据安全性。
五. 按照标准返回数据在设计接口时,返回数据格式同样非常重要。
一般情况下,我们应该按照标准返回JSON或XML格式的数据,同时对数据进行合理的加密保护。
返回数据格式应该清晰明了,易于解析。
六. 考虑错误处理在设计接口时,我们需要考虑到可能出现的错误情况。
例如,客户端传递的参数不正确,服务器端出现异常等等。
对于不同的错误情况,我们应该返回不同的错误码和错误信息,以便客户端进行相应的处理。
七. 接口版本管理随着业务需求的不断变化和更新,我们需要对接口进行版本管理。
在设计接口时,我们应该考虑到接口的扩展性和可维护性。
例如,为了保证接口的向后兼容性,在修改接口时需要保持接口名称、请求参数和返回数据格式不变。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
软件接口设计指南拟制人日期审核人日期批准人日期目录1目的 (1)2适用范围 (1)3参考文件 (1)4定义和缩写 (1)5规定 (1)5.1JAVA接口设计方法 (1)5.2C++接口设计方法 (5)5.3接口设计对软件性能的影响 (7)5.4面向对象设计中,接口设计的一般原则 (10)6附件 ............................................................................................................................... 错误!未定义书签。
1目的为大家在进行软件接口设计时提供一些指导,以帮助大家更好的理解软件接口设计的方法和原则。
2适用范围适用于公司软件开发的接口设计过程。
3参考文件本过程文件中的过程裁剪应依据《组织标准过程裁剪指南》的规定。
4定义和缩写本过程文件的编写依据是美国软件工程研究院(SEI)的集成成熟度模型软件分支1.2版本(CMMI-DEV V1.2)。
5规定5.1JAVA接口设计方法我们在设计系统接口时,经常会遇到这样的问题:我们的接口应该提供多少方法才合适?我们的接口应该提供"原子方法"还是"复合方法"?我们的接口是否应该封装(或者,能否封装)所有的细节?接口的设计需要考虑用户的使用习惯、使用的方便程度、使用的安全程度,根据我的编程经验,下面会详细讨论接口设计的2个需要权衡的方面:接口的单一化 & 复合化。
接口接口提供了不同系统之间或者系统不同组件之间的界定。
在软件中,接口提供了一个屏障,从而从实现中分离目标,从具体中分离抽象,从作者中分离用户。
站在用户的角度看,一个接口建立并命名了一个目标对象的使用方法。
一些约束(例如:编译时的类型系统、运行时的异常机制及返回值)使得类作者的目的得以体现和加强。
供给(affordances)指事物的被感知的真实的属性,这些属性可以决定事物使用的可能方法,供给提供了对事物操作的线索。
类设计者的一个职责便是在接口中减小约束与供给之间的隔阂、匹配目标以及一定程度上的自由度,尽可能减小错误使用目标对象的可能。
封装对于封装来说,远不止数据私有那么简单。
在设计中,封装往往会涉及到自我包含(self-containment)。
如果一个类需要你知道如何调用它方法(e.g. 在一个线程的环境中,在一个方法调用后调用另一个方法,你必须明确地同步对象),那么它的封装性就不如将所有这些全部包含并隐藏的类(e.g. 这个类是thread-safe的)好。
前一个设计存在着设计的漏洞,它的许多限定条件是模糊的,而且把部分责任推给了用户,而不是让类提供者做这些工作来完成类的设计。
在空间或者时间上分离方法的执行(例如,线程,远程方法调用,消息队列),能够对设计的正确性和效率产生意义深远的影响。
这种分离带来的结果是不可忽视的:并发引入了不确定性和环境(context)选择的开销;分布引入了回调的开销,这些开销可能不断增加,而且会导致错误。
这些是设计的问题,修改它们可不是象修改bug那样简单。
如果一个接口主要由存取方法(set和get方法)组成,每个方法都相应的直接指向某个私有域,那么它的封装性会很差。
接口中的域存取方法通常是不会提供信息的:他们在对象的使用中不能通讯、简单化和抽象化,这通常会导致代码冗长,并且容易出错。
所以,我们首先考虑接口设计的第一个原则:命令与查询分离(Command-Query Separation)要求:保证一个方法不是命令(Command)就是查询(Query)定义:查询:当一个方法返回一个值来回应一个问题的时候,它就具有查询的性质;命令:当一个方法要改变对象的状态的时候,它就具有命令的性质;通常,一个方法可能是纯的Command模式或者是纯的Query模式,或者是两者的混合体。
在设计接口时,如果可能,应该尽量使接口单一化,保证方法的行为严格的是命令或者是查询,这样查询方法不会改变对象的状态,没有副作用(side effects),而会改变对象的状态的方法不可能有返回值。
也就是说:如果我们要问一个问题,那么就不应该影响到它的答案。
实际应用,要视具体情况而定,语义的清晰性和使用的简单性之间需要权衡。
例如,在java.util.Iterator中,hasNext可以被看作一种查询,remove是一种命令,next合并了命令和查询:public interface Iterator{boolean hasNext();Object next();void remove();}这里,如果不将一个Iterator对象的当前值向前到下一个的话,就不能够查询一个Iterator对象。
如果没有提供一个复合方法next,我们将需要定义一系列的命令方法,例如:初始化(initialization)、继续(continuation)、访问(access)和前进(advance),它们虽然清晰定义了每个动作,但是,客户代码过于复杂:for(initialization; continuation condition; advance){... access for use ...}将Command和Query功能合并入一个方法,方便了客户的使用,但是,降低了清晰性,而且,可能不便于基于断言的程序设计并且需要一个变量来保存查询结果:Iterator iterator = collection.iterator();while(iterator.hasNext();){Object current = iterator.next();... use current...}下面,我们考虑接口设计的第二个原则:组合方法(Combined Method)组合方法经常在线程和分布环境中使用,来保证正确性并改善效率。
一些接口提供大量的方法,起初,这些方法看来是最小化的,而且相关性强。
然而,在使用的过程中,一些接口显现得过于原始,它们过于简单化,从而迫使类用户用更多的工作来实现普通的任务,并且,方法之间的先后顺序及依赖性比较强(即,暂时耦合)。
这导致了代码重复,而且非常麻烦和容易出错。
一些需要同时执行成功的方法,在多线程、异常、和分布的情况下会遇到麻烦。
如果两个动作需要同时执行,它们由两个独立的方法进行描述,必须都完全成功的执行,否则会导致所有动作的回滚。
线程的引入使这种不确定性大大增加。
一系列方法同时调用一个易变的(mutable)对象,如果这个对象在线程之间共享,即使我们假设单独的方法是线程安全的,也无法确保结果是意料之中的。
看下面对Event Source的接口,它允许安置句柄和对事件的查询:interface EventSource{Handler getHandler(Event event);void installHandler(Event event, Handler newHandler);}线程之间的交叉调用可能会引起意想不到的结果。
假设source域引用一个线程共享的对象,对象很可能在1、2之间被另一个线程安装了一个新的句柄:class EventSourceExample{public void example(Event event, Handler newHandler){oldHandler = eventSource.getHandler(event); // 1//对象很可能在这里被另一个线程安装了一个新的句柄eventSource.installHandler(event, newHandler); // 2}private EventSource eventSource;private Handler oldHandler;}为了解决问题,也需要由类的使用者而不是类的设计者来完成:class EventSourceExample{public void example(Event event, Handler newHandler){synchronized(eventSource){oldHandler = eventSource.getHandler(event);eventSource.installHandler(event, newHandler);}}private EventSource eventSource;private Handler oldHandler;}我们假设:目标对象eventSource是远程的,执行每一个方法体的时间和通讯的延迟相比是很短的。
在这个例子中,eventSource的方法被调用了两次,并可能在其他的实例中重复多次,因而,开销也是至少两倍。
此外还有一个问题是对外部的synchronized同步块的使用需求。
对synchronized 块的使用之所以会失败,主要因为我们通过代理对象来完成工作,所以,调用者的synchronized块,同步的是代理对象而不是最终的目标对象,调用者不可能对其行为做太多的保证。
Combined Method必须在分布的环境,或者,线程环境中同时执行。
它反映了用户直接的应用,恢复策略和一些笨拙的方法被封装到Combined Method中,并简化了接口,减少了接口中不需要的累赘。
Combined Method的效果是支持一种更像事务处理风格的设计。
在一个组合的Command-Query中提供一个单独的Query方法通常是合理的。
提供分离的Command方法是不太常见的,因为Combined Method可以完成这一工作,只要调用者简单的忽略返回结果。
如果返回一个结果招致一个开销的话,才可能会提供一个单独的Command方法。
回到前一个例子中,如果installHandler method返回上一次安装的句柄,则设计变得更加简单和独立:interface EventSource{Handler installHandler(Event event, Handler newHandler);}客户代码如下:class EventSourceExample{public void example(Event event, Handler newHandler){oldHandler = eventSource.installHandler(event, newHandler);}private EventSource eventSource;private Handler oldHandler;}这样,我们给调用者提供了一个更加安全的接口,并且不再需要他们解决线程的问题。