1.关于移动端对用户输入的校验
iOS和android的同事就移动端用户输入是否需要校验,以及用户输入是否需要更强的校验有不同的看法,争论的时候没有找到共通点,所以不了了之了。
现在想想我们其实都同意移动端适合弱校验、问题主要是在什么是弱校验上有分歧。android同事倾向于很弱的校验,比如手机号码只限制11位的最多数字,身份证只校验最大输入18位,他们认为这样即使未来手机号码段增加客户端也不会有校验通不过的风险。他们理由确实有道理,不能让客户端校验无法通过阻碍用户使用我们是有共识的。不过如果服务器端没做校验呢?比如用户输入一个非法的手机号,服务端确没有得到正确的反馈这也不太好,即使如果服务器端做了校验,那也是在发出请求loading一段时间之后给的用户反馈,这浪费了用户流量也浪费了用户时间,从用户体验的角度看,这是不太友好的。那如何平衡用户体验和功能可用性,提高用户体验同时又能保证功能可用?这是进一步思考的问题。为了保证这两点,我觉得对弱校验的弱需要做一点点增强,因为移动互联网发展特别快,手机更新换代也很快,软件升级发展更快,基本一两个月就会有一版,所以保证可预见的时间内产品可用就行了,比如两三年,这样的话我们就可以对一些数据的校验能不能更严格有一个判断,比如身份证我们完全可以做一个强校验,身份证号码是有一套严格的规则的,未来很长时间也不会有变化,完全可以更强的校验,在用户输入错误时,移动端提前就给用户输入错误以正确的用户提示,而不是在提交服务器后才得到反馈,作为用户的角度应该更容易接受,用户有这个心理预期。其他诸如银行卡,邮箱也都是可以做强校验的。至于一些在可预见的时间内会有些变化的输入,比如用户手机号码,可能未来号段会增加,我们可以预测下未来的几年可能会增加的号段,其实短时间号段也不会太大变化的,对于这种可能会变化的输入校验,就需要我们有一个更准确的评估,我们在客户端可以适当校验放松一点,但必要的校验还是要的,至少校验用户手机号码输入是1开头的11数字位是可以做的,甚至判断下第二位是在3、5、6、7、8中选一个数字也是可以做的。在保证用户体验的同时做一些必要的加强版弱校验还是必要的。
在一些技术和产品边界点,也许更考验一个团队的整体价值观了,一切都要从我们做产品的初心去思考,我们都希望做用户体验最极致的产品,我们都希望做功能最可靠的产品,都希望产品的效益最大化。回到初心之后,我们就需要一步一步的去规划,如何兼顾长期目标和短期目标,然后再去去了解团队现状,比如团队的能力是什么样子,团队开发的产品的迭代周期是多久,市场整体的发展状况是怎样等。
2.关于项目的横向依赖问题
最近因为几个bug搞得很郁闷,有几个类似的bug从界面上看android展示的比iOS友好,比如iOS一个详情页没有展示产品名称,而android却展示了,所以产品和测试就有足够的理由说iOS做的不对了,认为iOS端出了一个这么不友好且低级的bug,问题报给我们,我们肯定也觉得自己写的代码有问题导致差异。然而最后定位问题发现是后端没有返回产品名称,所以导致iOS 客户端无法展示,但是android为什么能展示呢,询问他们之后,他们告诉我android从前面的列表页面带过来了产品名称,我因此想起还有几个bug开给iOS,是因为android跨页面带入了数据导致。
从我的技术直觉上我不太理解这种做法,因为这样没完没了的横向带入不必要数据增加了类之间的横向依赖和耦合性,这不符合软件设计的基本原则:高内聚,低耦合。这种做法让代码里多了一些数据正常情况下不需要的判断逻辑,这无疑会增加代码的可维护性可阅读性的成本,也让类的迁移和更改带来成本。但android给人的效果确实好,所以这类bug对于iOS端来说改与不改都难受,不改的话就只能等着后端改好,后端会因为改bug的时间较长,而android做了兼容,后端同事会建议iOS端是否也可以参考带入先保证app工作,同时产品测试更是会催着你赶紧改好,然而改的话又觉得对不起自己做的技术架构和做技术运用的原则,iOS App是尽最大努力减少类之间的横向依赖,让项目中的类保持独立性,这样做符合软件设计的原则的,代码更简洁,我们以后的架构还会设计一个底层参数池的中间件,帮助类与类之间交换数据和通信,这样类之间的横向依赖问题会得到更好的解决,所以我不太愿意为了改一个bug,而牺牲代码质量和技术架构。最后我做了妥协,很郁闷。
关于这个问题android和iOS端处理方式的不同,android的做法保证了产品的健壮性,从产品的角度大家都是乐于看到的,但是从技术的角度,这样做其实是不太恰当,让代码质量变差了,是不太利于后期维护的。从发展的角度来说,后端应该解决这个bug,因为这种bug不解决是有点说不过去的,移动端为后端做这样的保护不太必要,首先这样的话两个客户端都需要做这种处理,增加了成本,其二这种问题早点暴露,还是有利于前后端解决好问题的。
这类bug的不同处理方式还引起我的更深层次的思考,我们作为程序员应该是技术导向的思维方式还是应该产品导向的思维方式?如何让技术人员兼顾这两种思维?兼顾这两者最佳的点在哪里?哪些地方需要做好健壮性保护,哪些地方由应该互相信任。一款产品的成功应该需要大家的通力协作,团队的每个环节都需要做到最好。
3.关于后端交付何种格式的数据给移动端
我们在项目过程中,还遇到了不少后端提供哪种格式的数据给移动端的问题,比如返回null导致iOS崩溃问题。
从后台的角度来说,api中返回的数据中,正确值和空值的类型必须一样,举例,用户名的字段是“realname”: “xxx”,如果用户名为空,则应该返回“realname”: “”。如果返回值是一个array,空数据则返回一个空array,绝对禁止null值。对于客户端,必须用个全局的函数来处理所有api的返回数据,需要有一个机制:对于某个客户端需要数据,如果api中缺失,客户端自动补上并给予默认值。这个机制在我们的实践中大大减少了app的闪退。
再比如返回时间数据问题。有同事认为将需要移动端计算的时间后端可以用长整型时间给到移动端,移动端计算后再处理用来回传或展示,而展示性的数据则由后端处理直接交给移动端展示,也有像我认为的同事,把这种格式化的问题交给移动端,后段提供统一的时间戳的格式给客户端就好,让事情变的统一一致。类似的问题还有金额问题,金额有些地方需要显示5000元,有些地方需要显示5万元,到底后端是直接给我们5万这个字符串让移动端直接展示好呢,还是给我们50000这个数字,移动端处理后再展示好呢。
这个问题其实不是什么大问题,把格式化放在后端可以让我们更容易控制,因为如果需要展示不同格式数据时,我们只需要修改后端就好,否则就需要客户端发布新版本,但是这样子也带来一些问题,让后端开发需要关注移动端页面展示的细节来定义接口文档,并且让接口返回的数据格式不统一,比如有些接口返回年月日,有些地方返回月日等,这其实不利于数据的标准化管理。把格式化放在移动端的话,会带来发布版本的成本,但却可以让接口文档更清晰,遇到时间和金额的数据的时候就知道接口返回的格式。
我个人倾向于后端应该是一个管道的角色,负责数据的增删改查组合分离等,后端专注于做大接口的提供方,而不是为了微观的事情改代码,这可能会引起更大的问题,比如后端修改后的部署对用户的影响是更大的,而把如果把数据的加工处理工作交给移动端处理,这样分工更清晰,虽然这样子的修改可能需要发版,但是这类小问题的完全可以积攒到一个大版本再发,其实也不太影响发版,不过可能会让不同版本的app的展示有些微小的不一致,用户一般一个平台都只有一个手机,即使有多个不同手机,展示的一点不一致,用户应该也是可以接受的。我个人认为这样做对项目长期可维护是有好处,当然这是一家之言,最后还是应该实践检验真知吧。
事物的存在都是有两面性的,技术选型也是如此。看来在技术运用和产品的实现上,价值观是一个很重要的,不忘初心,理清思路,方能设计一个一致性很强的技术项目,帮助实现产品的效益的最大。