android10 / Android-CleanArchitecture

This is a sample app that is part of a series of blog posts I have written about how to architect an android application using Uncle Bob's clean architecture approach.
Apache License 2.0
15.49k stars 3.33k forks source link

Organize by feature - View Injection #120

Open varunachar opened 8 years ago

varunachar commented 8 years ago

In your blog, you mentioned that organizing the code via feature is better and I totally agree. In my case, I've split my app into different modules and each module is actually a feature. I assume that this is how you guys also work at SoundCloud so as to allow individual teams working on a feature to work independently.

On splitting the code by module, I'm not able to use Butterknife's @Bind annotations since Android doesn't mark R constants in module as static final. Hence I get a compile time for the following @Bind (R.id.auth_et_password) EditText passwordTxt;

Error received : "Error:(44, 15) error: element value must be a constant expression"

So how do you guys inject views? Do you have a custom framework or use AndroidAnnotations framework or something else or you don't split by modules?

DISCLAIMER: I'm a Android noob.

Trikke commented 8 years ago

I won't go as far as creating separate modules per feature, as it comes with a list of problems and overhead in setting up a complex project correctly. Much code is also shared beween different features, so you're also stuck with setting up that correctly. I'd say you shouldn't think of features and feature-teams so rigidly. If a team is solely working on the "user" feature, this doesn't necessarily mean they should be contained codebase-wise into 1 module. Usually you'd have one codebase on which different feature teams working on it in different Git feature branches. A "feature" is just explaining the "why" and "how" a bunch of classes are grouped together under different name spaces. So i'd keep your project setup much simpler, but keep name spaces clear.

Here's a quick example. Notice that "caching" is also a "feature" of the app. Features aren't always what the app does from a user's perspective. They are everything that an app does.

app-module
└───cache-feature
    │   DiskCache
    │   SqlCache
    │   ...
    │
└───user-feature
    │   UserRepository (uses SqlCache to store users)
    │   UserDataRepository
    │   GetUserDetails
    │   GetUserList
    │   UserListActivity
    │   UserListPresenter
    │   UserListAdapter
    │   ...
    │
└───login-feature
    │   LoginService (uses DiskCache to store login credentials for faster login next time)
    │   LogInUserByDetails
    │   LoginActivity
    │   LoginPresenter
    │   ...
    │

You can also go the 3-tier module route that this project uses as an example.

Here is a good read on the topic.

varunachar commented 8 years ago

When would you generally decide to split into a module? Is having a large application inside a single module fairly common and generally accepted as a good practice?

You're right, I was having a trouble in trying to setup the project correctly since I kept running into circular dependencies, but was willing to pay the price of a one time setup v/s having to refactor all over again.

lenguyenthanh commented 8 years ago

I think three modules as example is good enough. Sometime we need more than 3 but it shouldn't be general.

Actually you should separate your project into libraries rather than modules. When you have a really big project you can split into group of features module should not each module for each feature.

Trikke commented 8 years ago

It al depends on you/your teams needs. Large applications can exist is one module. And even then, things can change, there is nothing wrong with refactoring project structures of the scope of the project increases. The hard part about "one feature per module" is that usually features share a lot of different code, so you'll end up with a lot of modules and code all over the place, and dependency hell.

The 3-tier module setup in this example is a very handy one because of several reasons, but this also makes a project packaged by layer, instead of feature. There's an ongoing discussion here about project structures. I posted some more ways to structure there.

RowlandOti commented 8 years ago

This here is an interesting conversation. I never before saw things the way @Trikke puts them.

"I'd say you shouldn't think of features and feature-teams so rigidly." - superb

Glad to borrow a new lens for coding sight. @Trikke , would you mind sharing a repo or blog outlining the given code arrangement?

android10 commented 8 years ago

Having a module per feature is a lot of overhead and unnecessary complexity. Why you wanna do that? We do not work that way at SoundCloud, not even close. We actually have a similar arquitectural approach to this repo but with only one module. This solution came out of my personal experience and it has nothing to do with my employer.

FranRiadigos commented 8 years ago

If you have your activities isolated on modules, How are you starting those activities from different modules?

varunachar commented 8 years ago

Certain features are pretty good candidates for modules, e.g. the authentication module or a networking module and even in some cases, certain design elements that are common amongst company apps. In my case, we're using a google maps and google location services that intends to collect a lot of data points which are going to be fed into our servers to help optimize routing tech, and do data collection etc. This module is going to be installed on 2 different apps targeted for 2 different set of users. Putting such a component along with its resources into a separate module makes sense.

@kuassivi : The main app has a dependency on the other modules and the main app controls all navigation, so moving between activities is via the main app.

varunachar commented 8 years ago

Anyway.. I have received my answer.

Thanks for helping out.

Trikke commented 8 years ago

@RowlandOti There's an ongoing discussion here about project structures. I posted some more ways to structure there.

RowlandOti commented 8 years ago

@Trikke , see comment here . I might need some criticism on organisation by layer, then by feature.