App 模块化实战经验总结

??


随着业务的不断发展壮大,App 端所承担的功能也越来越重,特别是代码几易其主之后开始变得杂乱无章,牵一发而动全局的事情时常发生。为了应对团队壮大之后的开发模式,我们必须要对业务进行隔离,同时沉淀出通用组件,完善移动开发的基础设施。

1. 痛点

模块化之前,我们主要面临以下痛点:

  • 业务边界不清晰
  • 通用代码与业务代码耦合
  • 代码、资源文件大量重复
  • 常量满天飞

其中业务边界不清晰是最大的痛点,最直接的表现就是处处有雷,经常会引入新的 Bug,而且很多 Bug 往往不能从根本上解决,代码维护成本居高不下。

2. 重构原则

模块化并不能一蹴而就,我们在重构的同时也在做新需求,每次看到那一坨旧代码心中就会有无数只”草泥马”奔腾而过,干脆重写的无奈之情难以抑制,结果在红牛的日夜陪伴下写出来的新代码虽然看上去“漂亮”,但是实际上问题更多,得不偿失。吃过几次苦头之后,我们总结出了重构的三项基本原则:

2.1 渐进式重构

如果一段代码已经比较稳定,可以从中抽取一部分功能重写,不要一上来就全部推翻重写,可以慢慢淘汰掉老代码。

2.2 iOS / Android 互相参考

业务代码总是惊人的相似,两端互相参考的过程中,不但可以 Review 代码,还能加深对业务的理解,可谓一举两得。
实践证明,如果人手紧张,项目早期可以只让一端的开发人员跟需求,另一端直接“翻译代码”,甚至一个人写两端代码。

2.3 理清业务再动手

App 作为业务链的末端,由于角色所限,开发人员对业务的理解比后端要浅,所谓欲速则不达,重构不能急,理清楚业务逻辑之后再动手。(可以找熟悉业务的同学聊一下 — PD、后端、测试)

3 模块化过程

所谓模块化,是一个分而治之的过程,概念类似于 SOA,首先进行垂直拆分,过程中必然会催生出业务共享的 Common 模块,而 Common 又可以继续水平拆分,逐渐变薄,直到 Common 消失。

刚开始不需要完美的目标,简单粗暴一点,后续再逐渐改善。

3.1 抽取 Common

Common 层服务于所有的上层业务,是通用层,不允许引用业务层代码。

  1. 首先把 Common 层用到的 Business 层代码下放到各个业务
  2. 然后把多个 Business 之间共用的代码提取到 Common 层
  3. 资源文件的处理方式与代码一致

Common 层作为权宜之计,它的命运是向死而生,最终会诞生出许多功能独立的基础模块。而这个过程是漫长的,我们只能在业务隔离的同时,不断丰富 Common 模块,然后在某个节点将其再拆分成一个一个独立模块。

代码也逃不出分久必合、合久必分的的宿命。

3.2 业务隔离

业务模块之间不能互相依赖,只能单向依赖 common。

业务之间存在两种耦合关系:

  • 页面耦合
  • 功能耦合

要做到彻底隔离就必须打破这两种耦合关系:

  • 页面解耦 - 跳转协议
  • 功能解耦 - 模块间 RPC

3.2.1 统一跳转协议

页面解耦可以借鉴 Web 的设计原理,给业务模块中对外的页面定义一个 URI,然后页面之间通过 URI 跳转。

举个栗子,A、B 两个页面分属于不同的业务模块,在页面未解耦之前,A 如果要跳转到 B,必须要依赖 B 的模块,那么跳转代码会写成如下形式:

Android

1.Intent intent = new Intent(getContext(), BbbActivity.class);

2.intent.putParcelable(BbbActivity.EXTRA_MESSAGE, message);

3.startActivity(intent);

iOS

1.BbbViewController *bbbVC = [[BbbViewController alloc] init];

2.bbbVC.messageModel = messageModel;

3.[self.navigationController pushViewController:bbbVC animated:YES];

如果 A、B 之间还需要传递数据,就要共享常量、Model,耦合继续加重。

如果我们为 B 页面定义一个 URI - wsc://home/bbb,然后把共享的 messageModel 拍平序列化成 Json 串,那么 A 只需要拼装一个符合 B 页面 scheme 的跳转协议就可以了。

1.wsc://home/bbb?message={ "name":"John", "age":31, "city":"New York" }

URL Router 有很多种实现方式,网上资料也是多如牛毛,这里只提供一种思路。

Android 实现方式

