布局编码的未来

2017 年 2 月 24 日 美团技术团队


客户端布局是客户端开发最为基础也是最为重要的编程实践之一,对于一个有着良好技术架构的客户端开发团队来说,布局编码工作占业务开发工作量的80%。显然,对于布局编码进行深入的思考、总结统一最佳实践、提供有力的基础架构支撑,对于提升客户端开发团队的生产力非常关键。


同时,客户端动态化是当前移动开发领域的技术热点,也是移动开发未来最为重要的发展方向之一。当前业界涌现出了React Native和Weex等解决方案,但是这里就存在迷一样的事实:所有框架的指导思想都是保持Web基本布局实践的前提下,通过原生渲染来提高性能。但是,在移动互联网时代,开发者应该扩展一下问题解决思路:Web及其Web的布局实践不是唯一的道路,甚至不可能是最好的思路。


本文从点评App iOS团队的布局实践——匠心布局开始说起,向大家展示一种反常规甚至反直觉的布局方案,和点评移动团队按照匠心布局全新设计的跨平台动态化布局框架毕加索(picasso)。


匠心布局


匠心布局原本是点评iOS布局逻辑开发最佳实践的总结,随着跨平台动态化布局框架毕加索(picasso)的推出,使匠心布局成为跨平台的标准实践。


布局逻辑的本质


在对比布局方案和思路之前,我们先思考一下布局需求的本质是什么?



布局的本质就是:

1. 指定视图的大小和位置
2. 响应变化,在产生变化的时候重新指定大小和位置


变化的来源


我们可以将变化的来源划分为两个方面,内部来源和外部来源:

1. 内部来源
    内容变化
    国际化
    动态字体

2. 外部来源
    多屏幕适配
    来电录音提示条
    设备旋转


说起适配,可能大家首先想到的就是针对屏幕的适配,实际上内部变化来源中的内容变化一直都是布局编码的核心需求,布局总会涉及到诸如:根据文本长度调整布局,根据具体业务特点排布icon等需求。


外部来源总结下来就是对视图容器变化的适配,这里其实并不能简单的等同于对机型分辨率的适配、设备旋转、来电录音提示条、分屏设计等因素的组合效应。


简单回顾下iOS布局需求发展历史(图片来自WWDC):



曾经有那么一段时间,iOS开发者的世界还是简单而美好的:)



然后我们迎来了iPhone 5、iPhone 6、iPhone 6 Plus……这些设备的出现在iOS技术史上具有里程碑的意义,iOS开发者需要适配更多的屏幕,当然苹果也推出了Auto Layout作为应对方案。当然,既然能适配iPhone6 和 iPhone6 Plus, 简单的、粗暴的适配iPad也成了顺理成章的事情。



当然,所有的iOS设备都有横屏的能力……


再加上iOS大屏幕上分屏的能力,iOS开发面临的适配挑战已经比肩甚至超过Android开发小伙伴了,因为老板和UED通常要求iOS设备的完美适配。


点评iOS最佳布局实践


点评iOS的布局实践总结起来非常简单的,其中核心的特点是:

1. 纯代码布局
2. no autolayout


其中纯代码布局指的是全完使用Objective-C完成布局逻辑,不使用Interface Builder,也不使用Interface Builder(IB)衍生出来的autolayout,以及任何基于autolayout的DSL实现。


事实上这并不是一个全新的思路,我们在苹果方案的文档中找到这样一段话:

1. programmatically defining a view’s frame provides the most flexibility and power.
2. When a change occurs, you can literally make any change you want.


显然苹果方案也认为纯代码布局有着灵活性巨大优势,但是他们并没有想清楚具体的布局编码实践,然而点评的匠心布局凭借“锚点”的概念完美的解决了布局代码难以编写,难以维护的问题。在这样的前提之下,Auto Layout之类声明式方案没有任何优势,却因为核心引擎实现的复杂度带来稳定性和性能方案的重重问题。


锚点的力量


逻辑表达的困境


使用具备完整编程语言表达能力的布局,显然在灵活性和性能方面具备压倒性的优势。但是,无论Android还是iOS平台上,原生API写出的布局代码都显得非常拙劣,难以编写和理解,进而变得难以维护。


