1 前言

因为《猫科动物和企鹅在窗口外看机器人吃苹果》这出戏太美,很多公司都希望能全平台同时发布新版本app,还要能复用代码以降低开发成本。这迫使一部分已熟悉某个平台的先锋们转岗到另一个平台边学习边开发。最终有少部分人在每个战场都打拼过,从而能全盘考虑以设计出良好的可复用架构。
革命总会出新知,今天已有一些开源框架能应对同时在5大平台Mac OS X、Linux、Windows、Android、iOS上开发客户端,新人们可以不再过多关心系统底层的那些事儿。不过多学点还是有很大好处的,最简单地概括就是会发现大道归一,多种编程语言、系统API、开发工具其实都是解决同一堆问题。越新的方法越方便,可是却算不上越简单。在理解这些之后,就会对编程乃至程序员职业本身有了更深层的看法。
(想到什么写什么,其实远远没总结完)

2 开发

2.1 开发环境

程序员肯定喜欢集代码编辑、编译、打包等一体化的IDE。然而好的IDE都不跨平台,比起写代码,掌握所有平台的官方tool chain是一件比较无聊的事,可是又重要得必须去做。

作用/工具/平台 Windows Max OS X、iOS Android Linux 跨平台
IDE Visual Studio Xcode Eclipse / IntelliJ IDEA 无官方版 自己打造=跨平台代码编辑软件+快捷键+命令行工具
工程文件 VS、Makefile xcodeproj Java IDE的、Android.mk Makefile cmake、gyp
代码编辑 可用IDE 可用IDE 可用IDE 无主流 Vim、Emacs、Sublime Text、Eclipse
命令行编译 cl、devenv、nmake xcode-build(以前是gcc,现在是clang) ant、ndk-build、gradle gcc、make gcc、clang
调试 VS、WinDbg Xcode(GDB、LLDB) JDB、GDB GDB
打包 Windows Installer、第三方工具 Xcode+zip aapt dpkg、checkinstall

很多好用的工具是某平台特有的,可以帮助检查多平台共有的部分代码,如Linux下的valgrind帮助检查内存泄露,Xcode自带Analyze静态检测代码等。
无论是什么工具,查阅说明文档和用户手册是最基本的工作。因为信息量太大且应用场景过于局限,会难有做笔记的动力,用到什么就查什么,多查几次自然就记住了。
如果一段时间内都用同一种工具,记住功能、快捷键、面板设置等能大大加快工作效率。
如果是人力资源充足,最好能有专人负责所有平台的基础设施建设,而不是一个平台一个专家。在这方面研究透彻,后面的工作会事半功倍。

另外,跨平台开发肯定会用到虚拟机(Virtual Box或VMWare)。利用磁盘共享功能,可以修改代码后立刻在多个平台编译调试。推荐以Linux为Host,因为它工具多、系统性能高,能让工作效率最大化。

2.2 编程语言

理论上说,可以用C/C++写遍全平台(有转译神器的语言就不提了)。然而除非是自虐,否则没什么理由不在Android和iOS上分别用到一些Java和Objective-C,因为那样更容易调用便利的系统API。总之,做跨平台开发是不能只懂C/C++的。
而且,一般会用到脚本做一些自动化处理,例如检查代码规范、按文件模板生成代码、按配置打包资源文件等。目前流行的是python,因为它跨平台。跨平台的另外还有perl和ruby。如果算上Cygwin的帮助,那么shell就不仅仅是*nix专用的脚本语言了。不跨平台的话,Windows是batch file,Mac是AppleScript。
如果不幸碰上客户端需要显示网页(移动端上使用WebView),还少不了要懂点HTML/CSS/JavaScript。

语言学多了,会发现有许多共通点。

编程语言的最终目标都是为了生成CPU指令,只不过是承担了越多工作的编程语言,需要程序员写的代码越少而已。形象点说就是所有语言都是汇编的子孙,基因大部分是相同的,长得胖的穿衣服少罢了。所以,随着语言越学越多,每学一种新的都会越快上手。
学多了会混乱,编程书籍或网页参考常备身边是个好办法。

