为什么ER建模是软件产品设计的核心:通过一个案例让你深刻理解
编辑导语:ER建模你知道是什么吗?对于产品经理来说必须重视ER建模工作,它决定了软件产品的扩展性和灵活性。本文作者通过例举了某在线教育公司的ER建模的例子,让大家在老王和小李的对话中,展现ER建模的魅力,同时加深对于ER建模的理解。
ER建模:Entity Relationship,也叫实体建模,是软件工程中非常重要且核心的概念。
对于产品经理,尤其是一名B端产品经理,必须掌握并且重视ER建模工作。
ER建模的好坏,决定了软件产品的扩展性和灵活性。ER建模不准确,有可能导致软件设计缺陷,甚至带来严重的业务问题。
如果将软件产品设计比喻成盖大楼,那么ER建模抽象出的实体对象就是大楼的根基,围绕实体对象建设的应用功能就是大楼的外貌,根基决定了大楼的结构和功能,如果根基不稳或错误,大楼就有可能崩塌或不符合预期。
这些偏理论的叙述可能会让大家感到困惑,接下来,我们通过一个实际案例,让大家深刻理解ER建模的魅力。
在案例开始之前,我们再稍微对ER设计相关知识,做一个非常简单的介绍。
一、什么是ER建模
软件设计的核心要点,就是将客观世界的事物,准确的提炼抽象,变成计算机可以理解的面向对象的设计。
我们将客观事物抽象成对象设计的过程,就叫ER建模,抽象出来的对象,就叫做实体(Entity),除了抽象出实体,我们还需要关心实体的属性,以及实体之间的关系(Relationship)。
比如电商中的账号和订单,就是抽象出的实体,一个账号可能有多个订单,每个订单只可能归属于一个账号,这就是账号和订单之间存在的一对多关系。
除了一对多关系,实体之间可能还存在零对多,多对多的关系。
描述实体对象和关系的图形,叫做ER图,ER图的呈现方式有很多种规范(比如UML,Chen,Crow’s Foot等等),绘制方法不重要,作为一名产品经理,只需要简单清晰地表达出设计意图即可。比如上述提到的账号、订单实体关系图,可以简单绘制如下:
本文的重点,在于让大家理解ER建模如何影响了产品方案并决定了业务,所以关于建模的一些基础知识和设计方法论不展开讲述。
接下来,进入我们的案例。
二、案例:某在线教育公司的ER建模
某初创公司开展在线教育业务,面向低龄儿童,因为客单价高,成立电销中心团队完成销售工作。公司安排了资深产品专家老王负责整体产品方案设计,小李是老王的助手,初级产品经理。
老王决定借这个机会锻炼培养小李,因此手把手指导小李参与设计工作。
老王:小李啊,公司计划开展在线教育业务,让我们首先聚焦在客户的模型设计部分,你可以聊聊你的想法啊。
小李:王老师,客户建模是什么?这个问题不是很简单么,我们只需要一个C端的app,有一套账号中心,客户完成常规注册后,在销售的引导下下单不就可以了么?
老王:这个工作会比你预想的复杂很多,客户模型的设计,对整个业务的开展,和系统的建设,都有全面的影响。慢慢我会引导你理解。不过你可以先基于你刚刚的说法,尝试用我教你的ER图,画一个草图出来,我们在此基础上一步步展开分析。
小李:好啊王老师,我认为我们面对的是典型的C端客户,只需要一个账号对象,每个账号下可以创建多个订单,ER图如下:
老王:很好,账号和订单是很常见的两个实体。那么,客户注册后,会由电销销售人员跟进服务,我们需要设计CRM系统给销售人员使用。你认为销售人员在CRM中操作管理的客户对象应该是什么,是账号么?
小李:我觉得销售人员在CRM中管理操作的对象是“账号”好像没什么问题,但又感觉怪怪的,感觉销售人员跟进的应该是客户,而不是账号,但我说不清楚这里边的关系和定义。
老王:你的感觉是正确的,销售人员在CRM系统中管理的应该是客户,而不应该是客户的账号。实际在销售管理中,我们认为新注册的客户、账号等等,都属于销售线索,线索就是指潜在客户。在典型的CRM系统中除了线索,还有商机的概念,不过在我们这里用不到。
小李:好像这样清晰一些了,感觉CRM系统和客户的登录账号就没有明显关系嘛。
老王:也不能说没有关系,只是我们在做数据建模的时候,要分清楚这些对象的概念,保证逻辑定义的清晰。在我们的业务中,可以设计线索和账号就是一对一关系,销售人员和线索是一对多关系,即一个销售可以拥有多条线索,每个线索只能属于0个或1个销售。
小李:为什么一个线索还可能属于0个销售呢,这是什么意思呢?
老王:因为在CRM系统中,并不是每条线索都有销售管理跟进,有些线索可能是无人维护跟进状态,所以线索和销售是1对多,其中的“多”,是指“0或多个”。我们将ER图完善,如下:
小李:这个图看起来更清晰了,背后对应的设计思路也比较明确。不过我还是有点不理解,为什么非要把账号和线索这两个实体分开,除了逻辑上更清晰,还有什么好处呢?
老王:对实体进行明确的建模和设计,除了逻辑上更清晰以外,还有很重要的一点,这样做,可以降低软件系统设计的耦合性。如何理解这句话呢?
ER模型最终会转化成数据库表结构设计,线索和账号可以分别保存在两张数据表,进一步讲,隶属于两个不同的数据库,即CRM系统的数据库,和账号中心的数据库。我们来看下边这张图:
老王喝了口水,继续说道:我在ER图外边绘制了两个框,圆桶代表数据库,圆桶外边的矩形代表业务系统,可以看到,实际上我们在ER图中描述的四个实体,分别隶属于三个数据库,和各自的业务系统。
这样的ER图设计,被清晰地传导到数据库底层设计,以及应用系统的设计,可以保证销售系统、用户中心、订单中心三者很好地解耦合,各自独立,互不影响。
例如:CRM系统如果更新时出了问题,并不会影响到用户中心系统,至少客户还可以登录访问app。
而如果线索和账号被设计成一个实体,对应的表结构设计可能就是一张表,就会导致多个应用系统使用同一个数据库底层,可能造成CRM更新一个销售拜访的功能,出问题影响到C端用户登录app。
小李:明白了,听起来很有道理,ER建模不仅在逻辑上很清晰,还能在物理存储上也很清晰。怪不得我们以前公司创业时做的系统,总说耦合在一起,非常死板,仓库系统做个升级,能把销售系统干趴下。
老王:很多时候系统耦合,都是创业公司为了快速上线,做的设计方案的妥协,比如各个业务系统做成一套代码,一套数据库。当然,我在这里举这个例子,主要是想说明ER建模对数据库表设计、对应用系统设计的传导和影响。
小李:嗯嗯,这下对技术的理解又深刻一层。
老王:我们再回到建模设计本身。现在的模型,依然存在很多问题。比如说,在目前的模型中,如果小朋友的爸爸妈妈都注册了账号,该怎么办?
小李:听起来没啥问题啊,那就各自注册呗?
老王:其实问题很严重,因为爸爸妈妈各自注册后,会产生两条没有关系的销售线索,CRM系统一般情况下会分配给两个销售跟进。
但对于这个家庭来讲,实际上只需要给孩子购买一次课程,那么,两名销售为了各自搞定家长获得提成,可能就会产生恶意竞争,给客户做出虚假的承诺,甚至给爸爸妈妈表述不一致,造成极差的客户体验。
而且如果成单(客户付费),很难说清楚到底是哪个销售的功劳更大,这就会造成销售人员之间天天打架扯皮,非常不利于业务开展。
小李:有道理,那如果爸爸注册了,妈妈再注册,让妈妈的线索分配给之前跟进爸爸线索的销售,不就可以了么?
老王:说的没错,问题是,我们并不知道爸爸和妈妈是否是一家人啊?我们的模型设计,并没有预留这样的能力支撑。你想想该怎么修改呢?
小李(沉思中):有了,我们可以将以前的单一账号体系,改成子母账号体系,账号可以彼此建立归属关系,这样如果爸爸和妈妈绑定彼此账号,销售人员就能够识别同一家庭的家长,就不会有冲突了。如下图:
老王:很好,你的这个模型,在数据底层提供了能力支持,是我们在应用层面解决销售冲突业务问题的一个前提基础。
小李:不过我还是没想明白,这个底层模型如何支持业务,因为一般C端用户并没有动力在注册时做家庭账号关联啊?
老王:你说的很对,一般C端用户并不会主动去做账号关联,但是如果我们有这个数据底层设计的支持,就可以在应用系统层面做各种功能,来解决业务问题,同时还要结合业务制度。
比如:销售部门可以明确做出规定,所有销售在第一次跟进新线索时,必须先确定该账号不是同一家庭账号,或者不是已注册家长的其他手机号。
如果发现是,则在CRM系统中提供功能,做账号合并,将两个或多个账号关联起来,这样和账号一一对应的线索,也就能梳理出关联关系了,让多个相关的线索被调配给同一名销售。同时也可以在C端提供功能,引导家长完成家庭多手机号的绑定。
正因为我们在数据建模时考虑到了这个问题,做好了数据底层设计的准备工作,未来才能在应用功能层面实现这些功能点,解决业务问题。
小李:明白了,真是神奇!如果销售部门已经明文规定了要确认是否重复账号,而销售人员依然不遵守规定,那么即便第二个销售跟进开发成功,佣金依然判定属于第一名销售,只要规则明确,大家就必须遵守,纠纷就容易解决了。
老王:你说的很对!不过你的子母账号的设计,可能会造成一种管理和被管理的感觉,在C端的体验并不是特别好,是否有其他方案呢?
小李(挠挠头):想不出来啊!
老王:其实我们的业务、面临的客户结构,就是典型的家庭结构。在数据底层,可以按照家庭的模型来建模,在账号之上设计一个家庭实体,账号都在同一个层级,隶属于某一个家庭,这样也可以完成账号关系的绑定和关联。如下图:
小李:精彩!家庭和账号是一对多,线索和账号一对一,这样就能在数据底层,保证可以对多线索进行唯一性识别!
老王:是的,实际上,账号本身和线索、家庭关联,也并不是很合理。账号只代表一个用户访问系统的凭证,并不代表用户自身。
在现实中,一个用户完全可能有多个手机号,对于企业来讲,理想的情况,是能够识别唯一的客户,以及他背后的多个手机号。所以,从建模的严谨性来讲,我们还需要抽象出一个实体,就是家长。修改后的ER图如下:
小李:我不太理解,这样做的目的是什么呢?你在图中,也没有将家长和账号设计成一对多啊?
老王:家长和账号设计成一对多,会一定程度增加系统的复杂性,也会让用户的操作体验变复杂。
实际上,目前大多数互联网跟公司的业务中,客户和账号设计成一对多,对业务价值并不是特别大,所以为了简化,都采用了一对一的设计方案,但是某些业务,就必须采用一对多设计了。
比如支付宝,通过身份证来识别唯一客户,同时允许一个客户注册多个账号(其实支付宝这样做也是历史原因导致的)。
但是,即便是家长和账号一对一,为了保证逻辑的清晰,我们也需要将两个实体(家长和账号)分离开,毕竟,账号只是是登陆凭证,他不代表用户自身。
我们可以在应用层面将复杂的系统逻辑简化呈现,但是如果可能,就尽量在数据底层保持逻辑的严谨性,虽然会带来底层设计的复杂度,但这可以保证系统在应用层面设计的灵活性。
小李:很有道理,受教了!
老王:这个模型中,还有致命问题,会影响到业务。
小李:啊?还有啊?我以为已经很完美了!
老王:目前订单是关联在账号下的。如果一个家庭有一个小朋友,这样的模型是没问题的,如果一个家庭有多个小朋友,该怎么办?实际上目前的模型不支持这个业务场景。
小李:是啊,这个问题的核心,是我们的模型中没有小朋友的实体!
老王:进步很快啊,那你思考下这个模型该如何完善?
小李:我想想,是不是可以这样,在家庭下增加一个孩子实体,订单挂在孩子实体上,系统默认创建一个孩子,购买的订单就挂在第一名孩子身上。如果家里有多个孩子,那么也支持家长增加孩子,并且可以针对其他孩子购买订单。ER图修改如下:
老王:非常棒,你的这个模型,很好地解决了先前的业务问题!
小李:不过我还是有困惑,这样做,会不会太复杂了?其实如果有多个小孩,那么让客户再注册个账号,不要合并家庭,创建订单支付,不就解决了么?
老王:你说的很对,确实有变通的处理方案,但会损失客户体验,并带来其他的业务问题。
实际上,我们做产品设计,重要的是能够想清楚所有的业务场景和问题,然后基于研发资源和实现周期,做出一个综合评估后的合理方案,这是一个首先做加法,再做减法的过程。
尤其是在ER建模的过程中,必须思考的非常缜密,全面,因为你会发现,ER建模的过程,就是帮你梳理业务的过程。
确实,如果底层模型设计过于复杂,可能会造成研发工作量指数级的上升,但更重要的是,你能考虑清楚所有业务场景,评估不同设计的投入产出比,和业务人员、技术负责人一起充分沟通,最终做出一个充分评估论证的设计方案。
小李:明白了,前辈所言极是!
老王:我们回到刚刚提到的多孩场景,实际上,你在上图绘制的ER模型,已经能够非常灵活的支持各种业务诉求。
比如说,如果一个家庭下,有两个小朋友都购买了课程,并在某一天同时上课,而此时孩子的爸爸妈妈分别在外地,想各自分别去看两个宝贝上课的情况(在线教育常见的监课功能),正因为有这个模型的支持,才能在C端的app做出强大的功能,父母各自登陆,查询到家庭下的两个孩子,并且分别切换看两个孩子上课的情况。
小李:明白,确实,如果没有这个模型,而让家长再注册个账号,在销售管理上也会带来混乱。
老王:是的。所以,这些问题,我们都要想清楚。另外有一点需要十分关注,ER建模最终会转换成数据库表设计,在软件工程中,一旦表结构定型,以后再想修改,是非常麻烦的事情。
比如,如果我们一上来就按照最简单的方案设计了客户模型,那么未来有一天,想切换到上述理想模型,研发的投入上会非常巨大,甚至是无法完成的。
软件系统重构,最头疼的问题就是如何将历史数据迁移到新的数据结构下边。
小李:理解,所以,ER建模,是一个非常核心的设计工作,必须充分探讨,务必谨慎!
老王:没错。接下来,我再问你个问题,刚刚绘制的ER模型,还是有瑕疵。
小李:我晕,还有啥问题啊?
老王:如果孩子也有账号,也需要用自己的手机号登陆系统,你的模型该怎么调整?
小李:啊,真是,我还以为我们做的是幼儿教育,小朋友都得用爸爸妈妈的账号登陆app完成学习。不过确实有这种可能性,如果我们的教育产品拓展到小学或初中,现在的小朋友都是有手机的。我想想,要不然,改这样?
老王:你这么设计是没有问题,但你不觉得抽象的实体有些冗余么,孩子和家长,实际上都是“人”嘛,无非是不同年龄的“人”。
小李:我想想,呃,要不改成这样?最终家长和孩子这两个实体,被进一步抽象到“人”的维度,通过“人”的某个属性来标记是家长还是孩子(甚至都不需要标记,只需要通过年龄进行识别,并产生相关的业务规则)。
不过,这样设计及好么,会不会在逻辑上看起来清晰干净,但是会让工程实现变得复杂?嗯,这个事儿,还得找技术负责人老李好好再合计合计。
老王:对,一定要和技术负责人一起沟通探讨,而且想的越复杂越好!不过,我还有问题要问你。
小李:您请讲!
老王:在最后的这个模型中,订单究竟应该挂在“人”上,还是挂在“账号”上呢?如果人和账号是一对多关系,订单又该怎么挂呢?家长购买课程产生的积分应该挂在“人”上呢,还是账号上呢,还是“家庭”上呢?学生上课获得的奖励应该挂在“人”上呢,还是账号上呢,还是“家庭”上呢?
小李:妈呀,怎么感觉无穷无尽的复杂啊,我想,这些问题,就留给我们聪明的读者来思考吧!哈哈!
老王:我看行!
#专栏作家#
杨堃,公众号:PM杨堃(ID:pmYangKun)。人人都是产品经理专栏作家,《决胜B端》作者,12年互联网研发、产品设计经验,曾任VIPKID产品总监,百度高级产品经理,现为慢酷咨询创始人兼CEO。
本文原创发布于人人都是产品经理,未经许可,禁止转载
题图来自 Unsplash,基于 CC0 协议
谈一下自己的看法哈:
1、虽然说学生家长都是人,但是对于业务而言这两类人的业务完全不一样。针对家长可能是促销,针对学生可能是用来分析成绩变化等,所以两类表最好分开。
2、订单归在哪里,我的意见是找到最小颗粒度人。人可以是家长,学生,家庭,甚至后期会有亲友团(多个家庭组成一个),但订单本质是对于学生而言,且学生和家长、家庭的关系已经建立很清楚。后期即时业务变动,也只是多连一张表的问题
3、目前账号一对多的现象,首先看是否需要解决,其实是解决方式是什么。在没有发生业务的时候,比如用户仅仅浏览时,可以用多个账号登录(微信、手机、qq等),但一旦要涉及到业务比如购买课程时,往往会要求绑定唯一标识(一般是手机)。即时当时没有绑定,当你的第二个账户准备再次购买业务时,如果购买中必须要填写一些基本信息(比如学生名字,家长手机号等),结合业务理解,可以考虑提醒合并账号
4、至于学生获奖挂在哪个账户上,奖项本身就是一个实体,可以多对多。同时挂在家长和学生账户上,完全没有任何问题,且考虑家长和学生的心理,这样的效果比较好
1.孩子从没有账号到有账号过程
当孩子没有账号时,仅存在在“人”这个实体中,记录孩子的基本信息,以及记录学习行为。
当孩子长大有了手机,注册账号。再将人-账号进行绑定,创建1对1关系。
当孩子没有账号时,使用父母的账号登录成功后,仅能选择以学生身份进入,学生身份仅有学习一系列的权限。父母角色可以加设一道进入口令。
当孩子注册绑定了自己的账号,使用账号登录始终指向学生这个身份。
所以人-账号存在1对多和,1对0关系。
2.订单始终挂在人上
账号仅相当登录凭据,爸爸的手机1、手机2登录都指向爸爸这个人。避免了手机1登录看不到手机2的购买订单;
另外当订单应包括购买人(爸爸)与接收人(孩子),这样可以避免一家多个孩子互相串课看
3.家长与购买人
家长角色包括所有孩子的督学权限,以满足妈妈从来不买课,但是要监督每一个孩子学习;
购买人除了家长权限外,还包括对自己的订单的操作权限,退款退单。
4购买课程产生的积分挂在家庭上,增加积分流动性,促进再次消费。
最后那个问题哪个大佬回答一下呗
我说怎么越看越眼熟,原来是堃哥写的!
我觉得我应该会一直跟随杨老师
这不应该是技术做的事情吗?产品只要思考全这些场景给出功能不用管这么深的层次吧
B端产品不得不思考这些的,不然产品设计时候问题很多
从浅到深,真的详细。持续关注中。
留名
大佬关于er建模这方面有什么好的学习途径 有什么书籍推荐吗?
决胜B端,哈哈
大佬 我来了