美文网首页
【Android】【架构】【美团外卖平台化】

【Android】【架构】【美团外卖平台化】

作者: 徐乙_ | 来源:发表于2019-08-10 23:04 被阅读0次

    背景

    美团外卖有多个流量入口,外卖App,美团App,微信小程序等
    其中外卖作为美团App的一个频道接入,其功能和外卖App大体相似
    早期由2个团队维护,如果可以由一个团队维护,人力成本就可以下降一半,这是极其重要的
    所以平台化可以理解为App融合技术,一份代码,多平台运行
    我所在的部门同样有2个功能相似的App,存在不少的两端代码拷贝问题,所以学习此文希望可以从中得到借鉴

    早期失败尝试

    复用公共组件,逐项解决差异化

    image.png
    1. UI样式可以在宿主复写一套同名,进行覆盖
    2. 建立代理Fragment统一基类
    3. 2个宿主通过适配器,输出一套公共的数据
    4. 其他差异通过接口隔离
      显然这样会产生大量适配代码,代码冗余。复杂度高。无法定义规范,难以维护,后来者容易打破约束

    页面组件化
    即拆分一个页面成多个单元,设想这些小单元更容易复用一些
    但是实际上底层库差异过大,代码逻辑还是无法有效复用

    优雅设计模式

    image.png

    借鉴MVP Clean,这是一个优秀的页面架构,可以把页面拆分成比较细的粒度
    你可以理解为把一个页面分成了6-7个组成,分别是UI、数据、逻辑、功能等
    按照这些维度来逐项适配
    这样适配的灵活性更高,也更规范
    但是其复杂度更甚,而且依然有维护困难的弊端

    最终方案:平台化

    统一底层库是必然的,而且这也没有什么不合适的,底层库都是公共的一些能力,基本没有特殊定制的需求
    同时要进行App融合,建立一个外卖平台App,分别以AAR的形式接入到外卖App壳子和美团App外卖频道

    image.png

    维护2端的差异,通过flavor即可。flavor可用于多渠道打包,在这里公共的部分单独定义,差异的部分放到2个不同的flavor里
    通过这种方式,全新的视野、思路,完美解决了代码复用的问题

    优化:多Project+多Module+多P

    组件化
    各个业务模块建立不同的module
    页面通信通过基于scheme原理的框架

    image.png

    功能的调用通过接口下沉+反射实例化框架

    image.png

    模块内的页面维度的隔离
    为了在模块内部实现更精细的解耦,每个页面都会被隔离
    隔离方式不是采用Module,这样成本太高
    而是通过文件夹隔离

    image.png

    所以需要修改Gradle中打包类和资源的路径

    sourceSets {
        main {
            def dirs = ['p_widget', 'p_theme',
                        'p_shop', 'p_shopcart',
                        'p_submit_order','p_multperson','p_again_order',
                        'p_location', 'p_log','p_ugc','p_im','p_share']
            dirs.each { dir ->
                java.srcDir("src/$dir/java")
                res.srcDir("src/$dir/res")
            }
        }
    }
    

    但是这样一来,无法通过flavor来适配2个平台的差异了,还是修改Gradle

    image.png
    productFlavors {
        wm {}
        mt {}
    }
    
    sourceSets {
        def dirs = ['p_restaurant', 'p_goods_detail', 'p_comment', 'p_compose_order',
                    'p_shopping_cart', 'p_base', 'p_product_set']
        main {
            manifest.srcFile 'src/p_restaurant/main/AndroidManifest.xml'
     dirs.each { dir ->
                java.srcDir("src/${dir}/main/java")
                res.srcDir("src/${dir}/main/res")
            }
        }
        wm {
            dirs.each { dir ->
                java.srcDir("src/${dir}/wm/java")
                res.srcDir("src/${dir}/wm/res")
            }
        }
        mt {
            dirs.each { dir ->
                java.srcDir("src/${dir}/mt/java")
                res.srcDir("src/${dir}/mt/res")
            }
        }
    }
    

    此时的问题每个Page之间如何通信?这里就较为简单,在模块内,抽出公共的base,再在此基础上建立多个Page

    image.png

    三级工程结构每一级也可以自由地升级、降级

    组件化过程:如何拆分业务模块?

    康威定理:代码结构可以遵循公司的组织结构,并且根据组织结构实时进行调整
    在外卖子频道比如商超快速发展的情况下,很可能脱离了外卖的【页面->商家->下单】流程,建立自己的流程
    这个时候仍然遵循外卖的业务拆分逻辑就不合适了
    所以要参照康威定理,如何拆分由商超团队自行考量

    外卖内核

    商超是外卖的子频道,但是不能保证它未来是否会升级,和外卖平级
    为了这种情况进行兼容,设计了如下内核

    image.png

    内层是Model,第二层是CRUD服务,最外层是业务模块
    假如未来商超升级,升级最内层即可
    假如未来商超Model一致,CRUD服务不一致,那么就抽象服务层,由商超和外卖定义具体的实现

    尾声:编译打包优化

    1、子库的依赖方式
    由aar和源码依赖两种方式
    每次都需要在Gradle中改是compile aar还是compile project
    这点很不灵活,所以开发了一个简单的插件,进行一键切换
    这点携程的Trip.com App也是这么做的
    不光携程,无数个公司都是这么做的
    但是我们组应该应用不了,因为我们都是远程依赖。。。
    2、一键打包
    外卖App可以直接远程依赖,使用Jenkins即可自动化打包
    而美团平台有限制,只能接入aar,所以需要打各个业务线aar,然后打一个总的aar
    所以通过脚本以及此模型实现一键打包

    image.png

    可优化的点

    1、组件化做的还是太过初级
    可以学习下Atlas架构
    2、动态能力弱
    可以考虑插件化

    收获

    其平台化思想值得借鉴
    多个相似的App可以融合到一个App内
    通过flavor屏蔽差异
    同时使用三级隔离+组件化,细粒度解耦项目

    后记

    学习自
    https://tech.meituan.com/2018/03/16/meituan-food-delivery-android-architecture-evolution.html

    有什么写得错误、让人费解或遗漏的地方,希望可以不吝赐教,我会马上更改

    相关文章

      网友评论

          本文标题:【Android】【架构】【美团外卖平台化】

          本文链接:https://www.haomeiwen.com/subject/cswdjctx.html