前后端分离的边界在哪

2017-05-14 04:53:07 +08:00
 zioc
有一句话说业务逻辑后端做,渲染逻辑前端做。

具体怎么理解呢?

例如表数据如下:
id name pid
0 广东 -1
10 广州 0
11 深圳 0
21 天河 10
22 南山 11


前端需要的格式如下:


A 方案后端递归处理数据最后输出如上,前端直接使用


B 方案服务端直接按照表结构给数据,前端递归,格式如下:


B 的好处是:
1 后端输出简单,节省服务器资源
2 源数据结构,不管页面怎么改,restful api 都不用改
3 分离清晰,后端只提供数据



是 A 还是 B 呢?
6083 次点击
所在节点    程序员
26 条回复
geelaw
2017-05-14 05:00:58 +08:00
A 方案怎么分页?每次重新返回整个链条?

如果可以保证 pid < id,那么用 B 显然可以很简单地处理分页。

另外如果数据出现不一致(譬如有环),如果用 A 会更容易导致后端崩溃,如果是 B 那么后端很难崩溃。毕竟,一个顾客心肌梗死和一个商店塌了相比,还是商店塌了更可怕一些。

还有另外的考虑:如果分级的层数是固定的,那么你的 model 可以变化为固定深度的,那应该用 A。
binux
2017-05-14 06:19:13 +08:00
我觉得你这个表首先设计就有问题,它天生带有一个需要递归查找所有的 children 的逻辑在里面。
如果你每次都要全读出来,那你还搞这个 pid 干嘛,直接存成 A 不就好了。
如果你要去遍历,难不成前端读完广东,还要再去读 where pid = 0 吗?

所以根本原因是你这个表设计得有问题。
think2011
2017-05-14 06:28:17 +08:00
跟前同事都是这样约定的

1. 前端负责展示,后端负责数据
2. 后端要是处理数据太麻烦,丢给前端整理
3. 前端要是运算数据太麻烦,丢给后端运算

基本上就 1 + 2,楼主的这种情况,通常是 2 的方案
ywgx
2017-05-14 10:10:31 +08:00
在安全性考虑的前提下,一般会尽量把计算量放到前端,分摊服务端压力
当然如果设计上前段解决起来,异常复杂,导致简单问题复杂化,就放在后端吧
这个灵活度比较大,还是具体项目具体实施吧~
reus
2017-05-14 10:30:31 +08:00
当然是 A,用 B 的后端也太懒了吧,什么都丢给前端。就想着自己有好处,想过前端怎么骂你吗?
前端要树,我就给树,前端要表,我就给表。分成两个 api。我不用 restful,一个 api 干什么的,我好好命名,不搞那套偷懒甩锅的把戏。
节省服务器资源?构造一个树,纯粹的计算,没有 io,能用你多少资源?找借口偷懒而已。
klesh
2017-05-14 10:50:53 +08:00
A
前端不应关心数据如何存储,既然这是一个树形结构就要返回一个对应的树形结构。后端应保持数据结构的统一表述和抽象隔离。现在是一个表结构,以后是一个文档结构呢?使用产后端分离最大的诉求之一是前端可能有无数个,从种类上分有 spa / mpa / iOS app / android app / 各种平台的 app。若在前端进行递归整理,工作量和维护量会增多。反之,你只要在后端维护一个树形结构,就可以节省很多前端的工作量以及可能出现的 bug。

1. 节省服务器资源的问题不存在,后端必须做 cache,否则只要有某一些前端 /app 调用不合理后端就跨掉?
2. 源数据结构不改页面就不用改?那要看你怎么定义源数据结构这个概念了。是从业务层面上去看这个问题,还是从数据库层面上去理解。
3. 我觉得可以用『去餐厅吃饭』这件事来类比这个事情。对于一个树形结构,直接返回原始底层数组,就相当于餐厅把原材料给你上上来,然后叫你自己拿回家去煮。

以上,你说的三条好处全部站不住脚,这不是后端偷懒的理由。即使你们要按哪端去处理比较方便,也得以『前端会有很多个 app 』这样的前提去考虑,以后端必须做 cache 为前提去考虑,以业务逻辑和关注点分隔的原则去考虑。

再扩展一下话题,若将来你们要集成第三方平台,然后他们的 location id 与你们的 location id 不一致要怎么处理?若『后端只给数据』这个是可以接受的话,然后是要把第三方的 id 也返回给前端,让所有的前端去处理吗?


@geelaw location selection 最多做一个联动选择界面,为什么要分页?分页之后只有一部分的数据,如何正确重建树形结构(如何说某一个 parent 没返回来过,但它的 children 返回了)?


@binux 有意思,表应如何设计?
coderfox
2017-05-14 10:51:07 +08:00
原始数据的结构是树,只是数据库设计上表现为表,所以应该用树。

如果后端有压力可以尝试使用缓存。

我理解的前后端分离是:后端提供的接口呈现数据的原始模式。
reus
2017-05-14 11:10:08 +08:00
@binux 没问题,不需要递归,一般是把所有行读出来,构建树结构,然后返回客户端。这个树可以缓存起来。这样查询和更新都很方便。直接在数据库存树,更新不方便。
geelaw
2017-05-14 11:18:51 +08:00
@binux 然而似乎没有什么好的策略用于存储层数任意的树。当然题主给的这个例子里面层数是有限的。