1. 在 AndroidManifest.xml 文件中定义 URI

01.<activity

02.android:name=".ui.BbbActivity"

03.<intent-filter>

04.    <category android:name="android.intent.category.DEFAULT" />

05.    <action android:name="android.intent.action.VIEW" />

06.    <data

07.        android:host="bbb"

08.        android:path="/home"

09.        android:scheme="wsc" />

10.</intent-filter>

11.</activity>

2. 封装跳转 Intent

1.final Uri uri = new Uri.Builder().authority("wsc").path("home/bbb")

2.    .appendQueryParameter("message"new Gson().toJson(messageModel)).build();

3.final Intent intent = new Intent(Intent.ACTION_VIEW);

4.intent.setData(uri);

5.startActivity(intent);

3. 步骤 2 代码进一步封装

1.ZanURLRouter.from(getContext())

2.    .withAction(Intent.ACTION_VIEW)

3.    .withUri("wsc://home/bbb")

4.    .withParcelableExtra("message", messageModel)

5.    .navigate();

iOS实现方式

1. 通过 plist 文件保存 URI 到 Controller class 的映射

2. 封装一个根据 URI 跳转到 Controller 的 SDK

3. 页面跳转

1.[ZanURLRouter routeURL:@"wsc://home/bbb"];

注意事项

  • 两端协议要保持一致
  • 需要通过工程手段保证页面 URI 唯一

3.2.2 模块间 RPC

「业务 A 」与「Remote: 服务端」之间通过 HTTP 或者其他协议进行远程调用,「Remote: 服务端」是服务提供者,「业务 A 」是服务消费者。

对于「业务 A 」来说,「Local: 业务 B」也是服务提供者,但是两者不存在依赖关系,所以只能通过协议来通信。

  • iOS 通过 protocol 提供服务,利用 BeeHive 做“服务治理”。
  • Android 通过 interface 提供服务,然后我们模仿 Retrofit 做了一个“服务治理”框架 - ServiceRouter,它的优势在于可以只在业务提供方的 module 中定义 interface,解耦更彻底。

4 代码管理

如果被隔离的业务模块仍然在一个 Project 中,就无法从“物理”上彻底隔绝代码间的相互引用,我们需要从工程上保证业务之间互相独立。

4.1 代码结构

Android (Module) iOS (Project)

4.2 独立发版

每一个 subproject 可以独立发版,然后通过坐标依赖组装成 App,以 Android 为例:

4.3 独立 Repo

现在还没有找到一个很好的代码组织形式,所以我们的观点是:

在团队规模不大的时候,一个人要 Cover 多个子工程,所以没有必要独立 Repo,当一个 Repo 需要多个人 Cover 时可以考虑独立 Repo。

规模 是否独立 Repo
Developer 1 : N projects
Project 1 : N developers

当解耦方案确定之后,模块化其实就是一个体力活,返工重做便成了家常便饭,所以我们觉得比较好的方式应该是专人负责、一气呵成

5 诗和远方

  • 通过移动配置中心动态下发跳转协议
  • 抽取移动端业务通用 UI 组件库
  • 主工程可选择性依赖业务模块
时间: 2024-08-06 16:00:18

App 模块化实战经验总结的相关文章

电子书 移动App测试实战:互联网企业软件测试和质量提升实践.pdf

在移动互联网高速发展的今天,打造上千万乃至上亿用户的移动App是每个开发者的梦想.为了支持这样量级的用户并持续运营和发展,App的高质量非常重要.而作为质量保证的重要手段,测试技术的重要性是不言而喻的,可以说每一个成功App背后都有一支强大的测试队伍. 本书作者在腾讯.京东.阿里等大型互联网公司有多年丰富的测试研发和测试管理经验,为我们揭开了移动App测试的神秘面纱.本书结合大量的实战经验,对移动互联网测试在功能测试.自动化测试.专项测试.QA等方面做了全面而详细的讲解,帮助测试从业者快速.系统

新书出版了 - 移动App测试实战

好久没有更新blog了,算是憋了一个大招 :) 下面是这本书的前言. 前 言 现在已经是一个移动互联网的时代,借助手机等移动设备,人们可以完成资讯的获取.社交.游戏,以及日常生活的各种应用,甚至很多工作的开展.有很多新兴的移动互联网公司在崛起,也有很多传统的IT公司在转型,更有大量传统行业的企业在借助移动互联网拓展自己的业务.对IT技术人员而言,这是一个非常好的时代,有大量的工作机会,因为有大量的移动互联网相关系统的研发需求.当然,这也意味着有很多新的技术和方法要去学习.有很多的研发人员快速转型

移动App测试实战:顶级互联网企业软件测试和质量提升最佳实践

这篇是计算机类的优质预售推荐>>>><移动App测试实战:顶级互联网企业软件测试和质量提升最佳实践> 国内顶级互联网公司测试实战经验总结,阿里.腾讯.京东.携程.百度等公司多位测试专家联袂推荐 编辑推荐 从移动互联网产品测试的准备工作到产品发布后的质量管理方法,涉及移动产品的整个研发流程,呈移动App开发与测试人员的必备参考 内容简介 本书由三位国内顶级互联网企业软件测试工程师联手打造,根据移动产品的特点,深入讲解了移动App测试的最佳实践,从移动互联网产品测试的准备工

网页设计原则理念以及实战经验技巧

(2)界面弱化 一个好的界面设计它的界面是弱化的,它突出的是功能,着重体现的是网站业提供给使用者是主要什么.这就涉及到浏览顺序.功能分区等等. 要让访客在0.5秒内就能把握网站的行业性质,1秒内就知道该从哪个地方开始使用这个网站,能点一次的,绝不点第二次.当然上面说的是大多数功能性网站,对于宣传展示性网站,诸如加特效的或Flash网站,可能就不得不花哨一些,但不能太过分.网站不是动画片,在效率越来越高,社会心理越来越浮躁的中国,人们的耐心越来越小,心理承受能力越来越低.效果可以体现意境,点到为止

Kotlin打造完整电商APP 模块化+MVP+主流框架

详情请交流  QQ  709639943 01.Kotlin打造完整电商APP 模块化+MVP+主流框架 02.Kotlin系统入门与进阶 03.Node.js入门到企业Web开发中的应用 04.精通高级RxJava 2响应式编程思想 05.Java秒杀系统方案优化 高性能高并发实战 06.Java深入微服务原理改造房产销售平台 07.快速上手Linux 玩转典型应用 08.快速上手Ionic3 多平台开发企业级问答社区 09.Java Spring Security开发安全的REST服务 10

《精通移动app测试实战:技术、工具和案例》新书上市

本书是测试专家.性能测试专家.专业畅销书作者--于涌,多年实战经验的总结,涵盖主流的测试工具,包括众多的测试实例,涵盖单元测试.功能测试.性能测试.UI测试.手游测试.自动化测试.测试用例管理.持续集成等移动测试中用到的所有实战技术,是一本贴近实战的移动端测试参考大全.本书主要内容如下. 书中讲解了单元测试,介绍了JUnit框架.单元测试实施.创建基于Android的测试项目和应用JUnit对Android项目进行单元测试:讲解了Android 提供的一个通用的调试工具ADB,借助这个工具,可以

面向Web Cloud的HTML5 App开发实战:Browser&amp;HTML5&amp;CSS3&amp;PhoneGap&amp;jQuery Mobile&amp; WebSocket&amp;Node.js(2天)

如何理解Android架构设计的初心并开发出搭载Android系统并且具备深度定制和软硬整合能力特色产品,是本课程解决的问题. 课程以Android的五大核心:HAL.Binder.Native Service.Android Service(并以AMS和WMS为例).View System为主轴,一次性彻底掌握Android的精髓. 之所以是开发Android产品的必修课,缘起于: 1,     HAL是Android Framework&Application与底层硬件整合的关键技术和必修技

mysql触发器的实战经验-不错的文章

1   引言Mysql的触发器和存储过程一样,都是嵌入到mysql的一段程序.触发器是mysql5新增的功能,目前线上凤巢系统.北斗系统以及哥伦布系统使用的数据库均是mysql5.0.45版本,很多程序比如fc-star管理端,sfrd(das),dorado都会用到触发器程序,实现对于数据库增.删.改引起事件的关联操作.本文介绍了触发器的类型和基本使用方法,讲述了触发器使用中容易产生的误区,从mysql源码中得到触发器执行顺序的结论,本文最后是实战遭遇的触发器经典案例.没有特殊说明时,本文的实

关于《精通移动App测试实战:技术、工具和案例》图书勘误信息

首先,对由于我们工作的疏忽向<精通移动App测试实战:技术.工具和案例>读者朋友们表示歉意,同时已将这些问题反馈给了出版社编辑同志,再版时将会统一修正: 其次,勘误信息请参看附件pdf文档,勘误信息: 最后,向支持作者的读者朋友们表示感谢,也衷心希望得到您更多的建议和批评.