例如就控件居中的需求来讲,iOS的原始方案可能是这样:

CGRect frame = view.frame;
frame.origin.x = bgView.frame.size.width / 2 - view.frame.size.width / 2;
frame.origin.y = bgView.frame.size.height / 2 - view.frame.size.height / 2;
view.frame = frame;


可能是这样的:

view.frame = CGRectMake(bgView.frame.size.width / 2 - view.frame.size.width / 2,
                        bgView.frame.size.height / 2 - view.frame.size.height / 2,
                        view.frame.size.width,
                        view.frame.size.height);


也可能是这样的:

view.center = CGPointMake(bgView.frame.size.width / 2 - view.frame.size.width / 2,
                          bgView.frame.size.height / 2 - view.frame.size.height / 2);


然而这样的布局逻辑代码显然是不可维护的,由此产生的“纯代码布局是脑残行为”的论断也是可以理解的。苹果和谷歌官方给出的方案就是Auto Layout、LinearLayout等“声明式”布局逻辑,而应对客户端动态化的方案,人们自然而然会想到Web的HTML+CSS,以及CSS的超频版本Flexbox和Gridlayout等等。


锚点及应用


纯代码布局在表达上所遇到的困境本质是,系统原生接口暴露的view.origin.x, view.origin.y, 与开发过程中所表达的诸如“居中对齐”, “左对齐”, “底对齐”等需求描述语义存在这小小的距离。而通过对视图增加锚点概念:

1. left
2. right
3. top
4. botom
5. centerX
6. centerY



7. width
8. height



则消灭了需求和本质实现的语义差距,于是居中逻辑表述变成了:

view.centerX = bgView.width / 2view.centerY = bgView.height / 2


类似的“左对齐”:

view2.left = view1.left


“底对齐”:

view2.bottom = view1.bottom


这样一来,布局需求的描述和布局实现如出一辙,容易编写,容易维护。锚点的概念让代码布局逻辑简洁清晰,使纯代码布局成为可能甚至成为优选方案。


开发效率


我们认为,对于关键技术和框架的选择,开发效率的考虑尤为重要。总结下来,下面两点非常关键:

1. 即时反馈的编程环境
2. 简洁强力的语义表达


即时反馈的编程环境

  • IB & Playground

  • Live Reload

  • IntelliSense

我们看到这些编程环境的特点:

1. 即时看到执行结果
2. 即时看到执行过程(中间步骤结果)
3. 即时的反馈可用接口


实际上前端开发同学之所以能在一个拙劣混乱的基础架构上达成较高的开发效率,很大程度上收益于前端开发很容易搭建一个即时反馈的编码环境,尤其是Live Reload支持,对生产力提升尤为明显,甚至弥补了语言和良好IDE支持的缺陷。这其中动态的能力是关键,但并不代表Web是客户端动态化唯一的方案。综合利弊,我们可以吸取三端编程实践最好的东西,构建最富有生产力的客户端动态化框架。譬如,picasso利用JavaScript的动态特性, 实现了Live Reload,又借助TypeScript+Visual Studio Code+Babel达到了传统客户端静态类型语言的开发体验,提高生产率的同时,还从工程上保证了可靠性。


简洁强力的语义表达


我们这里使用一个简单的例子,关于水平方向上约束的表达对比。



首先我们看到,官方使用伪代码的形式示意说明约束表达的含义,显然伪代码肯定是广大人民群众喜闻乐见的形式:

RedView.Leading = 1.0 x BlueView.trailling + 8


然后就面临这血淋淋的现实,模式的约束构造方式是这样的:

[NSLayoutConstraint constraintWithItem:blueView
                             attribute:NSLayoutAttributeTrailing
                             relatedBy:NSLayoutRelationEqual
                                toItem:redView
                             attribute:NSLayoutAttributeLeading
                            multiplier:1
                              constant:8];


很显然,没人原意去写这样的代码,于是GitHub上涌现了大量的基于autolayout的DSL,选一个其中的翘楚:Catography(Swift)来说明,写出来的代码是这样的:

layout(blueView, redView) { blueView, redView in
    redView.leading == blueView.trailing + 8}


