本文更像是一篇白话了的论文,也希望如此,你可以点击阅读原文以关注本文的更新。
我们一直在考虑的其实是一个终极问题:到底如何最大限度复用。在 PowerBI 中处理这类问题主要涉及两件事:业务逻辑的处理以及可视化的处理。在实践中常常表现为以下问题:
- 客户需求变化了,怎么办?
- 几十页的报告,上百的度量值怎么管理?
- 删除一个可视化图表时,为它而做的度量值是否可以安心删除? (如果其他地方在用就不能删除,但你不知道)
- 为了做一个图,要做一个辅助表; 那为了做100个图呢,辅助表巨多,怎么管理?
- 如果客户有一个展现原型,是否可以对着展现原型分工制作报告?
- 如果某个度量值发生变化,如何确保与其关联的度量值以及可视化都是正确的?
- 诸如: 对某类别按子类别市场所选元素的产品销售占有率 这种很长的逻辑命名如何处理?
- …
这些问题随着制作的 PowerBI 文件逐渐复杂,也就越来越严重,严重到需要:推倒重来。也就是说,到底应该如何正确地设计 PowerBI 报告,不会出现推倒重来,且可以可持续可应对变化地迭代推进复用呢?
这个问题才是作为 PowerBI 设计师需要思考的终极问题。当然,这在其他领域也很常见,如:建筑领域,软件工程领域等。那些领域更加成熟,也有着成熟的解决方案,而我们大可以将其他领域的成果移植到 PowerBI 领域,而本文正是一次这样的实践。之所以称为导论,是因为在这个导论下,我们会持续展开出很多细节,包括各种原则,各种套路等。
引子
罗叔在以前的很多文章中冒出过以下字眼:设计模式,非侵入式设计,MVC 模式,开放闭合原则,依赖注入等。这些其实都从属于一个体系:设计模式。本文将作为一个体系的开篇,给出一个 设计模式 的框架:PowerBI DAX MVC 设计模式。MVC 模式并不是用来解决用户做一个图的问题,而是用来系统化解决自助数据建模的整个工程流程,尤其是面对N页(如:50页),多种业务计算(如:上百度量值)的情况。
设计模式(Design Pattern),在软件领域是一个非常重要的概念。而 MVC 模式,可以说是模式的模式,本文将论述如何在 PowerBI 中实现 MVC 设计模式。MVC 设计模式具有非常强的通用性,此前,我们很多设计都采用了 MVC 设计模式,以保证 PowerBI 的建模设计可以应对变化,保持稳定。
虽然 MVC 设计模式来自于软件领域,也不是面向业务人员的,但罗叔就是要将复杂的概念简化,并让业务人员可以生搬硬套,并逐渐体会设计模式的好处。注意,这里并非学习笔记,也不是翻译,作为科班出身的罗叔,将站在不同领域前人基础上,基于成熟的软件工程,面向对象思想,PowerBI 大量实践总结后,推出这套原创体系。首先,罗叔会在公众号分享这个系列,相关的文件和视频讲解会作为订阅会员的内容。随后,我们会推出一个专题课程,更加系统性地讲解这个体系,从一定意义上说,可以深刻理解设计模式并运用于 PowerBI DAX,将达到的状态是:对于任何一个业务问题,如果 PowerBI DAX 可以解,那设计师就可以做出来;反之,如果设计师无法按照设计模式实现某个问题,那该问题也就不是 PowerBI DAX 可以解的。是不是够牛X的,是不是吹牛,让我们从本文慢慢开始体会吧。
关于设计模式
作为业务人员,可能这是一个新鲜的概念;而作为开发人员,设计模式几乎是一个分水岭,理解并使用设计模式标志了开发进入了一个正确的轨道。如果没有听说过设计模式,也一定听说过商业模式。从本质上来看,设计模式与商业模式一样,指的是某种场景下重复出现某类问题的成熟应对方案。也就是人们常说的套路。
在 PowerBI DAX 领域,由两位意大利老师(马克·啰嗦以及法拉利)在 2015 年给出了一些参考,并形成了一个网站以及一本书:https://www.daxpatterns.com/
该书很有意义,即使是现在也有很重要的参考意义。另外,两位意大利老师应该会重写该书,具体发布时间未知。
不过这并不重要,罗叔将会在战友联盟平台相继推出 PowerBI DAX 设计模式 系列。我们这里的设计模式绝非对意大利老师所提及的设计模式的简单参考或重复,而是全新的更加透彻的思想提炼,你将在全网范围首次看到如何将软件工程领域的成熟思想和解决方案平滑地在 PowerBI DAX 中实现,本文将让你看到虽然也许你已经学习了很多 PowerBI 课程,但一切才刚刚开始。能够驾驭本文所提出的问题以及涉及到的概念并帮助我们成为更加专业的设计师。
设计模式,作为白话理解的套路,就像下棋的棋谱:
作为棋谱,它会告诉你在某种场景下,每一步要怎么走,就是说套路并不是一招,而是一步一步的招数的相继组合。那么,DAX 设计模式也不是一个函数,而是为了解决某个场景的函数的连续使用方案。
那么,最重要的问题来了,设计模式有什么好处?作为棋谱或者套路,设计模式是帮助你可以解决重复出现的类似问题的通用解决方案。就类似于,中学时的方程,一上来管它三七二十一,设X,然后再说。设计模式,将给出你在 PowerBI DAX 中几乎所有问题的通用解决方式。更为重要的是,这里面所提出的一些原则,不仅仅适用于软件领域,PowerBI 报表设计领域,还适用于平时的企业管理等,你这需要领会精神就可以举一反三。
MVC 设计模式
MVC 模式(Model–View–Controller)来源于软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。罗叔没有必要展开让大家去理解软件工程,但如果你用过 PowerBI,你会马上发现,在 PowerBI 中使用 MVC模式 是自然而然的。
先来具体说明下什么是 PowerBI 中的使用 DAX 时的 MVC,一个示意图如下:
- 控制器(Controller): 即度量值,本质是计算逻辑。
- 视图(View): 用户可以看到的可视化部分。
- 模型(Model): 与分析主题相关的主体数据表及关系。
为了可以更加形象地理解这个过程,我们先看一个案例:
这是一个典型的 PowerBI 报告,从表面看不出什么不同,其不同在于它的打造方式是按照 MVC 模式来进行的,如下:
不难看出,这里使用了典型的 PowerBI 内置的一些构建元素,如:表,度量值,度量值文件夹,然后其组织方式是不同寻常的。
- 在 #Controllers 中,放置了与业务逻辑有关的度量值。
- 在 #Views 中,放置了与视觉展现有关的度量值。
- 以 Model_ 前缀开头的表,构成了主体数据模型。
以上三点是约定,罗叔在设计这套模式的时候本着:约定胜于配置的原则。这些并不是制作 PowerBI 报告时候的强制要求,但罗叔发现这些的习惯和约定在设计大型 PowerBI 项目时非常受用。
在 PowerBI 的2019年8月 更新后,由于视觉对象编组的出现,将 MVC 设计模式的实际可行性变得更强,我们看下它们是如何结合的:
可以看出,在某个页面中的 Chart 与度量值的对应关系,如下:
这样,很清晰地讲可视化与呈现可视化的度量值完成的对应。
PowerBI 工程
在真实的大型项目中(非常常见),目前没有任何教程来指导如何套路式地开展一个大型 PowerBI 报告项目。首先,罗叔根本不认为 PowerBI 是一个报告,也许那是其他 BI 报告工具的合适称呼,但在 PowerBI 身上并不适用。我们称一个 PowerBI 文件为一个 PowerBI 工程。
而 MVC 架构设计,正是为了流畅地处理这个工程的套路。先来看下一个 PowerBI 工程(报告)的组成部分。如下:
这应该是你首次见到这样的 PowerBI 工程模型,我们依次讲解如下:
- PowerBI 工程: 与一个 PowerBI 文件对应。这是一个逻辑概念,从一个很小的报告文件到一个很大很复杂的报告文件,都可以是工程,在应对大型 PowerBI 文件时,用工程的思路将更有助于设计师完成好的设计以及持续的改进和管理维护,应对变化。
- 一般地,一个 PowerBI 工程应该集中解决一类业务问题。
- PowerBI 报告: PowerBI 的可见部分,被包含在一个 PowerBI 文件中。
- PowerBI 页面: PowerBI 报告的组成部分,一个 PowerBI 报告内含多个 PowerBI 页面。
- PowerBI 可视化元素: 又称 PowerBI 可视化对象,是可以独立管理的最小可见元素,一个 PowerBI 页面内含多个 PowerBI 可视化元素。 如: 图表,表格,切片器,图形,按钮等。
- 数据模型: 需要解决业务问题所需要的表及其关系。 注意: 数据模型与业务直接相关,而与展示无关。
- 数据模型表: 加载进入数据模型的表。 一个数据模型中有多个数据模型表。 如: 订单表。
- 度量值: 处理数据的计算逻辑。 分为处理业务逻辑以及处理展现逻辑。 如: 销售额,销售额(考虑总计行)。
- DAX计算-业务逻辑: 为处理业务逻辑而定义的DAX表达式,用来处理业务问题。 如: 销售额。
- DAX计算-展现逻辑: 为处理展现逻辑而定义的DAX表达式,用来处理展现问题。 即: DAX驱动可视化。 如: 销售额(考虑总计行)。
- 视图模型: 需要解决展现问题所需要的表及其关系。 注意: 视图模型与展现直接相关,而与业务无关。
- 视图表: 为辅助展现而定义的表。 一个视图模型中有多个视图表。 如: 年龄分组。
- 参数表: 为辅助计算而定义的表。 一个视图模型中有多个参数表。 如: 计算单位参数表。
虽然 PowerBI 的构件本身是很少的,而为了解决实际的很多问题,罗叔将这有限的物理构件做了体系化的逻辑划分。这样就可以组织并管理不同的目的进而解决不同的问题。
上述对于 PowerBI 工程以及逻辑组成部分的定义是精确的,值得一提的是:
- 这些定义并非是微软官方的,但经过几年实践与观察,这是符合微软设计理念且可持续的。
- 这是对我们此前提出各种设计模式概念的首次正式定义。
- 值得强调的是: 与其他BI工具不同,在 PowerBI 中,将由 DAX 驱动可视化来完成复杂的可视化设计。
- 值得强调的是: 为了配合 DAX 驱动可视化,需要有与之搭配的数据,我们称之为视图模型。
在有了这些定义后,罗叔进而带你更加仔细地来理解这里面的设计思想。
DAX MVC
根据前面的描述,可以有:
其中,箭头表示依赖关系,为了便于理解,你可以读作:会用到。例如:度量值会用到数据模型;可视化会用到数据模型和度量值。
可以看出,这样的设计有一个非常大的好处,那就是:数据模型 不依赖于任何其他部分,这也就是罗叔以前所说过的非侵入式设计。将这个架构更加细分可以得到:
如果考虑到数据源和角色,还可以表示为:
我们将这里涉及到的角色也加入进来,可以看到:
- 数据模型依赖于数据源,从数据源加载数据便可以得到数据模型;
- 业务度量值仅依赖于数据模型,定义业务逻辑;
- 对于最终的可视化来说,数据模型也许不是直接来源,而是视图模型,例如: 年龄分组,就不是数据模型中的表,而完全是为了展现而创建的数据,属于视图模型;
- 为了展现而写的度量值,就是展现度量值,例如: 如果增长就是绿色,否则就是红色等。 它依赖于数据模型、数据模型和业务度量值;
- 最终的可视化由视图模型和展现度量值构成。
如果考虑下角色,可以看到:
- 数据分析师更侧重按照业务逻辑构建数据模型和业务度量值;
- 报表设计师会和用户沟通,用户说我要看到什么样的报告,报表设计师则实现用户的需求;
- 大部分情况下,数据分析师 和 报表设计师是重合的。
值得强调的是,可以注意这里面的依赖关系,这种依赖关系,可以形成良好的层次结构。上层的内容总是依赖于下层的内容,这样,当用户的需求改变时,不需要更改下层的内容,而仅仅需要修改上层的内容即可。这样就将更改限制在了一个有限的范围内。
如何在 PowerBI 中实现 DAX MVC
有了上述的理论讨论和说明,现在可以在 PowerBI 中进行实现。
数据模型
首先,按照常规操作,在 PowerBI 中构建数据模型,如下:
除非你非常清楚自己在干什么,否则请务必遵守以下规则:
- 保持表之间的关系是单向的一对多关系。
- 不同的主题可以用不同的布局来表示。
作为一个约定,可以将数据模型的表名命名为:Model_表名。
业务度量值
作为 Controller 的最组成部分,首先我们需要有个业务度量值表。并将所有业务度量值在其中排列,如下:
业务度量值也会构成一个依赖层级关系,例如:
视图模型与展现度量值
如上所述,视图模型与数据模型最大的不同在于视图模型是为了可视化而存在的,视图模型与展现度量值同时使用,这种结合特别可以反映 MVC 模式的特点:
其中,
- View.AgeGroup 表就不是数据模型表,它仅仅是为了显示年龄分组而存在的,而年龄分组是与业务逻辑没有关系的,属于视图层面。
- 由于该图放置于报告的第三页(P3)且为该页的第一个图(C1),讲放置于 #View 中的展现度量值命名为: View.P3.C1.Sales.ByAgeGroup 也正反应了这个事实。
值得注意的是,这里的 展现度量值 就开辟了 DAX 驱动可视化的思想,在无法用常规方式形成所需要的展现时,一个固定套路就是,将需要的样子依赖的维度放置在那,然后编写展现度量值即可。
视图
在 PowerBI DAX MVC 模型的视图与软件工程中的视图有所不同,DAX构建的视图是用户拖拽产生的 DAX查询而形成,它仅仅依赖于两个物件:维度 与 度量值。其中,维度来自于视图模型(或数据模型),而度量值来自于展现度量值。
如果仅仅显示销售额,也可以使用展现度量值进行包装,例如:
代码语言:javascript复制View.P1.C2.Value = [KPI.Sales]
这样做的好处是,当某个可视化对象被删除时,与之相关的展现度量值也可以被删除,这就解决了海量业务逻辑度量值可能会出现的模型管理问题。让视图仅仅依赖于视图模型和展现度量值,就解除了这种耦合关系。
总结
本文引出了 PowerBI DAX MVC 架构设计模式,其用意是彻底工程式地解决复用问题。
- 控制器:
将度量值看做是控制器,控制计算逻辑;
- 控制业务逻辑的,叫业务度量值;
- 控制展现逻辑的,叫展现度量值;
- 模型:
将数据模型进一步分为:
- 数据模型,仅仅指业务数据模型;
- 视图模型,用来展现所需要的辅助数据;
- 视图:
用户看到的可视化部分;
- 依赖于视图模型,为视图提供维度;
- 依赖于展现度量值,为视图提供计算结果。
既然我们考虑的终极问题是复用,MVC 架构设计模式更多的是为我们提供了一个框架,由于 PowerBI 本身并没有提供特定于 MVC 模式的支持,但我们通过约定的方式,仍然可以实现这一架构。以 MVC 架构开始,我们将不断进一步融入其他可复用思想,包括但不限于:抽象,单一职责原则,开放闭合原则,里氏代换原则,接口隔离原则,依赖反转原则以及面向接口和非侵入式设计思想,这些内容我们将逐步展开。