除了C++,各种语言都已和操作系统结合或者封装了系统的底层调用,以另外的模块/包的形式提供线程、进程等操作。越新的语言屏蔽了越多操作系统的细节,连C++11开始也提供了线程的操作。

另外,动态语言的特性在客户端开发的过程中被广泛利用。主要目的是解耦和调试。

  1. Objective-C动态语言的特性
  2. Java的反射
  3. 跨编程语言调用
    • C++调用命令行
    • JNI
    • python调用C/C++

2.3 操作系统

编程语言用到极致,最多也只能做纯数据运算。程序与外部交互的媒介是操作系统,所以跨平台开发还是得熟悉各个操作系统的特性。编程到了一定阶段,查系统SDK/API的用法会成为常态。最后你会发现,无非也就这几类:

  1. 窗口
  2. 进程与进程间通讯
  3. 原子操作与锁
  4. 线程与线程本地存储
  5. 消息循环
  6. 绘图/排版/动画/矢量图
  7. 文件读写
  8. 网络与协议
  9. 时间与日期
  10. 用户事件(鼠标、键盘、触碰)
  11. 设备事件(USB、陀螺仪、GPS、显示器/屏、电量等)
  12. 影音播放
  13. 动态库
  14. 权限、安全、验证
  15. 驱动与内核

使用第三方库能简化系统API和弥补不足,例如boost库能屏蔽很多系统API的差异,并有很多强大的工具。然而不能期望第三库能满足所有的需求,需要自己开发特定需要的库并不断积累,或许有一天还能贡献反哺给开源社区。
如果是做游戏客户端,以上需要关心的东西会更少,除非重新写一个游戏引擎。

为了符合平台用户体验、效能效率最优化、提升开发速度等目的,有时候我们必须使用特定操作系统的功能与界面,所以并不是对系统浅浅了解即可。根据开发的目标不同(特别是涉及硬件的),有时候还要挖掘底层API来用。

程序的一些额外处理:多语言、配置管理、初始化……

2.4 一些跨平台编程的坑

每个平台的坑都多如牛毛,是程序就有缺陷。举几个例子:
Windows带来的宏,如max、AddJob,这些不能作为函数名,否则Linux编译过了Windows会不过。


size_t在printf中的表示,Linux是%zu,Windows是%lu,没有通用的。当然,可以把这些warning关掉。


在linux平台能稳定运行的代码,在windows不一定行。例如

const char* GetString() {std::string temp = "1234";return temp.c_str();
}

因为STL的实现可能不同。还有系统内存回收机制也不同。


有些库只是特定平台需要,zlib(libz)就只有Windows需要。其余系统有自带的。


还有一些不算坑,仅算差异,但为了全平台能编译得过,仍需要记住。例如DEBUG宏不是所有平台都有的,动态库的接口导出写法不同:

#if defined(WIN32)
#  if defined(MY_IMPLEMENTATION)
#    define MY_EXPORT __declspec(dllexport)
#  else
#    define MY_EXPORT __declspec(dllimport)
#  endif
#else
#  if defined(MY_IMPLEMENTATION)
#    define MY_EXPORT __attribute__((visibility("default")))
#  else
#    define MY_EXPORT
#  endif
#endif

3 维护

3.1 架构设计

把架构设计放在维护这节是故意的,因为在跨平台产品中,可维护性是一切变态需求和bug的救星,这正正体现了架构设计的价值。
设计的结果基本上都是把程序分为三大层,从低到高是:平台无关层->平台抽象层->平台相关(适配)层。一些特定平台有的feature会作为component穿插到适配层中。

平台无关层包含数据处理和逻辑控制。数据处理是指通用数据描述(XML、JSON、Google ProtocolBuf),持久化存储,字符编码/多语言/国际化(ICU),图片解码,音频/视频解码,资源管理,log等。逻辑控制多是业务流程的实现。

平台抽象层把平台间有差异的部分做抽象,由平台相关层实现。这层是最考验设计功底的。

平台相关层多数跟UI有关,少数是此平台的特色业务需要,在移动端有衔接编程语言的作用。移动端会使用系统UI构件以求符合对应的用户体验,而且这些构件不是C++的。
当然,UI部分也能复用跨平台,不使用系统构件,完全自绘。这个方案的另一个好处就是容易换肤。不过系统构件一般都有硬件加速,自绘的性能相对较低。

更细致的划分就叫模块了。

3.2 测试与自动化

移动端是各平台的测试中最麻烦的,然而越是苛刻越是以那个平台为准。
如果由人工来保证每个平台都时刻正常那几乎是不可能的,所以要很多检测和测试需要依赖自动化。例如:

  1. 静态代码分析。如Xcode的Analyze。还可能做代码规范的检测,如cpplint。C++的代码自动格式化可以用clang-format.
  2. 编译与打包通过性测试。
  3. 单元测试、集成测试、系统测试、Monkey测试等,这些测试包含了兼容性测试。
  4. 内存泄漏检测。如Linux下的Valgrind、LLVM提供的ASan、Xcode的Leaks等。
  5. 性能测试。

为了实现这些测试,也是要写代码的。至少集成测试就没有通用的,要自己写。为了完成这些测试,又少不了用到各种第三方代码和工具。

自动化平台的工具推荐用buildbot。
从测试工具的举例可以看到,跨平台代码可以被多个特定平台才有的工具检测,对可靠性有非常大的帮助。

3.3 发布后

一般要做三件事:

  1. 崩溃日志收集以及log自动化分析。可以使用Google的breakpad。
  2. 统计信息与运营分析。
  3. 程序更新通知与信息推送。

这些是需要客户端配合的,但主要的工作量在后台。点到为止。
多平台共同开发有个好处:iOS的发布麻烦,及时发现bug慢,可以先在Android发布来弥补。

4 收获

坦白讲,最终的收获不怎么有趣,因为你看清了现实;然而又有些兴奋,因为下一步可能是创造新世界。
看清现实:

  1. 其实无论使用哪种语言或者在哪个操作系统编程都一样,虽然解决的问题不同,但手段是相似的,大道归一,程序的世界就是0和1。
  2. 做客户端应用程序开发,实际就是在使用各种API,极致境界是开发驱动程序和研究系统原理。
  3. 为了更好地开发,有很多“开发支持”领域中的事情不得不做,不少也是要写代码的。
  4. 程序最终是为产品服务的。软件的创新最终会是内容和功能的创新,“制作”本身终会到达瓶颈。

创造新世界:

  1. 最优架构设计或最优算法。(对,这就是程序员走向架构师的理由,不想继续Ctrl C+Ctrl V了)
  2. 各种新工具的开发,为提升效率而努力。
  3. 开发一门跨平台语言或者一个新系统?对技术有追求的,可以紧跟时代脉搏,学尽各种新语言,了解语言的趋势。最厉害的当然是发明一种新语言(及其配套的编译、调试工具)甚至一种操作系统了,不知道有生之年能不能看到中国人的发明呢。
  4. 知道了“怎样”编程,代码都写腻了,对编“什么样”的程序产生了兴趣,要转岗产品经理试试吗?

后续补充:《客户端开发设计总结》
http://blog.csdn.net/hursing/article/details/52586541

转载请注明出处:http://blog.csdn.net/hursing

嗯,干完跨平台项目就是这个样子:

跨平台客户端开发经验总结相关推荐

  1. QT跨平台项目开发经验(项目打包)

    1.代码编写 1.1 代码编写简短,代码运行效率高,适当注释.一般一个大型的项目,代码的运行效率要求较高,一般需要秒级响应,甚至毫秒级. 1.2 建议使用命名空间::的形式来访问该命名空间中的变量和函 ...

  2. 天翼数字生活C++客户端实习

    面试C++客户端实习的岗位,相对不难 面试官:实习主要做的是国产操作系统下的应用,主要做的是视频监控.安防相关的工具,具体就是一个叫做 天翼云眼的软件,目前在windows下和电视下都有对应的应用,就 ...

  3. 【深圳招聘】年包100W-150W+,高薪聘客户端开发/游戏引擎开发大咖~

    01客户端开发工程师 职位描述 1.负责公司游戏的的功能开发及架构设计; 2.负责公司游戏的逻辑和界面开发工作: 3.参与游戏代码结构优化,提高团队代码质量. 岗位要求 1.计算机软件等相关专业,本科 ...

  4. 搭建基于云端的中间层以支持跨平台的智能视觉服务

    不断演进的应用场景 初级应用场景-宅在家里 场景:Bob同学有一天在网上看到了一张建筑物的图片,大发感慨:"好漂亮啊!这是哪里?我要去亲眼看看!"Bob同学不想问别人,可笑的自尊心 ...

  5. app头像上传vue_Vue+Electron开发跨平台桌面应用实践

    总篇43篇 2019年第17篇 背景 公司去年对 CDN 资源服务器进行了迁移,由原来的通过 FTP 方式的文件存储改为了使用 S3 协议上传的对象存储,部门内 @柴俊堃 同学开发了一个命令行脚本工具 ...

  6. Delphi XE 10 跨平台三层数据库应用教程

    Delphi XE 10 跨平台三层数据库应用教程 Delphi XE 开始越来越庞大,比经典的Delphi7难用,但依然是目前所有跨平台开发工具中开发效率最高.最容易上手的,其快速设计RAD理念是无 ...

  7. 边缘计算:客户端 + 人工智能

    有人说人工智能会是继互联网之后的下一次工业革命,不可否认,大到汽车.小到手表,AI技术已经广泛应用在我们周围,随便一个APP都试图跟AI发生点关系以证明自己的与时俱进. AI的普及为客户端开发带来了挑 ...

  8. 滴滴android架构演进,滴滴出行iOS客户端架构演进之路

    自从蘑菇街的李忠老师在移动前线群里做了一次关于iOS组件化的分享之后,大家对于iOS客户端的架构非常感兴趣,展开了热烈的讨论.我很认同一句话,架构都是演变出来的,没有最好的架构,只有最合适的架构,刚好 ...

  9. 2020字节跳动提前批——抖音客户端一面

    1.个人经历 1.自我介绍 2.有无客户端开发经验 2.计算机基础知识 1.进程间的通信方式 1.管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行 ...

  10. 互联网江湖,桌面客户端框架技术比武大会

    By 技术怪咖 欧阳森林 导读:在互联网时代,如何将一个好的idea快速的转化为产品,如何在原有产品中增加新的特性,是产品能够快速的推向市场.快速占领的关键.因此,作为客户端的架构选型,面临哪几方面的 ...

最新文章

  1. LeetCode简单题之按键持续时间最长的键
  2. linux 本机发送邮件 smtp-server 553,Zabbix监控之邮件发送失败-smtp-server: 错误代码550与535...
  3. Behave用户自定义数据类型
  4. 微信小程序css 华文琥珀_琥珀项目:较小的,面向生产力的Java语言功能
  5. ZOJ 1234 UVA 10271 Chopsticks
  6. IBatis.net动态SQL语句(六)
  7. 5.26. sysvmsg
  8. 滞后问题_富锂正极材料的电压滞后问题
  9. Matlab中画柱状图详细教程bar函数使用方法(二维附matlab代码)柱状图创建/位置/颜色/图例
  10. 浅析Java设计模式——观察者模式
  11. 航空机票预定系统软件结构图
  12. ★ Android 各类依赖库文件 收藏 ★
  13. 一文说明前端和后端的区别、职业发展以及就业前景!
  14. es6---Promise
  15. 【愚公系列】2022年02月 微信小程序-数据绑定
  16. 存款利息计算器html代码,html+jQuery简单的利息计算器
  17. 怎么更改锁定计算机背景图片,电脑锁屏背景图片如何更改
  18. Java 泛型方法/接口、泛型限定
  19. security加密解密
  20. mongoDB使用数据(数据的插入,查询等介绍)

热门文章

  1. 数据库的海量数据的存储解析
  2. AX 2012导入Demo数据
  3. 简单的JAVA小程序
  4. Iocomp VC2017 - 5.12版本Crack
  5. Excel图表如何更改坐标轴最大值
  6. MySQL数据库优化的八种方式(总结)
  7. Html 返回顶部代码及注释说明
  8. android q beta3更新功能,Android Q Beta 3更新内容:拥抱5G和可折叠设备
  9. MySQL四种SQL性能分析工具
  10. 解决同一条sql在pl/sql工具中执行很快,在程序中却很慢