@klesh 所以我说如果 pid < id 且按照 id 升序返回那就不会有问题啊。

@klesh @coderfox 为什么有根树的森林就一定要是递归的样式?有根树的森林不可以是符合一个约束的父亲数组存储?
ezreal
2017-05-14 11:18:56 +08:00
A
klesh
2017-05-14 11:53:19 +08:00
@geelaw
"所以我说如果 pid < id 且按照 id 升序返回那就不会有问题啊"
第一,即使你的假定可以做到,分页的意义在哪里?第二,你的假定根本不可能做得到,行政区的划分并不是一成不变的,一定会存在 pid > id 的情况:如新区成立, 老的村镇其 pid > id

"为什么有根树的森林就一定要是递归的样式?有根树的森林不可以是符合一个约束的父亲数组存储?"
这里说的不是存储的问题,而是前后端数据结构交换的问题。前端不应关心后端如何存储数据,后端不应关心前端如何展示数据,两者之间通过合理的数据结构进行交流。
geelaw
2017-05-14 12:04:49 +08:00
@klesh

前一个问题:可以通过一开始取较大的 gap 避免,没说 id 必须是连续产生的;还有一种方法是准备另一个排序的 column,然后修改那个 column 以便以后按照“好”的顺序返回结果。(吐槽:行政区划这点数据还犯不着纠结这个问题,而且行政区划已经是有限层的问题了,不需要用这种组织形式存储。)

“前端不应关心后端如何存储数据,后端不应关心前端如何展示数据”

这个和你说用 A 不是矛盾的么?按照这个想法,A 和 B 都没有天然的优势,因为 A 是按照前端想要展示的方式准备数据,B 是按照后端立刻就可以得到的格式准备数据。

或者可能是我对“展示”的理解和你不同?在我看来数据以一个特定的逻辑形式存储出来(例如按照某种对象的形式)已经算是“展示”了,最后出现在屏幕上的方式不重要,因为从数据的逻辑存储形式到人可以通过不同的介质(常见的:屏幕、声音、编程)。或者说我认为前端和后端对接的部分是 model,而不是 view / view model,前端可以自己把 model 变成别的 model、view model。

如果把“展示”理解为打印到屏幕上,那前端和后端之间的 gap 可太大了……
int64ago
2017-05-14 15:22:32 +08:00
这种问题都是前后端彼此太狭隘造成的,如果一个人前后端都写,就会很自然的选出代价最小最优雅的方式,作为后端出生的前端,我更希望跟懂点前端的后端合作,大家很清晰如何分工

对于狭隘的后端恨不得把整个数据库直接查出来丢出来,特别是用 Java 的,那些又长又臭的数据结构都是一坨一坨扔出来的(想保证一行 80 字符都难)

对于狭隘的前端恨不得拿到数据直接展视(既然后端给了数组,为何还要给个 length ?),后端应该是尽可能给出简洁的**元数据**,因为很多时候暂时的时候顺便处理的一些数据计算是很自然的,放后端需要额外处理


对于楼主的问题,我觉得应该放后端处理,倒不是考虑遍历的性能代价(其实这点计算双方代码量和执行效率都差不多)。因为这种结构有很强的依赖性,这种依赖性从前端看是完全由 pid 决定,而这个太不靠谱,如果数据结构重新组织,肯定是前后端都需要改了,而且 pid 的规则对于前端有点类似于魔法的感觉。再换一个大胆的构想,现在你用关系型数据库,于是很方便返回列表,后面假如换成了 mongo 呢,会发现直接返回递归形式更方便,而这些不应该是前端关心的
binux
2017-05-14 18:02:37 +08:00
@reus #8 然而你这个例子里面,树结构是不会变的,不会有更新需求。即使变了,增加一个同名节点比修改指向更简单。
maomaomao001
2017-05-14 18:49:48 +08:00
lodash.js
sagaxu
2017-05-14 20:47:40 +08:00
我来提一个概念,中端,有的公司把中端归为后端,也有公司把中端归为前端,最有代表性的中端语言就是 php。
后端负责基础数据和基础业务逻辑的 API,中端组合后端 API 提供具体业务 API,并按前端的要求的格式返回。
fohuhu
2017-05-14 21:08:10 +08:00
有意思的帖子,公司目前也在谋划前后端分离
learnshare
2017-05-14 21:18:59 +08:00
前端不应该做类似数据库查询这种的动作,这增加了前端的复杂度,数据结构最好能够由后端处理完成。
当然,如果后端能够把数据库核心操作和 API 服务再分离一次,这种操作就有地方去了
x464744246
2017-05-15 09:11:00 +08:00
这种省市级 其实建议取消 pid 直接类似
id name
11 广东
1101 广州
110101 天河
类似 直接取位数匹配就好
x464744246
2017-05-15 09:11:36 +08:00
@x464744246 然后 就直接 B 方案

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/361182

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX