How to best divide big app into modules? - android

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?

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.

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):

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).

Related

Android complex project organization

Im thinking about trying to build a complex android app structure for a game maybe or just for practice reasons. Im used to code in objective-c, so im not that much experienced in android...
Anyway in work, we structure our app on ios like this:
-core framework: handling all core items, navigation, datahandling, mechanisms, etc. its the same in all of our project
-project framework: its files are mostly relying (including) the core framework's files, extending/modifying them, and doing the project depending stuff
-skin framework: this contains all the resources and images, if we want to do a re-skinned project, we only have to alter this
-main project: this includes everything just bashing together everything into an app. just starts the application, nothing more, anything else is done by the different frameworks
So I wanted to do a similar structure on android, but I'm not sure that I'm even able to do it... I see that there is android project and library project, I can include them into eachother... but my questions are:
1: can I build a similar structure as on ios?
2: can I make for example a "core" library what contains the basics of mechanisms, and another library containing only the resources, and a third one (or the third could be the actual runnable project), what can get resources from the resource library, can distribute jobs to the core library, etc...
3: can I organize the resources as I like (so not to throw every picture into the drawable folder root for example). For example to have somehow a characters folder (i know i cant do forlders in the res folder), and map files into map folder, etc... My only chance to name them "properly"? (map_sheet_type_1, map_sheet_type_2, character_sheet_type_1, etc) (if its going to be a game, it would use opengl, lots of sprite drawing, etc)
or I should do everything in a single project, dividing everything into a lot of packages, and use libraries only for jobs like "how to transcode "A" object into "B" object" ?
Thanks for the answers in advance
although I've never developed a game before, but an app is an app:
yes
as you mention you have executable projects and libraries projects, libraries can use other libraries and the only thing that goes to the device is whatever the executable project is building. It's just important to remark that compiled libraries *.jar files resources cannot be used in your executable project (that's why the ActionBar Sherlock have to be used as a library-project). In order to use a resource placed in a library project the project must be with its full source code open in the Eclipse so it can be compiled together. That is because inside an app, there's only one R (resources) object, and during build all the resources from all the projects are put together.
unfortunately no. As you mentioned yourself the resources cannot be in subfolders and even their file names are restricted as they can only use lower case letters, numbers and _ (underline). Just be clever and organised, write a spec or something.
packages IS the way to organize a single project in Java. If you gonna use multiple or single is your choice. Usually you can encapsulate in a library-project stuff that can easily be re-used in different projects, and the final project will contain everything that is specific to that one app/game. I'll give you an example on the place I work, we have a KicthenLibrary that is a library-project that we use in every single Android app we do. That library already contains an excellent multi-threaded bitmap download and cache classes, we used to have a MapFragment (now deprecated) before Google released their MapFragment, easy Http GET/POST methods, etc. As you can see, all of those are stuff that can easily be re-used in several different projects.
And just as a last trick, http://www.eclipse.org/egit/ IMHO is much easier to use GIT directly from inside Eclipse.
Here are a couple links that should help you get started on this.
http://kasperholtze.com/android/how-to-best-organize-your-android-source/
http://bartinger.at/organization-tips-for-android-projects/
Also, when I worked at a start-up, we made an app for both iOS and Android. We started creating native apps for each, and ended up having somewhat different structure. Global information/variables were handled different, and I couldn't structure my files quite like iOS did. That said, Android structure isn't terribly hard to figure out, and I made a fair amount of sub-folders in my assets folder (for libraries and js and such). And yes, you can definitely have several libraries.
As for having several projects in several in one app, see this link How to create a single application from multiple Android projects

How can I examine the whole source tree with an annotation processor?

I have a lot of handler classes that handle specific message types. To register all these handlers, I need to know which ones exist. Currently, they're all annotated with a specific annotation, and I use a Java 6 annotation processor to get all of them, and make a Register class that holds an instance of each of the annotated types.
This works great if the whole tree is being built at once, but if just one of the annotated classes is being built (when I save the file in Eclipse, for example), the processor only sees that type, and builds an incomplete Register. How can I examine the other types in this scenario?
I've solved this well enough for now. What I did is a little hackey, but basically for every annotated class I see, I add its name to a HashSet. Then I use Filer.getResource() to get open a file where I've recorded all the previously-seen annotated classes, and add those to the HashSet too. Then I generate the register class, and write the whole HashSet out to the same resource with Filer.createResource(). This will cause problems if I delete an annotated type, since it will still be recorded in that file, but I can just clean the project or delete that file to solve it.
EDIT: Also, I believe that passing the appropriate "originating elements" to Filer.createSource() should allow Eclipse to track those dependencies properly, but it doesn't. Perhaps that's an Eclipse bug.
Unsurprisingly, compile-time annotation processors only process the files being compiled. Eclipse uses incremental compilation to save time, so the short answer is that you cannot expect your annotation processor to see all types in one pass.
One solution is to change your architecture to support incremental compilation. For example, for each annotated HandlerClass, generate a RegisterHandlerClass class that registers that handler class.
That said, sounds like what you are doing would be better done at runtime, perhaps with the help of a tool like Reflections.

Linker stripping unused classes

