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

comeback · January 02, 2018 · Last by comeback replied at January 03, 2018 · 2360 hits

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

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

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

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

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

Reply to Catherine

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

会有这个问题

4.22 + 5
 => 9.219999999999999

https://stackoverflow.com/q/5419839

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

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

Reply to yfractal

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

Reply to 42thcoder

谢谢回复。

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

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

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

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

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

Reply to comeback

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

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

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

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

Reply to jasl

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

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

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,如输入值转换成存储值函数等)函数。一旦有业务变更,改动模块中的相关函数。避免代码冗余。

Reply to 42thcoder

好的,明白你的观点了。

Reply to jasl

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

Reply to hooopo

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

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

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

这个应用层指的是?

Reply to chq

谢谢回答。

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

为什么?

Reply to comeback

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

Reply to comeback

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

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

Reply to jasl

了然

建议不错!

You need to Sign in before reply, if you don't have an account, please Sign up first.