如果能选择性的忽略layout函数调用,block体里面的约束表达已经和伪代码描述如出一辙了,最后我们看下匠心布局的写法是什么?

redView.left = blueView.right + 8


对比下来匠心布局的表达是秒杀对手的,实际上匠心布局只做了最简单的一层抽象,毫无疑问是稳定性和执行效率更高的方案。


配合屈指可数的数个锚点,匠心布局代码无异于表达布局需求的伪代码,这样的代码具有最高的可维护性,显然对提高生产力有着巨大的好处。


picasso


picasso(毕加索)picasso是我们基于上述的匠心布局理念开发出的跨平台动态化布局框架。它有如下几个优点:- 配合100%的单元测试,picasso核心引擎稳定性值得信赖; picasso提供开放而统一的扩展体系,对控件的扩展支持只需要实现一个简单的wrapper,甚至丝毫不侵入自定义控件的实现。



简单描述一下picasso框架的基本原理。picasso接受使用匠心布局实现布局编码逻辑的js文件和和业务数据,在JSCore中执行JavaScript逻辑,并输出页面视图树的中间表示PicassoModel,而后由picasso引擎构建出不同平台的视图树。其中picasso计算的过程可以在手机后台线程完成,并且picasso在进行视图树构建的时候可以做极致的性能优化,可以认为picasso实现的视图可以有比原生代码实现更好的流畅度。


除了picasso核心引擎,picasso也是客户端动态布局一整套最佳实践总结。picasso-server提供了完整的Live Reload编程体验,推荐使用的VSCode+TypeScript+Babel的组合,带来的是客户端原生编程的安全性和便利性;同时,picasso-server还提供了项目和单文件的脚手架功能;随着picasso布局的深入使用,picasso将汇总广泛丰富的最佳实践,更进一步的促进生产力的提升。


显然热部署能力是现阶段各个业务对于picasso的“刚需”,即使放弃使用picasso的热部署能力,picasso解决方案所提供的Live Reload、跨平台、简洁强力的布局DSL,都能大大提升开发效率。


预测未来最好的方式就是创造未来,毕加索(picasso)就是我们创造出的布局编码的未来。


作者简介


大为,美团点评公司点评平台iOS负责人,资深布局师,主导研发包括piccaso在内的一系列基础框架和基础设施,有效支撑了美团点评移动业务的蓬勃发展。


点评平台移动技术团队,同时肩负了平台性业务研发和基础框架的研发工作,在支撑美团点评业务高速发展的同时,积淀了一系列的基础框架、研发技术流程等方面的最佳实践,未来期待和业界有更多交流。

热门博客

大前端

Android 热更新方案Robust

RestQL:现代化的 API 开发方式

基于 KIF 的 iOS UI自动化测试和持续集成

基于 Appium 的 Android UI 自动化


大后端

常见性能优化策略的总结

美团外卖订单中心的演进

CRM系统新思维

深度剖析开源分布式监控CAT

消息队列设计精要

大众点评订单系统分库分表实践

Java NIO浅析

Java 8 之重新认识 HashMap

高性能队列——Disruptor

分布式系统互斥性与幂等性问题的分析与解决

Spark Streaming + Elasticsearch构建App异常监控平台

Java Hotspot G1 GC的一些关键技术

分布式队列编程——系列篇



沙龙干货

移动App兼容性测试工具Spider

分布式会话跟踪系统的架构设计与实践

美团数据库运维自动化系统构建之路

大促活动前团购系统流量预算和容量评估

美团点评的Atlas实践

RDS平台介绍



美团点评

技术团队

http://tech.meituan.com

长按二维码关注我们




查看文章原网址可点击“阅读原文”。

更多技术博客:美团点评技术博客


PS:正文中标绿的名词均为参考链接,可点击查询。

登录查看更多
0

相关内容