I am working on a cross platform project in C++, under IOS and Android, and I am having the following situation
:
I am writing a library used to load scene graphs directly from xml files describing them. The library has a base tree node class, that implements all the functionality to make a class constructable by it's name. Then additional tree nodes are implemented, all deriving from this base node class. This works excellent but there is one problem. The linker 'thinks' that some of my classes are not going to be used and strips them out of the library. I have a nasty workaround right now, having a file that includes all existing nodes headers, and in this file one instance of every node is being created and altered to indicate the compiler/linker that this class is really being used.
Does anybody know a good design pattern that can be used to automatically generate the required instances of all classes?
I have tried to create macros that are placed into the classes cpp file that creates a static instance of the given class, but the linker still detects that those static instances are never going to be referenced.
Or is there a linker flag that can be used to tell the linker not to strip any unused classes out? Like already mentioned: I am working on Android (ndk 6.0) and on IOS (xcode 4.2)
This problem is not going to be a showstopper for my project but it would really be nice to find an acceptable solution here.
It is implementation-defined whether the dynamic initialization of a non-local variable with static storage
duration is done before the first statement of main. If the initialization is deferred to some point in time
after the first statement of main, it shall occur before the first odr-use (3.2) of any function or variable
defined in the same translation unit as the variable to be initialized.
Therefore there's no standard way to guarantee the construction of those objects but to list them all in one specific place.

Tips on organizing larger Android projects?

My current project is getting awfully large. I have dozens of activities, adapters, fragments, layout xmls, and other resources.
In my (smaller) previous projects I organized stuff with a 1 package / 1 category style. So I had com.stuff.xy.adapter, com.stuff.xy.activity, and so on. Now these packages contain too many items, and I find myself wasting considerable amounts of time searching for a specific class in the package hierarchy.
I use Eclipse, and there are some shortcuts one can use (go to class definition e.g.), but those tend to be situational (I can't use that to quickly jump to a layout definiton xml).
Could you share some tips on organizing large scale projects efficiently? Or some plugins for this perhaps? (It might help for example if I could group together source files that deal with a specific application screen - adapters, layouts, activity and fragment code - so I can quickly open them)
EDIT: After many months developing large projects
First I tried to go with working sets with Eclipse. It didn't really cut it for me, my problem was that our single Android project was simply too big, containing many resources, classes, interfaces, etc. Messing around with working sets in the context of a single project just took too much time, I think that they're mainly useful to organize projects in a single workspace.
On the long run we separated our huge single project into many smaller android-library projects and a single "main application" project that depended on all these smaller ones. This way we could split the resources among these library projects (there were many layouts, values, styles that were only used in certain parts in the application) and code of course. I also created a Base library, that all other libraries depended upon, and contained resources and (base)classes that every part of the application needed.
For all my android projects I prefer to sort code in the following structure:
com.company.projectname is the package of the application.
Underlying packages:
model - all my business-objects
logic - services and objects implementing business logic
screens - all the activities of the project. If activities require adapters and so on, then each activity is placed in a separate package under screens package and the related stuff is placed to the same project.
tools - package with Utility class. SettingsUtil and so on.
In the root of the package I usually have Constants.java interface with constants.
In Eclipse, you can use Working Sets to filter your source/layout/resource files in the Project Explorer view. This is a bit more powerful than packages, since it operates on all files including layout and image assets, not just java source files.
For example, you could create a Home working set which contains HomeActivity.java, HomeAdapter.java, res/layout/home.xml, res/drawable/home_icon.png, etc.
Just another tip.
Use Ctrl-Shift-R to quickly open a resource (you get an autocomplete drop down) and Ctrl-Shift-T to quickly open a java class. The list will also auto-populate using the most recent opened files.
Maybe a tip: to quickly go to a declaration in Eclipse
Hold Ctrl while hovering over a class or method. After 1 sec you get a popup with open declaration / open implementation.
Very useful in large project.
For the rest i recommend just making it intuitive and sort all Activities in a package aswell as all calculations e.g.
for your concern "I can't use that to quickly jump to a layout definiton xml", you can click the name of the layout xml, then ctrl+shift+R will lead you to that definition page.

Is there a "proper" way to keep a content provider implementation seperate from it's users?

I have a custom ContentProvider class, which I originally developed in the same project file with the application using it. However since this application is intended to be only one of many users of the ContentProvider, I want to split it in a different project. The code is being developed on the Android PDK, but future clients might be developed on the SDK (on a custom SDK, or SDK plugin, etc).
The problem I'm facing, is about the constants in the ContentProvider class, e.g. CONTENT_URI, column names and as well some constants which are used to interpret the values returned from queries. These of course cannot be accessed from another project. It seems to me I have 3 options at this point:
1) Ignore the problem, and type in the values directly in the user application code. This however makes accessing the ContentProvider uglier. I would have to change some columns, to encode some columns with strings instead of integers, to keep the code maintainable.
2) Put the constants in a separate class, and include a full copy in applications using the ContentProvider. I'm not a fan of duplicating code though. Keeping a duplicate of this code in each target app, will make some things slightly more annoying to maintain.
3) Abuse the fact that I'm developing on the PDK, and expose a platform library, as described in vendor/sample/frameworks/PlatformLibrary. However, platform libraries don't have a manifest file, which if my understanding is correct means that I can't include a ContentProvider. This means I would need one "normal" project for the ContactProvider, and a separate one just to expose the class with the constant values. This feels so much wrong.
The answer at Class structure for a ContentProvider having multiple sub tables seems to imply option (1), which probably looks like the best option right now.
However, maybe I have missed another, neat & tidy, way to do this? Keeping in mind that I am developing on the PDK, I would certainly like my ContentProvider to be usable in the same manner as stock Google providers.
You probably already have at least one class/interface that defines the "contract" of your ContentProvider using static constants for column names, a content URI, etc.
If you put this into its own Android SDK library project (just for the Android classes to be on the build/classpath), you can then use this library from your actual SDK/PDK application's ContentProvider and also distribute it as myapp-api.jar JAR for others to use.
This way you get the best of both worlds: No outdated code (because your ContentProvider depends on it) and other people can use nice constants for URIs and column names.
For an example of a contract class, see ContactsContract.

Categories

Resources