Featured image of post 什么是事件建模Event Modeling?

什么是事件建模Event Modeling?

基本概念

事件建模(Event Modeling)是一种描述系统的方法,展示信息如何随时间变化的例子。具体来说,这种方式省略了瞬息万变的细节,而着眼于在任何特定的时间点上的持久化存储和用户所见数据的变化。这些时间轴上的事件,构成了对系统的描述。

近年来,很多系统使用事件通过事件存储数据库或者使用特定方式使用常规数据库构建了状态和信息传播的模块。然而,大多数方法仍然依赖于通过SQL数据库、文档数据库或者其他技术实现严格意义上的当前时间点信息的视图。

对很多系统而言,特别是对于非小型系统而言,随着系统复杂性的增加,变更成本将会随着时间的推移难度指数级上升。与现有的设计和建模方式对比,事件建模可以在短时间内创建一个基础蓝图,将返工工作量降到最低。

从过去谈起

讲故事自古以来就是人类能够将知识传递给后代的方法,它在很大程度上依赖于我们如何存储记忆-无论是逻辑的、视觉的、听觉的还是其他的。这一点很重要,因为这与信息系统的构建方式有相似之处。 用具体的例子说明某物应该如何工作是一种常见的方式。这种方式可以在软件开发的成功实践中看到,如行为驱动开发。这种方式很有效,因为我们通过故事来沟通更有效。将它和讲故事联系在一起,是一种保持社会信息的方式。我们的大脑是为它而建的,而不是为流程图和其他格式而建的。 而事件建模模型就是遵循这种讲故事模式而建立的产品建模方式。

事件建模模式

时间线是最好描述故事主线的方式,对我们的系统而言,时间线也是描述我们系统核心部分概念的重要组成部分。我们可以通过在一条时间线上,系统从开始到结束,在没有分支情况下应该做什么方式展示我们系统的一部分功能。这就是一个典型的事件模型的组成。我们可以用这种方式跟踪所有UI界面中字段值如何存储和如何展示的。比如在上面的示例图中,我们使用了3种不同模块的内容和传统的线框模型就展示了整个系统的模型。但是简单性是我们重要的一个目标,因此我们只依赖于4种模式构建这种模型图。

保持简单性

当我们想采用某些做法或流程来帮助彼此理解和沟通时,它与个人为熟练掌握这些方法而进行的学习量成反比。换句话说,如果我们可以更快的掌握一个名叫X的方法时,我们就可以更好的通过这种方式进行知识分享和互动;反之,无论这种方法多么好,昂贵的学习成本总会搞砸一切。

当一本书是团队中的必读书目时,每个人都会说他们读过;但事实上只有一半的人会真正读过;这些真正读过的人中一半的人会声称他们理解了这本书;而这些声称理解的人中只有一半的人真正的理解了这本书;而这些真正理解了这本书的人只有一半的人能够使用它。

这就是为什么使用3个模块和基于2个想法的4种模式进行事件建模。因为这只需要几分钟就可以将所有的东西向所有人解释清楚。其他的学习则可以在实践中进行。即便理解出现了不足和错误,也可以很快在实践中得到纠正。

事件

假设我们想为连锁酒店设计一个酒店网站,让我们的客户可以在线预订房间,并让我们安排清洁和任何其他酒店问题。 我们可以显示在该业务的年度时间线上存储了哪些事件。 我们可以假装我们已经有了这个系统,然后问自己随着时间的推移存储了哪些事件。

线框图

让我们看一下在图片的最上面的部分的第一个模块。为了让讲故事这个事情更加可视化,我们可以在顶部显示功能的线框图或者网页模拟图。这也可以被具象化为具体的泳道图,以方便不同的人(也可以是系统)与我们的系统进行互动。这里一些自动化的内容可以用齿轮表示,同时说明系统正在做什么。通过这种方式,我们可以非常容易的展示出系统需要实现的功能列表,执行流程和项目完成标记。这里的图是示例了一个酒店的预订、支付和通知系统的过程,我们可以重点关注一下所有相关高亮显示的内容。

借助这个模块,我们可以很方便的和设计师一起沟通设计系统,当然,这里需要注意在设计中,两个重要的内容需要添加到整个设计中:用户所拥有的权限和用户可以获取的信息。

命令

