UML面试题 第一部分






4.55/5 (85投票s)
UML面试题 第一部分
目录
- (B) 定义UML?
- (I) 您能解释一下用例图吗?
- (I) 您能解释一下主参与者和次参与者吗?
- (I) 一个简单的用例是什么样的?
- (I) 您能解释一下用例中的“扩展”(Extend)和“包含”(Include)吗?
- (I) 您能解释一下类图吗?
- (B) 在类图中,我们如何表示私有、公有和保护成员?
- (I) 类图中的关联(associations)是什么意思?
- (I) 您能解释一下类图中的聚合(aggregation)和组合(composition)吗?
- (A) 什么是组合结构图(composite structure diagram)和类图中的自关联(reflexive association)?
- (I) 您能解释一下业务实体类(business entity)和服务类(service class)吗?
- (I) 您能解释一下系统实体类(system entity)和服务类(service class)吗?
- (B) 您能解释一下泛化(generalization)和特化(specialization)吗?
- (B) 我们如何表示UML中的抽象类(abstract class)和接口(interface)?
- (B) 我们如何实现泛化和特化?
- (I) 您能解释一下UML中的对象图(object diagrams)吗?
- (I) 您能解释一下顺序图(sequence diagrams)吗?
引言
我再说一遍,不要指望通过阅读面试题就能获得一个架构师职位。但确实需要一些参考资料来帮助你快速复习定义。仅仅阅读这些答案,你可以了解基础知识。但是如果你没有实际工作经验,你肯定会在基于场景的问题中失败。所以请将此作为快速复习,而不是捷径。
从下面的链接下载我的500个FAQ电子书 http://www.questpond.com/SampleDotNetInterviewQuestionBook.zip
在我上一节中,我们重点关注了设计模式,这是架构师面试中最重要的基础知识之一。如果你错过了,下面是链接。除了设计模式,架构师还需要掌握的另一个领域是为设计文档选择合适的UML图。
我以前的一些文章,相信你会喜欢的。
设计模式FAQ - SoftArch4.aspx
使用IOC和DI构建松耦合架构:IOCDI.aspx。
编写灵活的业务验证 https://codeproject.org.cn/KB/aspnet/Questpond.aspx
祝您求职愉快......
(B) 定义UML?
统一建模语言(Unified Modeling Language),一种用于以面向对象的方式设计和记录系统的标准语言。它有九种图,可以在设计文档中使用,以表达软件架构的设计。
(I) 您能解释一下用例图吗?
用例图从用户的角度回答系统做什么。用例回答“系统会做什么?”。用例主要用于需求文档,以清晰地描绘系统。用例场景有三个重要部分:参与者(actor)、用例(use case)和场景(scenario)。
场景 (Scenario): 场景是当用户与系统交互时发生的一系列事件。
参与者 (Actor): 参与者是系统的“谁”,换句话说,就是最终用户。
用例 (Use Case): 用例是最终用户执行的任务或目标。下图“用例”展示了一个简单的场景,包含“参与者”和“用例”。场景代表一个会计在系统中录入账目数据。由于用例代表执行的动作,它们通常由强动词表示。
参与者由简单的火柴人表示,用例由椭圆形表示,如下图“用例”所示。
图:用例
(I) 您能解释一下主参与者和次参与者吗?
参与者进一步分为两种类型:主参与者和次参与者。主参与者是主动参与并发起用例的用户,而次参与者是被动参与用例的参与者。
(I) 一个简单的用例是什么样的?
用例在任何需求文档中有两种表示视图。一种是用例图,另一种是关于用例如何工作的详细步骤表。因此,它们是成对出现的:首先用例图显示概述,然后一个表格详细解释。下面是一个简单的“登录”用例,以图示方式显示,然后是一个包含执行用例步骤的详细表格。
图:登录用例
用例 | Rel001 |
用例名称 | 登录 |
描述 | 此用例描述了用户如何登录聊天应用程序的流程。 |
主参与者 | 简单聊天用户。 |
触发器 | 用户在浏览器URL中输入聊天应用程序。 |
前提条件 | 不适用 |
假设 | 目前系统中没有密码 房间将保持不变,如本文档的假设部分所述 |
失败的结束条件 | 聊天应用程序不允许重复的用户名。 |
操作 | 用户点击登录按钮。 |
主场景 |
|
操作 | 不适用 |
备选场景 | 不适用 |
成功场景 | 1. 打开所选房间的页面,可以看到其他用户名和他们的消息。 |
注意事项和待解决问题 | 不适用 |
表:登录用例表
注意:你可能在想为什么我们需要这对组合,为什么不只显示一个用例表?用例图擅长展示用例之间的关系,并且提供高层概览。用例的表格解释则详细描述了用例。因此,当开发人员或用户阅读需求文档时,他们可以通过查看图表获得概览,如果他们感兴趣,可以阅读用例表以获取更多详细信息。
(I) 您能解释一下用例中的“扩展”(Extend)和“包含”(Include)吗?
“扩展”(Extend)和“包含”(Include)定义了用例之间的关系。下图“扩展和包含”展示了这两个基础概念如何在项目中实现。下面的用例描述了一个用于维护客户的系统。当成功添加客户时,应向管理员发送电子邮件,告知已添加新客户。只有管理员有权修改客户。首先,我们定义扩展和包含,然后看看它们如何适应这个用例场景。
包含 (Include): 包含关系表示一个用例被另一个用例调用。如果从编码角度来看,它就像一个函数被另一个函数调用一样。
扩展 (Extend): 这种关系表示扩展用例与基本用例完全相同,只是在扩展用例中会插入一些新的步骤。
下图“扩展和包含”显示,“添加客户”与“添加折扣客户”相同。“添加折扣客户”有一个额外的过程,即为折扣客户定义折扣,而简单客户则没有此项。项目的一个需求是,当我们添加客户时,系统应发送电子邮件。因此,在通过“添加简单客户”用例或“添加折扣客户”用例添加客户后,都应调用“发送电子邮件”用例。因此,我们使用带有“<
图:扩展和包含
注意:在“扩展和包含”图中需要注意的一点是,我们定义了简单用户和管理员用户之间的继承关系。这也有助于我们定义简单用户和管理员用户之间关系的技??术路线图。
(I) 您能解释一下类图吗?
类图
类(Class)基本上是一个帮助我们创建对象的原型。类定义了项目的静态结构。一个类代表一个对象的族。通过使用类,我们可以创建统一的对象。
在下图 you can see how the class diagram looks. Basically there are three important sections which are numbered as shown in the below. Let’s try to understand according to the numbering
- 类名 (Class name): 这是类的第一个或最上面的部分,它代表类的名称 (clsCustomer)。
- 属性 (Attributes): 这是类的第二个或中间部分,它代表系统的属性。
- 方法 (Methods): 这一部分包含对属性执行操作的方法。
图:类的三个部分
接下来我们将看看这些类之间的关联关系。
(B) 在类图中,我们如何表示私有、公有和保护成员?
为了在类图中表示属性和方法的可见性,我们需要在每个属性和方法旁边放置符号,如下图“私有、公有和保护”所示。“+”表示公有属性/方法。“-”表示私有属性,意味着它不能在类外部访问。“#”表示保护/友元属性。保护属性只能在组件内部看到,不能在组件外部看到。
图:私有、公有和保护
(I) 类图中的关联(associations)是什么意思?
类图中的关联
单个类无法代表项目中的整个模块,因此我们需要一个或多个类来代表一个模块。例如,“客户详情”模块不能仅靠客户类来完成,要完成整个模块,我们需要客户类、地址类、电话类,简而言之,类之间存在关系。因此,通过对类进行分组和关联,我们创建模块,这些被称为关联。为了关联它们,我们需要在类之间绘制带箭头的线,如下图所示。
在图“订单由支付类支付”(Order is paid by payments class)中,我们可以看到订单类和支付类以及带箭头的线,表示订单类是通过支付类支付的,换句话说,订单类将由支付类用于支付订单。从左到右的箭头基本表示了订单类使用支付类的流程。
如果支付类使用订单类,则标记箭头应从右到左,表示流程方向。
图:订单由支付类支付
有四种符号表示流程:
图:UML中的方向符号
多重性 (Multiplicity)
多重性可以被定义为类具有多个关联,或者一个类可以链接到许多其他类的实例。如果您查看下图,客户类基本上与地址类相关联,并且还可以观察到符号(*、0 和 1)。如果您查看右侧,(1….*)符号表示在客户类中可以存在至少一个或多个地址类的实例。现在向左看,我们有(0….*)符号,表示地址类可以独立于客户类而存在,或者许多客户类可以与其链接。
为了表示类的多重性,我们必须显示如下图所示的符号,如(1….*)、(0….*)。
注意:“*”表示“多”,而“(0, 1)”分别表示“零个或至少一个”。
图:类中的多重性
(I) 您能解释一下类图中的聚合(aggregation)和组合(composition)吗?
在这种关联中,主要有两种类型:聚合关联(Aggregation Association)和组合关联(Composition Association)。
聚合 (Aggregation) 关联表示整体对象可以独立于聚合对象而存在。例如,在下图中有三个类:大学类、系类和教授类。大学可以没有系而存在,这意味着当系关闭时,大学也会关闭。换句话说,大学的生命周期依赖于系的生命周期。
在同一张图中,我们定义了系和教授之间的第二种关联。在这种情况下,即使教授离开了系,系仍然存在,换句话说,系不依赖于教授,这称为组合关联(Composition Association)。
注意:实心菱形表示聚合,空心菱形表示组合。您可以在下面的图中查看更多详细信息。
图:聚合和组合的应用
(A) 什么是组合结构图(composite structure diagram)和类图中的自关联(reflexive association)?
组合结构图 (Composite structure diagram)
当我们尝试在一个完整的项目中展示聚合和组合时,图会变得非常复杂,为了保持简单,我们可以使用组合结构图。在下图 we have shown two diagrams one is normal diagram other is Composite structure diagram and the simplicity can easily be identified. In the composite diagram the aggregated classes are self contained in the main class which makes it simpler to read.
图:组合结构图
自关联 (Reflexive associations)
在许多情况下,您需要显示同一个类的两个实例彼此关联,这种情况称为自关联。例如,下图显示了实际项目中的自关联。在这里,您可以看到客户类有多个地址类,地址可以是总部、公司总部或区域办事处。其中一个地址对象是总部,我们链接了地址对象以显示自关联关系。这就是我们可以阅读图表的方式:区域地址对象被零个或一个总部对象实例阻塞。
图:自关联
(I) 您能解释一下业务实体类(business entity)和服务类(service class)吗?
业务实体对象(Business entity objects)表示持久信息,如数据库表。为了使我的观点更清晰,它们只代表数据,本身不包含业务验证。例如,下图“业务实体与服务”(Business entity and service)显示了一个简单的客户表,包含三个字段:“客户代码”、“客户地址”和“电话号码”。所有这些字段都是“ClsCustomer”类中的属性。因此,“ClsCustomer”类成为业务实体类。业务实体类本身不能做任何事情,它只是数据的占位符。在同一张图中,我们还有另一个类“ClsServiceCustomer”。该类聚合了业务实体类,并执行“添加”、“下一个”(移至下一条记录)、“上一个”(移至上一条记录)和“获取项”(根据条件获取客户实体)等操作。
通过这种方法,我们将数据与行为分开了。服务代表行为,而业务实体代表持久数据。
图:业务实体与服务
(I) 您能解释一下系统实体类(system entity)和服务类(service class)吗?
系统实体类(System entity class)表示与系统相关的持久信息。例如,在下图“系统实体与服务类”(System entity and service class)中,我们有一个系统实体类,它表示系统注册表中“登录日期”(loggedindate)和“登录时间”(loggedintime)的信息。系统服务类有两种形式:一种是作为系统实体类中的包装器,为持久的系统实体数据表示行为。在图中 you can see how the ‘ClsAudit’ system entity is wrapped by the ‘ClsAuditSytem’ class which is the system service class. ‘ClsAuditSystem’ adds ‘Audit’ and ‘GetAudit’ behavior to the ‘ClsAudit’ system entity class.
图:系统实体与服务类
系统服务类的另一种形式是操作非持久信息。第一种形式操作持久信息。例如,下图“非持久信息”(Non-persistent information)显示了“ClsPaymentService”类如何操作支付网关来检查卡是否存在、卡是否有效以及卡上有多少金额?所有这些信息都是非持久的。通过将非持久数据的逻辑分离到系统服务类中,我们提高了项目的可重用性。
图:非持久信息
注意:上述问题可能会在面试中从你如何分离行为与数据的角度被问到。问题通常会以扭曲的方式提出,例如“你是如何分离行为与数据的?”。
(B) 您能解释一下泛化(generalization)和特化(specialization)吗?
泛化与特化 (Generalization and Specialization)
在泛化与特化中,我们定义类之间的父子关系。在许多情况下,你会发现一些类具有相同的属性和操作,这些类被称为超类(super class),之后你可以从超类继承并创建子类(sub classes),子类拥有自己的自定义属性。下图展示了泛化与特化关系的三个类。所有电话类型都有电话号码作为泛化属性,但根据是座机还是手机,你可以有作为特化属性的有线或SIM卡连接。在此图中,clsphone 代表泛化,而 clslandline 和 clsmobile 代表特化。
图:泛化与特化
(B) 我们如何表示UML中的抽象类(abstract class)和接口(interface)?
接口(Interface)在类图中用“<
图:接口的应用
抽象类(Abstract classes)用“{abstract}”表示,如下图“抽象类的应用”(Abstract classes in action)所示。
图:抽象类的应用。
(B) 我们如何实现泛化和特化?
通过使用继承。
(I) 您能解释一下UML中的对象图(object diagrams)吗?
类图显示了系统的静态性质。从前面的问题,你可以轻易地判断出类图显示了类型以及它们如何链接。类只有在创建对象后才能“活”过来。对象图在任何时间点上对类图进行图形化表示。下图“对象图”(Object diagram)展示了当实际对象被创建时,一个类是什么样子。我们展示了学生和课程之间的简单关系。所以一个学生可以选修多门课程。类图用多重性关系展示了这一点。我们也展示了当使用对象图创建对象时,类图是什么样子的。我们用“对象名: 类名”(Object Name: Class Name)来表示对象。例如,在下图 we have shown ‘Shiv : ClsStudent’ i.e ‘Shiv’ is the object and ‘ClsStudent’ the class. As the objects are created we also need to show data of the properties, the same is represented by ‘PropertyName=Value’ i.e. ‘StudentName=Shiv’.
图:对象图
图还表明,“ClsStudent”可以申请多门课程。在对象图中,我们通过显示两个对象来表示这一点,一个对象是“Computer”,另一个对象是“English”。
注意:对象图只应用于表示对象之间复杂的关系。它也有可能使你的技术文档变得非常复杂。所以要谨慎使用。
(I) 您能解释一下顺序图(sequence diagrams)吗?
顺序图 (Sequence diagrams)
顺序图显示了对象在特定时间段内的交互。下图“顺序图”(Sequence diagram)展示了顺序图是什么样子的。在这个顺序图中,我们有四个对象:“客户”(Customer)、“产品”(Product)、“库存”(Stock)和“支付”(Payment)。消息流以瀑布式垂直显示,即从顶部开始流到底部。虚线表示对象存在的持续时间。虚线上的水平矩形表示对象的激活。从一个对象发送的消息用实心箭头和实心箭头头表示。返回消息用虚线箭头表示。因此,下图显示了这四个对象之间的交互顺序:
- 客户对象向产品对象发送消息,询问产品是否可用。
- 产品对象向库存对象发送消息,查看产品是否存在于库存中。
- 库存对象回答“是”或“否”。
- 产品对象将消息发送给客户对象。
- 然后客户对象向支付对象发送消息以支付款项。
- 支付对象随后向客户对象发送收据。
需要注意的一点是,当支付活动发生时,产品和库存对象处于非活动状态。
图:顺序图
顺序图中的消息
顺序图可以表示五种不同类型的消息。
同步和异步消息
同步消息用实心箭头头表示,而异步消息用细箭头头表示,如下图“同步和异步”(Synchronous and Asynchronous)所示。
图:同步和异步
递归消息 (Recursive message)
在我们遇到需要表示递归调用的函数和子例程的场景时。递归是指方法调用自身。递归消息用大矩形内的小矩形表示,并有一个从大矩形到小矩形的箭头,如下图“递归消息”(Recursive message)所示。
图:递归消息
消息迭代 (Message iteration)
消息迭代表示活动序列中的循环。下图“消息迭代”(message iteration)显示了“订单”如何在一个循环中调用“订单项”(orderitem)对象来获取成本。要表示循环,我们需要写“For each <
图:消息迭代
消息约束 (Message constraint)
如果我们想表示约束,它会被放在方括号内,如下图“消息约束”(message constraint)所示。在下面的“消息约束”图中,“customer”对象只能在客户年龄大于 10 岁时调用“book tickets”。
图:消息约束
消息分支 (Message branching)
下图“消息分支”(message branching)显示了“customer”对象有两种分支:一种是当客户调用保存数据时,另一种是当他取消数据时。
图:消息分支
实际进行顺序图
让我们以一个简单的例子来实际理解顺序图。下面是一个简单的账单录入屏幕,用于账目数据录入。会计师录入账单的步骤如下:
- 会计师加载账单数据录入屏幕。账单屏幕加载,其中借记科目代码和贷记科目代码分别在组合框中。
- 然后会计师填写账单的所有详细信息,如账单描述、日期、借记科目代码、贷记科目代码、描述和金额,然后点击“添加账单”按钮。
- 一旦点击“添加账单”,它将出现在屏幕下方的网格中,并且账单录入屏幕将被清除,等待添加新的账单。在此步骤中,账单未添加到数据库,仅在集合中。
- 如果还有更多账单要添加,用户会再次填写账单并点击“添加账单”。
- 所有账单添加完毕后,用户点击“提交账单”,该组账单最终被添加到数据库。
下图“账单数据录入屏幕”(Voucher data entry screen)以图形方式展示了屏幕的外观。
图:账单数据录入屏幕
图“账单数据录入顺序图”(Voucher data entry sequence diagram)展示了顺序图的外观。下面的图显示了上述屏幕如何从用户界面流到数据访问层的完整顺序图视图。顺序图中有三个主要步骤,让我们一步一步地理解它们。
步骤 1:- 会计师加载账单数据录入屏幕。从账单数据录入屏幕图像中,您可以看到我们有两个组合框:借记和贷记科目代码,它们由 UI 加载。因此,UI 调用“科目主数据”(Account Master)来加载科目代码,该代码又调用数据访问层来加载会计代码。
步骤 2:- 在此步骤中,会计师开始填写账单信息。此步骤中要注意的重要一点是,在添加了一个账单后,有一个条件语句,询问我们是否要添加新账单。如果会计师想要添加新账单,他会再次重复顺序图中的步骤 2。需要注意的一点是,账单并未添加到数据库,而是添加到账单集合中。
步骤 3:- 如果没有更多账单,会计师会点击提交,最终将整个账单添加到数据库。我们使用了顺序图的循环来展示整个账单集合是如何添加到数据库的。
图:账单数据录入顺序图