zoukankan      html  css  js  c++  java
  • 开发一个第三方库的一般性和团队特定规则

    目的

    在于将可以重复使用的轮子共用,避免重复造轮子,从而提高生产力。

    一般性规则

    1. 避免重复造轮子

      如果已有思路类似的轮子,请完善之而不是另起炉灶,除非对方的代码已经不堪维护。

    2. 谨慎设计 API

      规范化类和方法的命名,注意多参函数参数的位置,过时的 API 使用 @Deprecated 注解。

    3. 避免引入其他库

      当需要依赖第三方库时使用 compileOnly 而不是 implementation ,以避免将第三方库(特别是 support 包)打入其中,将其他第三方库的选择权交给集成者。

    4. 尽量用注解代替枚举

      注解 @IntDef@StringDef@Interface@Retention 了解一下。

    5. 资源文件加上特殊前缀

      第三方库的资源文件会跟集成者的相合并,因此需要在命名上独一无二。假定该库为 xxx-yyy ,那么所有资源文件建议加上前缀 xxx_yyy_

    6. 提供可插拔依赖的方案

      假定该库依赖于一个图片加载库,但不知集成者使用 Picasso 还是 Glide 或者其它图片加载库,这时可以使用 compileOnly 把它们都依赖进来(但不会打进最终的 aar 包),然后在代码中使用 Class.forName() (要捕获异常) 依次检测是否有对应的依赖,有则用之。

    7. 将Manifest中的参数变量化,并由 gradle.properties 控制

      // build.gradle
      defaultConfig{
          manifestPlaceholders = [
      		XXX_APP_KEY: "${XXX_APP_KEY}",
      	]
      }
      
      // gradle.properties
      #XXX
      XXX_APP_KEY=82d79e3cec5013
      
    8. 有多个相关依赖,做聚合依赖

      目的在于将依赖分组,这样可以当需时整组引入,当不需要时可以整组删除,不会留尾巴。下面以 retrofit2 依赖为例,进行依赖分组:

      ext.versions=[
        retrofit:'2.3.0',
      ]
      dependencies {
          implementation([
              "com.squareup.retrofit2:retrofit:${versions.retrofit}",
              "com.squareup.retrofit2:converter-gson:${versions.retrofit}",
              "com.squareup.retrofit2:adapter-rxjava2:${versions.retrofit}"
          ])
      }
      
    9. 当依赖中有两个以上需要使用相同的版本号时,请抽取到ext.versions 中,如上例的 retrofit 依赖,以便于版本维护。

    10. 根据需求考虑是否提供no-op

      如果开发的库只在 debug 模式中被使用,比如说 leakcanary 只在测试时进行内存泄漏检测,并不需要包含进生产包,那么可以提供生产的方法壳,里面为空实现。

    11. 仅仅在 debug 模式中引入代码

      对应仅仅在 debug 模式中被使用的库,请使用 debugImplementation 注解。

    12. 使用 JitPack 做库的托管仓库

      简单,快速

    13. 严格限制库的大小和方法数

    14. README 要讲清楚用途和用法

      要回答这几个问题:
      1. 有什么用?
      2. 怎样引入?
      3. 基本用法是什么?
      4. 支不支持自定义?
      
    15. 快速解决issue,多和提问者沟通

    16. 不断完善,坚持更新

    特定于我们团队

    1. 使用 S3 Maven 发布第三库。

    2. 发布制品的规范。

      groupId 统一为 com.<group>.androidartifactId 统一使用前缀 <group>-

    3. 布局只用 XML 写,相关的字符串、颜色值期望可被自定义的统统抽取出来。

    4. 资源 ID 统一使用 artifactId- 替为_ 作为前缀。

    5. 整个库项目要包含两个模块:一是名为 app 的示例模块;二是名为 lib 的库依赖模块。

    6. app 的示例模块使用包名 com.sample.<库名>lib 模块使用包名com.<group>.<库名>

    7. 打包脚本统一放置在lib/script 中,并统一为:

      #!/bin/bash
      
      SCRIPT_DIR="$(dirname "${BASH_SOURCE:-$0}")"
      # ROOT_DIR=`readlink "$SCRIPT_DIR/../.."`
      ROOT_DIR=`python -c 'import os,sys;print os.path.realpath(sys.argv[1])' "$SCRIPT_DIR/../.."`
      
      cd $ROOT_DIR
      
      # detect gradle command
      GRADLE=`which gradle`
      GRADLE="${GRADLE:-$ROOT_DIR/gradlew}"
      
      "$GRADLE" clean 
                :lib:assembleRelease
                
       sleep 2s # wait the file being generated
      
       "$GRADLE" :lib:publish
      
    8. 每发布一次后请在代码中打上相应的 tag。

      假如发布了版本 1.0.1,那么请执行:

      git tag v1.0.1
      git push origin v1.0.1
      

    参考

    1. 开发第三方库最佳实践 - 掘金
    写在后面:

    1. 子曰:「学而不思则罔,思而不学则殆」。
    2. 站点地图
    2. 本作品作者为 Lshare,采用知识共享署名 4.0 国际许可协议进行许可。
  • 相关阅读:
    简单的语句统计所有用户表尺寸大小
    CodeSmith 介绍
    Oracle Partition By 的使用
    Oracle Contact By的使用
    正则提取 html 里<input> 标记的value 值
    IOS 7 风格Checkbox
    aspose words 介绍
    大规模web 服务开发技术
    数学之美 读后感
    工作流简介--(转)
  • 原文地址:https://www.cnblogs.com/lshare/p/11334143.html
Copyright © 2011-2022 走看看