大多数信息系统必须给用户一种影响系统的状态的能力,而这种能力就是命令。在我们的例子中,我们必须允许房间预订改变系统状态,这样我们就不会发生超额预订情况。当那个人在未来的预订日期到达时,他们就有一个为他们准备的房间。

改变系统状态的意图会被封装在一个命令中。相对于简单地将表单数据保存到数据库中的一个表中,这可以让我们以非技术性的方式来显示意图,同时允许任何实现 - 尽管我们可以看到某些方法更具优势。

从UI和UX的角度来看,这就是一个"命令响应式用户界面",对帮助制作可组合的UI大有帮助。使用这种模式,从技术和商业的角度来看,交易的界限就更清楚了。以酒店入住为例,酒店的客人要么登记成功,要么没有。

当命令成功的前提条件有细微的差别时,它们会在"Given-When-Then"风格的描述方式中进行阐述。这种方式也是行为测试模式惯用的描述方式,也是一种成功的讲述故事的方式。实际执行过程中,可能会有几个这样的故事来说明一个命令如何能成功执行和不能成功执行。

这里我们可以用一个例子来描述一下:

Given:我们已经注册并添加了一个支付方式

When:我们试图预订一个房间

Then:一个房间被预订了

这种描述方式也通常被叫做“安排、行动、断言”,在UI/UX的世界中,也被称为“情景、统计、价值”。 在图中我们也可以发现,所有的命令都是用蓝色进行标记的。

视图(或者叫读模型)

任何信息系统的一个重要能力是将系统中保存的状态告知用户。我们的酒店客人需要知道他们感兴趣的某些类型的房间在哪一天可以入住。这通常有很多种情况,需要支持信息系统的多个模型。

随着这些新事件的存储,系统中的视图也会一直变化。在我们的酒店系统中,这个日历视图随着影响库存的新事件的发生而被更新。其他视图中清洁团队可以在客户离店事件存储后在其他视图中看到房间已经可以被清理了。

指定视图的行为方式与我们指定接受命令的方式非常相似,但有一处不同。视图是被动的,并且不能在事件被存储到系统中之后撤销事件。

举个例子:

Given:酒店设置了12间海景房,海景房从4月4日到12日被预订

Then:日历上应该显示除4月4日到12日以外的所有海景房的日期

从上面图中我们也可以注意到,所有的读都是用绿色进行标记的。

集成

我们刚刚介绍了描述大多数系统所需的 4 种模式中的前 2 种模式。 系统可以从其他系统获取信息并且将信息发送到其他系统。 强迫这 2 个模式成为前 2 个模式的扩展并共享相同的空间是很诱人的选择。 然而这会让交流变得更加困难,因为它们没有人类可见的方面,并且需要一些更高级别的模式。

翻译

当我们有一个为我们提供信息的外部系统时,将这些信息转换成我们自己系统中的更熟悉的形式会很有帮助。 在我们的酒店系统中,如果选择让我们的清洁人员反应更加灵敏,我们可以从客人的 GPS 坐标中获取事件。 我们不想使用经度和纬度对作为事件来指定我们系统中的先决条件。 我们宁愿选择对我们有意义的活动,例如“客人离开酒店”、“客人回到酒店房间”。

通常,翻译很简单,可以表示为从外部事件中获取信息的视图。如果我们不将它们用作测试的任何“Given”部分,则它们存储在该视图模型中的值仅在我们的状态更改测试中的命令参数中表示。

自动化

我们的系统一般都需要与外部服务进行通信。当我们酒店的客人在退房时支付住宿费用时,我们的系统会调用付款处理程序。我们可以通过系统中某个处理程序的“待办事项列表”的概念来了解这是如何发生的。这个待办事项列表显示了我们需要完成的任务。例如,我们的处理程序会不时查看该列表(可能是几毫秒或几天)并向外部系统发送命令以处理付款。然后将来自外部系统的回复转换为我们存储回系统中的事件。通过这种方式,我们将系统中使用的构建块保留为对我们有意义的东西。

我们通过在具有线框的蓝图顶部放置一个处理程序来展示这一点。这表明这些东西在屏幕上无法看到但在后台发生。由于需要完成后台任务,用户可能期望旋转图标提示延迟。此规范的形式为“Given:要执行的任务的视图,When:每个项目启动此命令时,Then:这些事件会返回。”

