瞎扯淡 讨论一个接口设计相关的问题

comeback · 2018年01月02日 · 最后由 comeback 回复于 2018年01月03日 · 2400 次阅读

现在有个项目里面一些跟钱相关的字段,比如余额,价格等,在数据库是以分为单位,Int 类型来保存数据的。 但是前端一般是以元为单位来展示或者输入数据。

问题:后端接口是统一提供分为单位还是元为单位的数据?理由是什么?假设涉及到的接口有很多,前后端分离。

其实还可以引申为 同一件事,前后端都能做,是前端做还是后端做的问题?欢迎举例说明,谢谢

  1. 第一反应,用分...理由的话.....大概是“感觉比用元更好吧”....

  2. 后端处理。前端需要什么数据,直接处理好丢给他们,让他们拿着直接用。好处差不多就是减少他们问你这啥单位、需要四舍五入吗之类的问题,以及减小客户端过度计算造成卡顿的可能性吧。既然是“服务”器,这点小数据就帮客户服务了。不然叫“自助”器好了。仅个人意见

Catherine 回复

谢谢回复。 用分的理由,后端语言用的是 Java,他们说是为性能考虑,他们是认真的。 同意第二点。

会有这个问题

4.22 + 5
 => 9.219999999999999

https://stackoverflow.com/q/5419839

  1. 单位一般以最小常用单位为准,例如钱用分,时间用秒

  2. 看起来是谁做都一样,但实际上不是的。如果后端来做,向后兼容的难度会越来越大,而且因为逆转了依赖关系,复杂度有可能失控;但是有些地方,服务端改一改可以迅速上线,但是客户端就需要发版。

yfractal 回复

谢谢。这是转换过程中可能会遇到的问题,Ruby 和 JS 等很多语言都有这个问题。不过这些不是上面问题的重点。

42thcoder 回复

谢谢回复。

  1. 个人认为金钱的常用单位应该是元,而不是分,比如各种网站上的价格,没有看见是以分为单位的。同理时间常用单位为 s 才说得通,不然 ms 也是可以见到的。
  2. 前端来做我觉得才是增加复杂性,后端控制对外输出统一以元为单位,能减少前端(ios、Android、各种 web)的复杂性,想想各个端开发人员的变动,项目的新旧迭代维护,每一个地方都要考虑一下转换单位的逻辑,这酸爽。而且各个端的每个接口都做一遍单位转换,其实是做了很多重复的事。
comeback 回复

你说得两条,其实是一条:需要有接口的统一规范,大家都遵守。

至于这个统一规范是啥,那就见仁见智了;我说“一般以最小常用单位为准”,你也不会信得,:-D

后端控制对外输出统一以元为单位,能减少前端(ios、Android、各种 web)的复杂性

这个呢,是减少不了的;我举个很简单的例子,运营要搞个“一分钱买 XX” “九分钱兑换会员”的活动,要求有个页面,价格显示分

comeback 回复

主要是 JS 没有 Decimal 类型,他的 Number 也是单精度浮点,用元来传递和计算(分自然就是小数了)就很容易出意外的问题,不考虑转汇的问题的话,存分,计算也用分来进行,只有在显示的时候才转换成元,是最安全的实现方式。

当然你时不时的 round 一下,也可以算是一种 workaround,绝大多数情况都可以避免计算导致的精度问题

另外考虑案例的话,支付宝的支付接口的金额单位是元,微信支付的是分

存 Decimal 有什么问题?其实这个主要是业务规则的问题,和存储完全没关系...

jasl 回复

JavaScript 虽然没有 Decimal 类型的,但与 Ruby 一样有类似 BigDecimal 的东西(这话有些多余 ...)

另外我想说的是涉及金额的,我个人主观认为精度丢失这种情况是不能容忍的,但具体还是看需求 😂

hz_qiuyuanxin 回复

JS 的基本类型没有吧。。。用第三方库也不是不行,不过前端的主要目的是展示,计算结果 round(2) 可以 ok 了,基本不会出错,话说去年大会用的多会,他们就在算金额的时候出过 bug

这个问题要根据业务来分析。

下面高能,非战斗人员请立即撤离😄

一个数据,一般都会有三种形式:

输入值

- 1,2300.3¥,可以选择简写,或者根据 IP,GPS 定位国家现金单位,或者配置决定输入风格

存储值

这个是数据的核心, 如 整数1230030 或者 多个字段存储,或者 String/TEXT,或者采用浮点数。

  • 如果采用 String/TEXT,灵活,记录的形式多样,但不利于计算和检索。
  • 如果采用整数,ruby 中,整数可以无限大,存到数据库时或者用其它语言(java) 中协同处理时要小心。
  • 如果是采用浮点数,计算后有精度损失,因此取整时要注意是采用四舍五入还是四舍六入五取双的方式,而且在数据库存储也要调整精度。

显示值(输出值)

根据配置显示金额和单位形式。

它们互相转化,是等价的

- 1,2300.3¥ == -1230030

BTW

  • 输入值的校验和存储值由后端开发人员处理。
  • 输入值的校验,前端人员可以选做。
  • 显示值的处理,前端人员和后端开发人员需要有人进行处理。
  • 三种形态的转换规则(如配置),协同处理。

最后,简单直接粗暴的解决方案就是:存的是什么,就返回什么!(不需要进行规则转换,不需要校验)

涉及到的接口有很多,但不管是哪一个,都需要调用上面的说的处理模块(ruby 关键字module,模块中有几个函数,ruby 关键字def,如输入值转换成存储值函数等)函数。一旦有业务变更,改动模块中的相关函数。避免代码冗余。

42thcoder 回复

好的,明白你的观点了。

jasl 回复

谢谢回答,对于以分为单位来计算和存储是可以接受的,但是前端毕竟是需要显示为元为单位的,我想知道的是这个转换的过程是后端接口做,还是前端来做?

hooopo 回复

哈哈,这个问题被带偏了,decimal 和 int 其实都没问题,其实我更偏向 decimal,不过这些都不是我问题的重点。

hz_qiuyuanxin 回复

可以理解为你是赞同后端接口来做这层转换的,对吧

应用层统一用币种最小单位来做运算和存储

这个应用层指的是?

chq 回复

谢谢回答。

最后,简单直接粗暴的解决方案就是:数据库存的是什么,就返回什么!

为什么?

comeback 回复

我让前端做的,而且是显示的时候再转成元,这样就不会遇到计算钱时候遇到的坑

comeback 回复

应用层,就是你理解的接口或者或 Rails 或者说后端。

另外补充说明一点,楼主可能只是涉及国内,我想的是全球化的交易,所有才会有上面那些建议。

jasl 回复

了然

hz_qiuyuanxin 回复

建议不错!

需要 登录 后方可回复, 如果你还没有账号请 注册新账号