利用 DITA 专门化和扩展捕获用例文档

使用 DITA 利用单一来源用例文档

探究如何将需求收集与开发管理人员、开发人员、测试人员和技术作者们可以在开发周期中重复使用的文档相结合。达尔文信息分类体系结构(Darwin Information Typing Architecture,DITA)中灵活的扩展机制即将成为这类任务的行业标准。本文中,您将为用例文档创建一个专门化的模式。

Piers Michael Hollott, 高级顾问, Sierra Systems

Piers Hollott 从事软件行业工作已经 15 年了,他专长于 Java 开发、XML 技术和函数式编程。他为好几个开源项目贡献过力量,目前是 Sierra Systems 的一名顾问。



2011 年 5 月 30 日

常用缩写词

  • DTD:文档类型定义
  • OASIS:结构化信息标准促进组织
  • PDF:便携文档格式
  • XSD:XML 模式定义
  • XML:可扩展标记语言
  • XSL:可扩展样式表语言

在软件行业,用例用于收集关于软件应用程序如何与其用户交互的信息。OASIS 达尔文信息分类体系结构 (DITA) 是一个基于 XML 的技术文档框架,用于映射及发布关于给定主题的信息。在 DITA 中,单个主题代表一个信息单元,使用主题图展示对应于其他主题的相关主题。类似地,用例代表较大流程的一部分,用例模型代表整个流程。使用 DITA 结构性专门化(这会将现有主题类型扩展为一些新类型,却保持与现有操作兼容),可以扩展基本的 DITA 主题类型,以支持用例收集。

本文是前一篇 developerWorks 文章 “利用单一来源的 DITA 创建演练脚本和验收脚本” 的续篇,那篇文章描述了如何将一篇简单的用法文档重新用作验收测试阶段的质量保证 (QA) 文档。前一篇文章使用基本的 DITA 主题类型,而本文采用更健壮的方法,将基本主题类型扩展成新的专门化类型,同时将重点放在单一来源和重复利用等优势上。

管理用例

在软件开发中,一个用例 代表用户与所描述的系统之间的一个独立交互单元。很多用例与用例模型 中的各个用例相关。通常在软件项目的需求阶段详细描述用例。在充分详细说明之后,用例被交付给开发团队,他们将用例当作所开发产品的规范。这些用例并不仅仅是蓝图。它们也是合约,被交付给内部人员、工厂和用户验收测试人员,他们验证所开发软件满足用例模型提供的初始需求。

用例文档本身是静态的,从业务分析人员传递到开发人员和测试人员。文档本身的格式不会改变 — 尽管文档中信息的不同部分被用于软件开发生命周期 (SDLC) 的不同阶段。

好的用例完成业务需求收集、软件构造和验收测试之间的循环。但是在最好的情况下,这些环节是 SDLC 的不同阶段,用例在每个阶段的使用方式也各不相同。在软件项目中,如果发现用例不包含继续前进所必需的信息类型,那么后果起码是代价惨重 — 甚至是灾难性的。

我管理软件开发项目时,大部分时间花在“内容争论”上,即组织和准备诸如用例之类的文档。正如我在另一个地方所指出的(参见 参考资料 中的链接),一种更灵活的方法及时出现了。


使用 DTD 和 XSD 定义 DITA

前面提到,DITA 是一个基于 XML 的文档框架,单独地代表每个文档化主题。例如,一个手册可能包含很多描述如何执行各种任务的主题。这些主题然后通过一个叫做主题图 的 XML 文档与其他主题相关。除了基本主题图和主题之外,DITA 框架还被扩展来提供一类更专门化的适合于不同类型文档的主题。基本的专门化主题类型是 conceptreferencetask

您可以使用 DTD 或 XSD 定义 DITA 文档。这二者都被作为 DITA Open Toolkit 的一部分提供,已经在很多 XML 编辑器中可用。我首选使用 XSD 模式,但是模式语言的选择由您做主。任意一种情况下,DITA 主题类型的模式定义都包含两个主要部分:模式本身(例如,concept.dtd 或 reference.xsd,负责定义主题类型的高级领域)和模块(例如,concept.mod 或 referenceMod.xsd,负责定义组成模式的元素和属性)。如果您使用的是 XSD 模式,那么您也会修改一个组(比如 referenceGrp.xsd),这个组为每个定义的 DITA 元素包含占位符 xs:group 元素。结构性专门化涉及到创建模式定义、模块和组文件。

一般主体类型被专门化为三个基本主题类型,这需要为每个基本主题类型创建一个新模式,定义它们包含的所有新元素以及新模式如何与初始模式相关。您使用一个类属性(在下文中更详细地描述)来描述这种关系。但是,专门化过程并不到此结束,因为三个基本主题类型又会以相同的过程被专门化,以创建新的 DITA 主题类型。这样,您可以使用 DITA 结构性专门化将 DITA 扩展成用例领域。

清单 1 中(取自基本任务类型的 DITA 模式),您可以看到默认的类字符串 tasktaskbody 是如何以一个短线 (-) 打头的(这表示此专门化是结构性的),后跟一个由空格分隔的主题类型和主题元素对(由斜杠 / 分隔)列表。该列表定义新元素,将它映射回更一般的元素 — 例如,将 taskbody 映射回更一般的 body

清单 1. 从 topic.class 扩展而来的 task.class
<!-- Base type: topic.class -->
<xs:complexType name="task.class">
     ...
     <xs:attribute ref="class" default="- topic/topic task/task "/>
</xs:complexType>

<!-- Base type: body.class -->
<xs:complexType name="taskbody.class">
     ...
     <xs:attribute ref="class" default="- topic/body  task/taskbody "/>
</xs:complexType>

DITA Open Toolkit

DITA Open Toolkit(参见 参考资料)是一个开源项目,可以用来从一个 DITA 来源生成各种输出类型(包括 PDF)。因为您总是可以在结构性专门化中将新元素映射回更一般的元素,所以任何使用基本主题类型创建的新主题类型都从这些基本主题类型和那些与初始 topic 模式相关的主题类型继承样式。


使用 DITA 详细说明用例

利用单一来源的 DITA 创建演练脚本和验收脚本 中一样,这里提供的样例应用程序只专门针对演示目的进行介绍。它为一个带有主页、主操作流(也叫做“阳关大道”)和备选操作流的简单向导描述了需求。两个操作者(应用程序的用户和系统)之间的主要交互要求用户键入他/她的名字,然后才能够修改个人资料。

跟以前一样,应用程序由单个包含几个页面的模块组成。一个关联 reference 主题的 DITA 主题图向相关的用例描述了这些页面。DITA 主题图扮演用例模型的角色。上次我使用了 task 主题;现在我将通过使用结构性专门化创建一个新主题类型(我称之为 case)来扩展 task 主题。

约束和不变式

一个典型的用例由一组描述软件状态的前置和后置条件组成(描述为用例被触发以及最终完成)。此外,您还可以定义状态不变式(invariant),这类似于用例过程中不会改变的规则 —— 例如“显示在屏幕上的姓总是大写形式”。您可以使用 DITA 专门化分别为这些约束、条件和不变式建模,可能还要扩展 concept 主题类型。为简单起见,我选择将这些细节直接添加到 case 主题模式的主体。

被标准地定义为 DITA 体系结构一部分的基本 task 主题针对前提条件、后置条件和上下文(类似于前面定义的状态“不变式”)包含有元素。这些元素都是从基础主题中的节标题(section heading)类扩展而来,这允许单个标题元素包含多个段落。对于用例主题,您想要这些元素(或者那些扩展它们的类似元素)允许一个无序的规则列表,因为这种方法更接近于您试图模拟的功能。要完成此任务,为所有三个类别扩展 DITA 无序元素列表,而不是扩展节头(section header)。

清单 2 扩展了 DITA 基础无序列表 (ul) 和列表条目 (li) 元素,以创建继承自它们的新元素,从而给出前提条件或约束的集合。注意,我选择将 constraints 类不仅映射到基础主题中的 ul 元素,也映射到中间任务中的 prereq 元素。我用事例/约束取代任务/前提条件,所以我想要它同时从两个前辈继承样式。constraint 元素没有中间前辈。这一专门化的结果是,尽管 task 主题允许单个前提条件,但是 case 主题要求一系列前提约束。

清单 2. caseMod.xsd 中的约束类
<!-- Base type: ul.class -->
<xs:complexType name="constraints.class">
     <xs:choice maxOccurs="unbounded">
          <xs:group ref="constraint"/>
     </xs:choice>
     ...
     <xs:attribute ref="class" default="- topic/ul task/prereq case/constraints "/>
</xs:complexType>

<!-- Base type: li.class -->
<xs:complexType name="constraint.class" mixed="true">
     <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:group ref="listitem.cnt"/>
     </xs:choice>
     ...
     <xs:attribute ref="class" default="- topic/li case/constraint "/>
</xs:complexType>

正如您可以从本文样例文件(参见 下载)看到的,一种类似的方法定义了后置条件和不变式。在两种情况下,task 主题模式的一个元素在格式上被定义为节标题(prereqpostreqcontext),被约束、条件和不变式的一个无序列表所取代。以这种方式建模用例更为严密,但是允许 case 主题继承自更一般的 task

清单 3 中的代码展示了约束组在模式组文件中是如何设置的。

清单 3. caseGrp.xsd 中的约束组
<xs:group name="constraints">
     <xs:sequence>
          <xs:element ref="constraints"/>
     </xs:sequence>
</xs:group>
<xs:group name="constraint">
     <xs:sequence>
          <xs:element ref="constraint"/>
     </xs:sequence>
</xs:group>

场景、步骤和交互

任何用例的重点是软件用户与软件本身(通常描述为系统)之间的交互。一个用例可能涉及到很多操作者和交互,从更广泛的意义上,这些条目应该使用 DITA reference 主题来描述。引用(reference)通常用来代表实际对象,所以它们非常适合于应用程序用户、模块和页面。同样,为了简单起见,我选择在 case 主题的主体内给出很多这些引用,尽管您可以从您用来代表用例模型的主题图中单独引用这些条目,然后再将这些引用捆绑到单个用例主题中。不幸的是,这样做超出了本文范畴。

DITA 任务的核心是一系列步骤,它们可以被专门化回有序列表类 ol.class。这个类接近于您试图产生的模型,只有一个重要的局限性除外:正如所定义的,step 不归因于操作者。这个区别很重要,因为用例场景中的每个步骤都必须归因于操作者。通常,定义用例的一组步骤代表应用程序用户与系统之间的一次对话。可能也涉及到其他操作者,但是这里只考虑简单情况。但是,step 元素并不归因于操作者。还有,标准的 DITA task 主题只为单组步骤包含一个条件(provision),您可能愿意您的用例不仅包含主操作流,还潜在地包含几个备选操作流。

清单 4 中,观察步骤的类是如何被扩展来创建 scenario.class 的,这个类类似于前辈类。被专门化的类需要一个属性用于描述这是一个主操作流还是备选操作流,默认为 main。定义 casebody 元素时,在模式中的另外一个地方处理这种多样性。由于任务中的主体只允许一组步骤执行任务,所以用例允许多个备选步骤执行用例。

清单 4. caseMod.xsd 中的 scenario.class
<!-- Base type: ol.class -->
<xs:complexType name="scenario.class">
     <xs:choice>>
          <xs:group ref="interaction" maxOccurs="unbounded"/>
     </xs:choice>
     <xs:attribute name="type" default="main">
          <xs:simpleType>
               <xs:restriction base="xs:string">
                    <xs:enumeration value="main"/>
                    <xs:enumeration value="alternate"/>
               </xs:restriction>
          </xs:simpleType>
     </xs:attribute>
     <xs:attribute ref="class" default="- topic/ol task/steps case/scenario "/>
