In an Android project, I am using dagger 2 for dependency injection, applying mvp design pattern, and I am writing interface for almost every class. Although it does achieved the separation of concerns, each individual logic is not coupled with others. But for just making a simple REST call, it involved 20 plus java class files which makes the codebase to become very complex, I start to think is it normal to have 20 plus java classes for just making a simple REST call? Should I be really doing the MVP pattern and writing interfaces for every classes, or I am just doing it wrong?

For Dagger 2, it requires to set up components, modules and scopes, that's 5 files including the parent and child components.

For MVP pattern, there is an interface and an interface implementation class for the Model, View and Presenter, that's 6 files already. For the presenter, there is another layer that does the actual work of REST call, that's 4 files, interfaces and interface implementations for doing the REST call and result handling.

Plus the activity class and it's parent class and some other utility classes and xml files, that's 20 plus files.

If I remove dagger 2, remove the MVP pattern, and remove all the interfaces, I could achieve the same in few java classes or even just one java class. If I give this 20 files to myself a few years ago, I might have no idea how each connect to others, can only do the guess work probably, even now I found it a lot harder to trace through the code compared to the version without the DI, MVP and interfaces.

  • Sounds like too many to me. There is no right or wrong; there is only that which best meets your software's functional and non-functional requirements. – Robert Harvey Jul 21 '16 at 23:05
  • 3
    Is that 20 classes for each REST call, or 20 classes to set up the infrastructure that handles all your REST calls? – Karl Bielefeldt Jul 21 '16 at 23:08
  • @KarlBielefeldt: It seems like an awful lot of classes either way. – Robert Harvey Jul 21 '16 at 23:09
  • 1
    Why don't you post all twenty classes to a question on Code Review, and see what they have to say about it. I'm quite curious, actually. – Robert Harvey Jul 21 '16 at 23:10
  • I've updated the question with the file counts – s-hunter Jul 21 '16 at 23:28

Is 20 Java classes for just making...

This is entirely the wrong question. Something is wrong or you wouldn't be asking. It sounds like you're looking for something to blame. Anguishing over the number of classes isn't going to fix it.

I've felt this same pain before. You step back and look at everything. It works. You can kinda follow it. But you know looking at it later you're going to be lost. You don't like that. You want to fix it now while you can follow it. Setting a limit on the number of classes because you're just trying to do x isn't going to fix it.

What will fix it is abstraction.

Why do you CARE that there are 20 classes? It may be because they're all showing up in one place so now you have to think about them all at once. That is what's bad.

20 is a big number. 4 and 5 are not. I wouldn't mind seeing 4 groups that each had 5 classes working together. That's still 20. It's just organized so it's easier to look at.

Sometimes a dependency injection framework makes it easy to take a procedural attitude to construction. You just create a pile of links between objects that has no structure to it. It's easy to write. Not so easy to read.

If you've dumped all of them into one file that defines how they link together you're looking at the entire object graph at once. With only 5 classes that can start to be painful. Find some logical separations. Break things down. Group objects together that have to do with each other. Separate those that don't.

A big thing that can help with this is creational patterns. When you expose every dependency an object has, you make building it a nuisance. A good builder lets you separate the dependencies that change often from the dependencies that don't. Rather than hide dependencies in the object you hide them in the builder. When good defaults are available they should be easy to use.

As for interfaces you're saving grace here is you said "almost". I HATE when people blindly extract interfaces without thinking about what they're doing. It's completely backwards to think an interface BELONGS to the class that implements it. No, clients OWN the interface. The interface exists FOR the client, should be defined BY the client, and may not ever change except at the CONSENT of the client. If you happen to be an object that implements that interface, good for you. Now shut up and do what you're told. The client doesn't even want to know you exist.

That said, I LIKE interfaces. Mostly because when I write clients that refer to them and not implementations I'm not tempted to use new on them. The big exception to this is value objects. Strings don't need you creating interfaces for them. If you use other value objects, even ones of your own design, generally you don't give them interfaces, you shouldn't give them behavior, don't really need to test them, and shouldn't ever change them. You know, like strings.

Now if you're talking about a behavior object that has to actually do some thinking then test that damn thing.

If you're doing MVP, setting up dagger components, modules and scopes, you're doing a hell of a lot more than just REST.

  • those 20+ files are not in one place, they are grouped into packages. Maybe I should change the question to is it worth it to spend a lot of time on DI, MVP, Interfaces, making a hell lot of relations to link all these together which gives me decoupled and testable code but a complex codebase that is not easy to understand and trace the code – s-hunter Jul 22 '16 at 3:31
  • Those links and relations are exactly what should be abstracted. At any one time don't show me more than 7 of the same thing going on or my eyes glaze over. If I draw it, it should fit on one piece of paper (letter sized, with 12 pt font). Have as many pages as you like but no stitching them together to make a poster. The relations between pages must be simple. I've added a paragraph about how creational patterns can help with that. – candied_orange Jul 22 '16 at 3:54

Just a hunch, but are you writing unit tests? Many small classes over a few large ones become more valuable as you test your code more thoroughly and from more levels of mocked out, unit environments or production-like environments.

I don't think having a large number of classes in Java is a problem or is unusual, but I am concerned that you feel so negative about productivity overall. But again, if you're just not testing, then code quality is an issue. Slowly and painfully writing bug free code is good, or next best, code that is easy to debug via good stack traces and ability to run tests on problematic classes.

One suggestion is to write the "vanilla" version then migrate to MVC, Dagger2, etc. when you feel you increasingly have problems or pain points that would be solved by these frameworks. It's possible to overestimate the cost of a migration just as easily as to underestimate it. This strategy may ease your productivity now give you a sharper understanding of what problems the frameworks should be solving and what pain points are more or less expected.

Your Answer

