本文更像是一篇白话了的论文,也希望如此,你可以点击阅读原文以关注本文的更新。
我们一直在考虑的其实是一个终极问题:到底如何最大限度复用。在 PowerBI 中处理这类问题主要涉及两件事:业务逻辑的处理以及可视化的处理。在实践中常常表现为以下问题:
这些问题随着制作的 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 模式(Model–View–Controller)来源于软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。罗叔没有必要展开让大家去理解软件工程,但如果你用过 PowerBI,你会马上发现,在 PowerBI 中使用 MVC模式 是自然而然的。
先来具体说明下什么是 PowerBI 中的使用 DAX 时的 MVC,一个示意图如下:
为了可以更加形象地理解这个过程,我们先看一个案例:
这是一个典型的 PowerBI 报告,从表面看不出什么不同,其不同在于它的打造方式是按照 MVC 模式来进行的,如下:
不难看出,这里使用了典型的 PowerBI 内置的一些构建元素,如:表,度量值,度量值文件夹,然后其组织方式是不同寻常的。
以上三点是约定,罗叔在设计这套模式的时候本着:约定胜于配置的原则。这些并不是制作 PowerBI 报告时候的强制要求,但罗叔发现这些的习惯和约定在设计大型 PowerBI 项目时非常受用。
在 PowerBI 的2019年8月 更新后,由于视觉对象编组的出现,将 MVC 设计模式的实际可行性变得更强,我们看下它们是如何结合的:
可以看出,在某个页面中的 Chart 与度量值的对应关系,如下:
这样,很清晰地讲可视化与呈现可视化的度量值完成的对应。
在真实的大型项目中(非常常见),目前没有任何教程来指导如何套路式地开展一个大型 PowerBI 报告项目。首先,罗叔根本不认为 PowerBI 是一个报告,也许那是其他 BI 报告工具的合适称呼,但在 PowerBI 身上并不适用。我们称一个 PowerBI 文件为一个 PowerBI 工程。
而 MVC 架构设计,正是为了流畅地处理这个工程的套路。先来看下一个 PowerBI 工程(报告)的组成部分。如下:
这应该是你首次见到这样的 PowerBI 工程模型,我们依次讲解如下:
虽然 PowerBI 的构件本身是很少的,而为了解决实际的很多问题,罗叔将这有限的物理构件做了体系化的逻辑划分。这样就可以组织并管理不同的目的进而解决不同的问题。
上述对于 PowerBI 工程以及逻辑组成部分的定义是精确的,值得一提的是:
在有了这些定义后,罗叔进而带你更加仔细地来理解这里面的设计思想。
根据前面的描述,可以有:
其中,箭头表示依赖关系,为了便于理解,你可以读作:会用到。例如:度量值会用到数据模型;可视化会用到数据模型和度量值。
可以看出,这样的设计有一个非常大的好处,那就是:数据模型 不依赖于任何其他部分,这也就是罗叔以前所说过的非侵入式设计。将这个架构更加细分可以得到:
如果考虑到数据源和角色,还可以表示为:
我们将这里涉及到的角色也加入进来,可以看到:
如果考虑下角色,可以看到:
值得强调的是,可以注意这里面的依赖关系,这种依赖关系,可以形成良好的层次结构。上层的内容总是依赖于下层的内容,这样,当用户的需求改变时,不需要更改下层的内容,而仅仅需要修改上层的内容即可。这样就将更改限制在了一个有限的范围内。
有了上述的理论讨论和说明,现在可以在 PowerBI 中进行实现。
首先,按照常规操作,在 PowerBI 中构建数据模型,如下:
除非你非常清楚自己在干什么,否则请务必遵守以下规则:
作为一个约定,可以将数据模型的表名命名为:Model_表名。
作为 Controller 的最组成部分,首先我们需要有个业务度量值表。并将所有业务度量值在其中排列,如下:
业务度量值也会构成一个依赖层级关系,例如:
如上所述,视图模型与数据模型最大的不同在于视图模型是为了可视化而存在的,视图模型与展现度量值同时使用,这种结合特别可以反映 MVC 模式的特点:
其中,
值得注意的是,这里的 展现度量值 就开辟了 DAX 驱动可视化的思想,在无法用常规方式形成所需要的展现时,一个固定套路就是,将需要的样子依赖的维度放置在那,然后编写展现度量值即可。
在 PowerBI DAX MVC 模型的视图与软件工程中的视图有所不同,DAX构建的视图是用户拖拽产生的 DAX查询而形成,它仅仅依赖于两个物件:维度 与 度量值。其中,维度来自于视图模型(或数据模型),而度量值来自于展现度量值。
如果仅仅显示销售额,也可以使用展现度量值进行包装,例如:
View.P1.C2.Value = [KPI.Sales]
这样做的好处是,当某个可视化对象被删除时,与之相关的展现度量值也可以被删除,这就解决了海量业务逻辑度量值可能会出现的模型管理问题。让视图仅仅依赖于视图模型和展现度量值,就解除了这种耦合关系。
本文引出了 PowerBI DAX MVC 架构设计模式,其用意是彻底工程式地解决复用问题。
既然我们考虑的终极问题是复用,MVC 架构设计模式更多的是为我们提供了一个框架,由于 PowerBI 本身并没有提供特定于 MVC 模式的支持,但我们通过约定的方式,仍然可以实现这一架构。以 MVC 架构开始,我们将不断进一步融入其他可复用思想,包括但不限于:抽象,单一职责原则,开放闭合原则,里氏代换原则,接口隔离原则,依赖反转原则以及面向接口和非侵入式设计思想,这些内容我们将逐步展开。