</xs:complexType>

清单 4 中,您也可以看到新的 scenario 元素是如何继承自 stepsol 的。新元素被诸如 DITA Open Toolkit 之类的 DITA 应用程序遇到时,这种继承性允许它像其前辈一样地执行,同时仍然完成新功能。

清单 5 展示了定义用例 interaction 元素的类,同样,此元素类似于它被专门化时所来自的 step 类,惟一的不同之处是,您必须将这个新元素归因于一个操作者。在本例中,我将操作者组限定为“系统”和“用户”,但是您可以添加更多的操作者,并且这些操作者可以引用各个主题(这一内容同样超出了本文范畴)。

清单 5. caseMod.xsd 中的 interaction.class
<!-- Base type: li.class -->
<xs:complexType name="interaction.class">
     <xs:sequence>
          <xs:group ref="cmd"/>
          ...
     </xs:sequence>
     <xs:attribute name="actor" default="system">
          <xs:simpleType>
               <xs:restriction base="xs:string">
                    <xs:enumeration value="user"/>
                    <xs:enumeration value="system"/>
               </xs:restriction>
          </xs:simpleType>
     </xs:attribute>
     <xs:attribute ref="class" default="- topic/li task/step case/interaction "/>
</xs:complexType>

同样,您可以看到这个新元素是如何基于 task 主题中的前辈和基础 DITA 主题中的前辈并从两者继承行为的。


综述

既然已经扩展了一个 DITA 基本主题,您就可以使用自己喜欢的 XML 编辑器快速创建新用例了,并基于新模式向它添加内容。完了之后,您就可以创建一个引用该主题和其他 DITA 主题的主题图了,然后您可以将之用作用例模型,以及使用 DITA Open Toolkit 从它生成一个 PDF 文档。您可能发现,这种方法允许您利用一种将对 DITA 可用的协作构造环境,或者您也可能发现,您可以利用 XSL 或 XQuery 的转换能力来重复利用您的需求文档,使之对您软件开发团队的不同成员更有用。您可以参见 清单 6 中的一个样例 case 文档。

清单 6. 使用 dita/case.xsd 创建的用例文件
<case id="UC5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="Schemas\dita\case.xsd">
     <title>Use Case 5: Review personal information</title>
     <casebody>
          <constraints>
               <constraint>First and Last Name have been entered</constraint>
          </constraints>
          <invariants>
               <invariant>First Name is capitalized</invariant>
               <invariant>Last Name is capitalized</invariant>
          </invariants>
          <scenario type="main">
               <interaction actor="system">
                    <cmd>displays current First and Last Name</cmd>
               </interaction>
               <interaction actor="user">
                    <cmd>accepts current First and Last Name</cmd>
               </interaction>
          </scenario>
          <scenario type="alternate">
               <interaction actor="user">
                    <cmd>rejects current First Name</cmd>
                    <stepresult>loads edit screen for First Name</stepresult>
               </interaction>
          </scenario>
          <scenario type="alternate">
               <interaction actor="user">
                    <cmd>rejects current Last Name</cmd>
                    <stepresult>loads edit screen for Last Name</stepresult>
               </interaction>
          </scenario>
          <conditions>
               <condition>returns to home page</condition>
          </conditions>
     </casebody>
</case>

结束语

利用 DITA 框架,您可以记录软件应用程序与用户是如何交互的。同样,软件用例被用来收集关于软件应用程序如何与用户进行交互的信息,所以两种技术自然融合就成了顺理成章的事情。使用 DITA 结构性专门化将现有主题类型扩展成新的支持用例收集功能的主题时,您可以维护与现有操作的兼容性并对之加以利用。扩展基本 DITA 任务主题之后,您可以使用这个新模式来构建用例;利用这些用例,您可以构建一个灵活且易于维护的用例模型。


下载

描述名字大小
本文样例文件examplecode.zip21KB

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML
ArticleID=664800
ArticleTitle=利用 DITA 专门化和扩展捕获用例文档
publish-date=05302011