Building the app I am working on takes a lot of time. Its the biggest one I worked on. I tried to tweak the gradle settings, which is helping, but still the build is quite slow.
Since the app was built without modules in mind, its just a whole lot of packages and now I wonder how I could "extract" some of them and put them into separate modules. AFAIK the modules should not have dependencies to the app module, so I wondered if there is a tool or technique which would allow me to analyse code and help me to find the right packages to extract, since it's a lot of code.
How would you approach my issue?
Your question is Source Code Modularization in Software Engineering. It is new subject in software and there are few references about it. Source Code Modularization is recasting of Clustering concepts on Source Codes.
in this reference from (see reference 1)
The aim of the software modularization process is to partition a
software system into subsystems to provide an abstract view of the
architecture of the software system, where a subsystem is made up of a set of software artifacts which collaborate with each other to
implement a high-level attribute or provide a high-level service for
the rest of the software system.
However, for large and complex software systems, the software
modularization cannot be done manually, owing to the large
number of interactions between different artifacts, and the large size
of the source code. Hence, a fully automated or semiautomated tool is
needed to perform software modularization.
There are many techniques (Algorithms) to Source Code Modularization (see reference 1):
Hierarchical Techniques:
- Single Linkage, Complete Linkage, Average Linkage
- Ward Method, Median Method, Centroid Method
- Combined and Weighted Combined Methods
Search-Based Techniques:
- Hill Climbing, Multiple Hill Climbing (HC)
- Simulated Annealing (SA)
- Genetic Algorithm (GA)
Notice that you can find other Clustering techniques with this names too. But Modularization is a little different. They are recast to source code modularization.
The overall Source Code Modularization Process shown as below:
There are many tools you can use. You can use them in Modularization Process:
- Static Source Code Analysis Tools (to get ADG format and etc.) see the reference here - (like Understand, NDepend and etc.)
- Visualization Tools - (Graph Visualization) see the list here (like Tom Sawyer Visualization)
For example of little project, If your project structure (that generated from source code by use of Static Analysis Tools) are like this:
the result can be like this (after applying Modularization Process):
This is primarily a design problem. As you stated that there is already a large amount of code in the project, one approach would be to analyse the UML diagram for the entire project structure. The goal is to identify regions of the architecture where the interactions are closely coupled between a few classes, groups may also be formed based on which classes have the same external dependencies.
With this approach, you reduce the complexity of the large project, de-coupling classes from external dependencies which they do not use in the large project. The invididual modules which you split the project into will have faster build times. The modules which you split the project into can then be referenced in the main project as dependencies. The additional benefit is that only the modified modules in the main project will be rebuilt each time you make changes.
This Stack Overflow post discusses many UML diagram generator plugins for Android Studio. Code Iris is a good option that you can install via the Android Studio plugin menu. As an example, here is the output from Code Iris on a sample FaceTracker
Android application (click on the diagram to enlarge):
The diagram here shows the grouping of packages and projects. You can see that different projects are split into separate green boxes, within these boxes, are boxes for the packages and then finally classes and interactions. By analysing the UML, you can first identify how to best group your classes and create individual projects. Once you split the main project into modules, you can then use Code Iris again to visualise interactions after changes have been made to the structure.
I would Divide my application into four layers :
- Layer for Objects : in this layer you initiate all the objects that you are in need , with the get and set methods {example:
class person{
region private
private int _PersonID;
endregion
region public
public int PersonID{get{return _PersonID;}set{_PersonID=value;}}
endregion
}}
Layer for Data Access : this layer will handle the contribution of connecting your database and do everything related to procedures, triggers and functions .{this section must be truly protected }
{Do not implement any sql queries inside your code , build all your queries into your database and connect those procedure by calling their names in your codes}
{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;
}
} }
Layer for Business Object , this Layer will delegate instances of the Data access library and than modify it and add with multiple exception handlers . "we use delegates to hide our method names that are used in by equalizing the method to it's delegate into the constructor function of the DataAccessLibrary ".
example
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}
}
4.Finally there is the final layer or the layer where the user have the privilege to inter-act with , it is a multiple connected forms that are handled via front-end handlers and hidden back-end Handlers (where they are called using delegates too).
this structure may take longer in building your application than
other
but it is fast ( since delegates make it faster)
it is protected( since it is devised into many layers and you are dealing with the hidden methods that call an instance of an object not the object itself).