如何最好地将大型应用程序划分为模块?

时间:2018-01-09 12:46:33

标签: android gradle code-analysis

构建我正在开发的应用程序需要花费很多时间。它是我工作过的最大的一个。我尝试调整gradle设置,这有帮助,但构建速度仍然很慢。

由于应用程序是在没有模块的情况下构建的,它只是一大堆软件包,现在我想知道我是如何能够提取的#34;其中一些并将它们放入单独的模块中。 AFAIK模块不应该依赖于app模块,所以我想知道是否有一种工具或技术可以让我分析代码并帮助我找到正确的包来提取,因为它有很多代码。

你将如何处理我的问题?

3 个答案:

答案 0 :(得分:8)

这主要是一个设计问题。正如您所说,项目中已有大量代码,一种方法是分析整个项目结构的UML图。目标是识别体系结构的区域,其中交互在几个类之间紧密耦合,也可以基于哪些类具有相同的外部依赖性来形成组。

使用这种方法,可以降低大型项目的复杂性,将类从外部依赖项中解耦,而这些依赖项在大型项目中不会使用。将项目拆分为的invididual模块将具有更快的构建时间。然后,您将项目拆分为的模块可以在主项目中作为依赖项引用。另外一个好处是,每次进行更改时,只会重建主项目中的已修改模块。

This Stack Overflow post讨论了Android Studio的许多UML图生成器插件。 Code Iris 是一个不错的选项,您可以通过Android Studio插件菜单进行安装。例如,以下是sample FaceTracker Android application上代码Iris的输出(点击图表放大):

enter image description here

此处的图表显示了包和项目的分组。您可以看到不同的项目被分成单独的绿色框,在这些框中,是包的框,最后是类和交互。通过分析UML,您可以首先确定如何最好地对类进行分组并创建单个项目。将主项目拆分为模块后,可以再次使用Code Iris在对结构进行更改后可视化交互。

答案 1 :(得分:4)

您的问题是软件工程中的源代码模块化。它是软件中的新主题,关于它的参考文献很少。源代码模块化是在源代码上重新构建聚类概念。

来自(see reference 1

的参考文献
  

软件模块化过程的目的是分区a   软件系统进入子系统提供了一个抽象的视图   软件系统的体系结构,其中子系统由一组软件工件组成,这些工件彼此协作   实现高级属性或提供高级服务   其余的软件系统。

     

但是,对于大型复杂软件系统软件   模块化不能手动,因为它很大   不同工件之间的交互次数和大尺寸   的源代码。因此,完全自动化或半自动化的工具是   需要执行软件模块化。

源代码模块化(see reference 1)有许多技术(算法)

  1. 分层技术:

    • 单一链接,完全链接,平均链接
    • Ward方法,中位数方法,质心方法
    • 组合加权组合方法
  2. 基于搜索的技术:

    • 爬山,多山攀登(HC)
    • 模拟退火(SA)
    • 遗传算法(GA)
  3. 请注意您也可以使用此名称找到其他群集技术。但模块化有点不同。他们重新编写源代码模块化。

    整个源代码模块化过程如下所示:

    enter image description here


    您可以使用许多工具。您可以在模块化过程中使用它们:

    1. 静态源代码分析工具(获取ADG格式等)参见参考here - (如了解,NDepend等)
    2. 可视化工具 - (图形可视化)查看列表here(如Tom Sawyer Visualization
    3. 例如小项目,如果您的项目结构(使用静态分析工具从源代码生成)是这样的:

      enter image description here

      结果可以是这样的(在应用模块化过程之后):

      enter image description here

答案 2 :(得分:1)

我会将我的申请分为四层:

  1. 对象图层:在此图层中,您可以使用get和set方法启动所有需要的对象{example:
  2. class person{ region private private int _PersonID; endregion region public public int PersonID{get{return _PersonID;}set{_PersonID=value;}} endregion }}

    1. 数据访问层:此层将处理连接数据库的贡献,并执行与过程,触发器和函数相关的所有操作。{此部分必须真正受到保护} {不要在代码中实现任何sql查询,将所有查询构建到数据库中,并通过在代码中调用它们的名称来连接这些过程} {example://

      class personDAO { private List _GetPersons(){//codes here} ; public List GetPersons(){ _GetPersons();} public delegate void del_GetPersons(); private del_GetPersons _del_GetPersons; public del_GetPersons Del_GetPersons { get{return _del_GetPersons;} set {_del_GetPersons=value;} } public personDAO() {//constructor del_GetPersons=GetPersons; } } }

    2. 业务对象层,此层将委派数据访问库的实例,然后修改它并添加多个异常处理程序。 “我们使用委托来隐藏我们使用的方法名称,通过将方法均衡到它的委托给DataAccessLibrary的构造函数”。 例 class personBO { //create instance of personDAO //create an other delegate for personBO //create private method _GetPerson(){//call personDAO.del_GetPersons()} //create public method GetPerson() {// call _GetPerson()} create public constructor function personBO{//set public method = delegates of bo} }

    3. 4.最后,最后一层或用户有权与之交互的层,它是一个多个连接的表单,通过前端处理程序和隐藏的后端处理程序处理(它们是也使用委托调用)。

      • 这种结构在构建应用程序时可能需要更长时间 其他

      • 但速度很快(因为代表会加快速度)

      • 它受到保护(因为它被设计成很多层,你正在处理调用对象实例而不是对象本身的隐藏方法。)