Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Splitting big classes with Inner classes in Java

I am working on an Android project. I have searched high and low but I can't figure out a good strategy to split and package my code.

My problem is that I have Inner Classes that use the main class variables, and I can't figure out how to decouple them.

I have tried to create helper classes, but then either I pass a lot of variables through constructors, or I expose my main class, and I don't want to do either.

I want to keep max lines of code per class to 150. Currently, it's 278. I am looking for ideas to decouple these, specifically, how to restructure classes to preserve abstraction (private variables). What are the Java best practices for this?

As an example, here's one of my main classes, MainActivity, ~300 lines.

like image 831
xyz Avatar asked Jun 05 '15 07:06

xyz


People also ask

What are the disadvantages of using inner classes in Java?

Inner classes have their disadvantages. From a maintenance point of view, inexperienced Java developers may find the inner class difficult to understand. The use of inner classes will also increase the total number of classes in your code.

What is the purpose of splitting big chunk of source code to different classes?

Code splitting allows you to strategically omit certain dependencies from bundles, then insert them only where they are needed. This means they are also not loaded until they are needed — loading JavaScript only when it is needed speeds up the page's load time.

Can an inner class extend another class?

You can extend static inner class with another inner class.

Can a class have multiple inner classes?

You can only have inner classes one level deep. Save this answer.


1 Answers

Edit:

Following the addition of the actual code for MainActivivty, I'd suggest the following:

  1. Follow MVC/MVP architectural pattern. You can find a link to a template that I wrote at the end, but there are many more templates - just choose one that you like. Once you understand how to get all UI related code outside of MainActivity, the method addButtons() will be gone, as well as CategoriesListener class.
  2. There is really no need for AllPostsFetchAsyncTask to be an inner class. Implement it as a regular class outside of activity. In order to pass the data from this class back to MainActivity, just define a listener interface that your MainActivity will implement, and pass MainActivity.this to the constructor - when this task is finished, it will call a callback method on the MainActivity, which, in turn, will handle data binding to Adapter. In fact, you adopt here a very bad practice - by making AllPostsFetchAsyncTask aware of implementation details of MainActivity you create unnecessary coupling between the two, thus violating Encapsulation, Single Responsibility and Open Closed principles of OOP.

Just by implementing the two steps above you will make this particular MainActivity way shorter than 150 lines of code.

Said that, your intent of keeping the activities 150 lines long is too restrictive. This boils down to the fact that if your Activity or Fragment are not trivial, then once you implement onCreate(), onPause(), onResume(), onPrepareOptionsMenu(), onBackStackChanged() and other standard lifecycle methods, then you'll probably have more than 150 lines of code even before you add the logic of your custom controller.

Now, I totally hate inner classes and am trying to avoid them at all costs. The following checklist can serve as a guideline, but it is not complete by any means:

  • Never manipulate UI elements in controllers/presenters (Activities, Fragments and Adapters) - encapsulate these manipulations in separate classes. These classes are MVC/MVP views (as opposed to Android View) and I put them in views or mvcviews packages. My Activities and Fragments tend to have zero findViewById() calls in their source code.
  • Put all Adapters in a separate package (even if they 30 lines long). I call this package controllers.adapters or controllers.listadapters
  • If you ever need to pass a set of related data in your app - define a POJO (also known as Value Object) and use it to encapsulate this data. I usually have a package named pojos, even if it contains just a single class.
  • Define abstract classes AbstractActivity and AbstractFragment and put there any convenience logic which is used by your controllers. For example: I always have the following method (or similar) in my AbstractActivity and AbstractFragment:

    public void replaceFragment(Class <? extends Fragment> claz, boolean addToBackStack, Bundle args) { 
        // Code to replace the currently shown fragment with another one 
    }
    
  • Check to see if there are any third party libraries which might be useful in the context of your app and use them.

My packaging usually follows this pattern:

enter image description here

I know you wrote that you've already seen some discussions on MVC, but I still encourage you to try the implementation I propose in this template/tutorial project: https://github.com/techyourchance/android_mvc_template

Hope this helps

like image 190
Vasiliy Avatar answered Oct 17 '22 10:10

Vasiliy