实际上,这些可以通过许多不同的方式实现,例如队列、响应式或实时构造。它们甚至可能是我们使用的待办事项列表。这里的目标是传达我们的系统在需要影响外部时是如何与之沟通的。

落地实现

事件建模分7个步骤进行。我们已经解释了最终的目标。因此,让我们倒退到开头,展示如何建立起蓝图。

头脑风暴

我们让某人解释项目的目标和其他信息。然后,参与者设想系统的外观和行为是什么样的。他们写下所有他们能想象到的发生的事件。在这里,我们只需要明确改变了状态的事件。这些所有的事件一定要意味着某些状态的变更,如果没有发生变更,那么他们就不是事件。比如,有人会说出"客人查看了房间的可用日历",那么这个就不是事件。

阐述剧情

现在的任务是用这些事件创造一个合理的故事。因此,它们被排列成一条线(也就是时间线),每个人都检查这条线,以了解这条时间线作为按顺序发生的事件是合理的。

制作故事

接下来,需要制作故事的框线图或模拟图,用可视化帮助初学者上手。更重要的是,每个领域都必须被表示出来,这样系统的蓝图就可以从用户的角度来表示信息的来源和目的地。

UX并行

线框图一般被放在蓝图的顶部。如果有超过一个用户的话,它们可以被分成独立的泳道,以显示每个用户看到的东西。这里需要注意我们需将系统的每个变化转化为蓝图的单独一列,因此屏幕不能出现垂直重叠的情况。不同的排序可以显示在各种详情中。如果它是系统的核心或非常重要的交互,则需要在蓝图中添加备用的工作流程。这是显示部分的最后一步,但如果有帮助的话,可以提前完成。

鉴别输入

从前面的部分我们看到,我们需要展示我们如何让用户改变系统的状态。这通常是我们引入蓝框的步骤。每次由于用户的操作而存储了一个事件时,我们通过一个命令将其与UI联系起来,如果是一个网页程序,这个命令展示了我们从屏幕上获取或隐式的从客户端状态得到的信息。

鉴别输出

再次回头看一下我们的蓝图目标,我们现在必须通过视图(又称读模型)将通过存储事件积累的信息链接到用户界面。这些可能是像酒店系统中的日历视图一样的东西,当用户想要预订房间时,它将显示房间的可用性。

应用康威定律

现在我们知道了所有的信息是如何进出我们的系统的,我们可以开始研究将事件本身组织成泳道。我们需要这样做,以便让系统的模块作为一组独立团队可以拥有的自主部分而存在。这允许专业化发生在我们控制的水平上,而不是脱离团队的组成。详见梅尔康威的康威法则

精心设计场景

每个工作流程步骤都与一个命令或一个视图/读模型相联系。前面已经解释了这些规范。我们如何制定它们,仍然是与所有参与者合作进行。一个Give-When-Then或Given-Then可以在快速的构建的同时被多个角色进行审查的。这使得传统上由专门的产品负责人以文本格式单独完成的用户故事写作,可以在极短的时间内以可视化的方式协作完成。更为关键的是,每个定义都与一个命令或视图相关联。

完整性校验

事件模型应该有每一个字段的说明。所有的信息都必须有一个起点和一个终点。事件会促进这种转换,并包含必要的字段来实现这一目标。这种严格性是使用该技术的最大好处。

这方面的一个变种是,我们不做这个最后的检查,在某些情况下,这也是可以的。

项目管理

如果完成的足够良好,我们制作出的是一组包含每个工作流程所有场景定义的足够小的组合。他们可以直接转化为开发人员的开发内容和测试内容,并且只与约定部分和相邻工作流程相耦合。

明确的约定

许多项目管理、业务和协调问题都因为我们对工作流的某一步骤开始时的信息形状和完成时的数据形状做了明确的约定而得到缓解。这些事前和事后的条件是允许工作在相对孤立的情况下完成,并在之后按照设计与相邻的步骤结合在一起。

平坦的成本曲线

使用事件建模的最大影响是可以建立一个平坦的成本曲线。这是由于建立每个工作流程步骤不受其他工作流程开发的影响。需要理解的一件事是,如果一个工作流程步骤使用了相同的命令或视图,那么它就可以被认为是在事件模型上的重复。