FPGA加速系统开发工具设计:综述与实践
专知会员服务
63+阅读 · 2020年6月24日
专知会员服务
180+阅读 · 2020年6月21日
专知会员服务
79+阅读 · 2020年6月20日
【KDD2020-清华大学】图对比编码的图神经网络预训练
专知会员服务
43+阅读 · 2020年6月18日
德勤:2020技术趋势报告,120页pdf
专知会员服务
187+阅读 · 2020年3月31日
【德勤】中国人工智能产业白皮书,68页pdf
专知会员服务
295+阅读 · 2019年12月23日
【强化学习】深度强化学习初学者指南
专知会员服务
178+阅读 · 2019年12月14日
美团:基于跨平台框架Flutter的动态化平台建设
前端之巅
14+阅读 · 2019年6月17日
2019社交行业研究报告
行业研究报告
5+阅读 · 2019年5月30日
【数字化】数字化转型正在成为制造企业核心战略
产业智能官
33+阅读 · 2019年4月22日
每个架构师都应该培养业务思维
InfoQ
3+阅读 · 2019年4月21日
2018年游戏行业研究报告
行业研究报告
3+阅读 · 2019年4月20日
职人沙龙 | 走进小打卡,小程序技术实战交流
云游戏行业发展趋势分析报告
行业研究报告
13+阅读 · 2019年3月24日
李善友:战略听着空?但有人用它“绝处逢生”
互联网er的早读课
10+阅读 · 2019年1月15日
智能时代,图像检索技术在美团APP中的应用分析
人人都是产品经理
9+阅读 · 2018年5月23日
Learning Dynamic Routing for Semantic Segmentation
Arxiv
8+阅读 · 2020年3月23日
Image Segmentation Using Deep Learning: A Survey
Arxiv
43+阅读 · 2020年1月15日
Arxiv
6+阅读 · 2019年7月29日
Arxiv
9+阅读 · 2019年4月19日
Star-Transformer
Arxiv
5+阅读 · 2019年2月28日
Arxiv
23+阅读 · 2018年10月24日
Hierarchical Deep Multiagent Reinforcement Learning
Arxiv
8+阅读 · 2018年9月25日
VIP会员
相关VIP内容
FPGA加速系统开发工具设计:综述与实践
专知会员服务
63+阅读 · 2020年6月24日
专知会员服务
180+阅读 · 2020年6月21日
专知会员服务
79+阅读 · 2020年6月20日
【KDD2020-清华大学】图对比编码的图神经网络预训练
专知会员服务
43+阅读 · 2020年6月18日
德勤:2020技术趋势报告,120页pdf
专知会员服务
187+阅读 · 2020年3月31日
【德勤】中国人工智能产业白皮书,68页pdf
专知会员服务
295+阅读 · 2019年12月23日
【强化学习】深度强化学习初学者指南
专知会员服务
178+阅读 · 2019年12月14日
相关资讯
美团:基于跨平台框架Flutter的动态化平台建设
前端之巅
14+阅读 · 2019年6月17日
2019社交行业研究报告
行业研究报告
5+阅读 · 2019年5月30日
【数字化】数字化转型正在成为制造企业核心战略
产业智能官
33+阅读 · 2019年4月22日
每个架构师都应该培养业务思维
InfoQ
3+阅读 · 2019年4月21日
2018年游戏行业研究报告
行业研究报告
3+阅读 · 2019年4月20日
职人沙龙 | 走进小打卡,小程序技术实战交流
云游戏行业发展趋势分析报告
行业研究报告
13+阅读 · 2019年3月24日
李善友:战略听着空?但有人用它“绝处逢生”
互联网er的早读课
10+阅读 · 2019年1月15日
智能时代,图像检索技术在美团APP中的应用分析
人人都是产品经理
9+阅读 · 2018年5月23日
相关论文
Learning Dynamic Routing for Semantic Segmentation
Arxiv
8+阅读 · 2020年3月23日
Image Segmentation Using Deep Learning: A Survey
Arxiv
43+阅读 · 2020年1月15日
Arxiv
6+阅读 · 2019年7月29日
Arxiv
9+阅读 · 2019年4月19日
Star-Transformer
Arxiv
5+阅读 · 2019年2月28日
Arxiv
23+阅读 · 2018年10月24日
Hierarchical Deep Multiagent Reinforcement Learning
Arxiv
8+阅读 · 2018年9月25日
Top
微信扫码咨询专知VIP会员