这一点的影响是非常深远的,因为它是将软件开发重新变为工程实践的原因。它使创建一个信息系统的工作像建造房子一样。功能可以以任何顺序被创建。传统的开发不能依靠估算,因为功能是否在项目的早期和后期所需的工作量会随着系统的复杂度而被影响。重新确定工作的优先次序使得以前的估算变得不可靠。

真正的完成就是要正确的完成

当一个工作流程步骤被实现后,实现任何其他工作流程步骤的行为都不会导致需要重新调整这个已经完成的工作流程步骤。这也是恒定特征成本曲线能够实现的原因。

没有估算的估算

有了恒定成本曲线,一个团队的开发可以简单地通过许多功能在一段时间内进行衡量。这是一种相对公平的方式,可以凭经验确定团队的速度。这些数字在之后可以被用来确定未来项目的范围、进度和成本。

关于测试驱动开发

这是行业内采用敏捷实践带来的影响,就像将创可贴贴在缺乏设计的核心问题上。因为现在每个团队需求的范围都是按工作流程步骤进行的,所以TDD的重构步骤不会影响事件模型中的其他工作流程步骤。当我们没有事件模型的时候,重构就可以不受限制地进行,以前完成的工作片段就需要进行调整。已经完成的工作越多,在我们构建解决方案的过程中,每一个新增加的工作都会被审查和调整。

项目外包

恒定成本曲线给了制定固定成本项目的机会。一旦有了一个团队的开发速度,你就可以明确团队的软件的成本。有了这个数字,你现在就可以为你愿意给外包厂商完成的每个工作流程步骤的报酬定价了。

产出保证

由于每个工作流程步骤都受到保护,不受其他工作流程步骤的影响,因此,任何缺陷都将由谁为它们提供非计费工作来保证。因此,如果一个外包商只是为了快速完成更多的可计费项目而做得不好,他们就必须让接下来的工作时间专门用来修复之前已经完成的工作的缺陷。这就平衡了他们的有效工资率,因为他们不是在做新的应交付的工作。

这可以通过不同的绩效检查点来提供这些指标,在员工参与的过程中长期进行下去。

由于有效薪酬可以根据个人的能力进行自我调整,这也是一种让新员工入职的方式,在他们处于试用阶段的时候,对他们进行公平的支付。这种从合同到雇佣的过程消除了技术职位的主观和基本无效的面试过程。

确定优先顺序

在不改变每个项目的估计成本的情况下,在时间表上移动工作,即哪些步骤要先实施。这确保了工作的优先次序对总成本没有影响。恒定成本曲线的要求是允许这种重新确定优先次序的 “敏捷性”。

变更管理

当计划改变时,我们只需调整事件模型。这通常是通过直接复制当前的内容并进行调整来实现的。这样,我们就可以直观的看到差异在哪里。如果一个事件中加入了新的信息,这就构成了创建该事件的工作流程的新版本。视图也一样。如果这些还没有开发,那么这就不会改变我们的计划。如果它们已经开发了,它们就会给我们的开发计划增加另一个实现单元,它被认为是对原有流程的一种替换。围绕这一点还有一些规则。最终的结果是为变更管理提供一个明确的指南。

安全性

有了事件模型,该方案可以准确地显示敏感数据在哪里,同样重要的是,敏感数据何时越界。在传统的审计中,与员工面谈的次数很耗时,而且有可能错过重要的领域。当应用程序有一个事件模型作为参考时,安全问题就能够得到最有效的保障。

遗留系统

大部分组织所面临的情况是大多数系统已经存在了。处理一个因为复杂和缺乏理解而难以管理的系统的主要方法是重写它或在它运行时重构它。这两种做法的代价都是非常昂贵的。

其实还有第三个风险较小的选择。冻结旧系统。在适当的支持下,团队可以不再考虑变更现有的系统。相反,处理错误和增加新的功能是作为sidecar方式来完成的。

可以从旧系统的数据库中收集事件,并制作该状态的视图–采用前面描述的翻译模式。用户行动的Y型阀重定向可以在侧面解决方案中增加新的功能。一个修复了一个错误的例子(注意,我们采用了外部集成模式,并对旧系统进行了扩展,增加了资料图片,如图。)

这种模式可以让团队停止将精力浪费在现有的系统上,并能够通过实现事件模型的模式解除遗留系统对快速交付价值的阻碍。

Built with Hugo
主题 StackJimmy 设计