Is "inject everything" a bad practice in Android? - java

Studying about dependency injection I found some approaches that suggests to inject everything and other saying that it's not necessary to do so.
In my current project, my rule of thumb regarding Dependency Injection is "if the class was created by me, I make it injectable". In other words only classes like SimpleDateFormat, ArrayList, HashMap are newables in my project. My intent doing this approach is that I can #Inject any class anywhere once calling Injector.getApplicationComponent().inject(this) in the Activity. Basically all my classes have a non-args constructor with #Inject.
I was primary using DI because I thought it will improve the performance and memory usage once the new operator is used exclusively by the Dagger generated classes. But I read a post from Dagger 1 developer saying that DI does not have impact on performance and the usage is basically to reduce boilerplate.
The first question is:
Dagger 2 does not any performance advantage in Android application?
My project is running without problems and I think the approach of "inject everything" helps organizing better, despite some drawbacks.
An example of usage of this approach is the following class:
public class TimelineEntryAdapter {
#Inject
Provider<TwitterEntry> mTwitterProvider;
#Inject
Provider<InstagramEntry> mInstagramProvider;
#Inject
Provider<FacebookEntry> mFacebookProvider;
#Inject
TimelineEntryComparator mComparator;
#Inject
public TimelineEntryAdapter() {
}
The second question is:
Is it a bad practice to inject everything in Android?
If the answer for the second question is "No", there is a better way to handle the non-args constructor to create classes? Because when I create an non-args constructor with #Inject annotation and a class need some parameters to work with, I must use setters:
public class SavelArtist {
private MusicBrainzArtist mMusicBrainzArtist;
private DiscogsArtist mDiscogsArtist;
private List<SavelTweet> mTweetList;
private SpotifyArtist mSpotifyArtist;
private List<SavelInstagram> mInstaTimeline;
private List<SavelFacebook> mFacebookTimeline;
private List<SavelRelease> mReleases;
#Inject
Provider<SavelRelease> mReleaseProvider;
#Inject
public SavelArtist() {
}
public void setMusicBrainzArtist(MusicBrainzArtist mbArtist) {
mMusicBrainzArtist = mbArtist;
}
public void setDiscogsArtist(DiscogsArtist discogsArtist) {
mDiscogsArtist = discogsArtist;
}
public void setTweetList(List<SavelTweet> tweetList) {
mTweetList = tweetList;
}
public void setSpotifyArtist(SpotifyArtist spotifyArtist) {
mSpotifyArtist = spotifyArtist;
}
public void setInstaTimeline(List<SavelInstagram> instaTimeline) {
mInstaTimeline = instaTimeline;
}
public void setFacebookTimeline(List<SavelFacebook> fbTimeline) {
mFacebookTimeline = fbTimeline;
}
All the parameters could be set on the constructor, once all are get at the same time in the flow.

Studying about dependency injection I found some approaches that suggests to inject everything and other saying that it's not necessary to do so.
The froger_mcs blog entry you quote doesn't advocate injecting everything. It quite clearly states:
The purpose of this post is to show what we can do, not what we should do.
And it goes on to state a disadvantage of injecting everything:
If you want to use Dagger 2 for almost everything in your project you will quickly see that big piece of 64k methods count limit is used by generated code for injections.
Now, on to your questions:
Dagger 2 does not any performance advantage in Android application?
While Dagger 2 offers a performance advantage over other reflection-based DI frameworks (such as Guice) it doesn't claim to offer any performance advantage over manually constructing your object graphs by calling constructors. You can inspect the generated classes yourself to see that these indeed still eventually call constructors.
Is it a bad practice to inject everything in Android?
Well let's take the following very common Android code:
Intent nextActivity = new Intent(this, NextActivity.class);
startActivity(nextActivity);
Should we extract an IntentFactory and inject this using Dagger 2 merely to avoid the new keyword here? At this point, it is easy to approach pedantry. The advice in the other answer you quoted about the difference between injectables and newables is more flexible and elegant.
Moving on to your next question:
If the answer for the second question is "No", there is a better way to handle the non-args constructor to create classes? Because when I create an non-args constructor with #Inject annotation and a class need some parameters to work with, I must use setters:
Using setters is the wrong approach for parameters. You should distinguish dependencies and parameters. Dependencies normally have the same lifecycle as the object itself. During the lifetime of the object, the methods exposed for that object may be called with different parameters.

I'm not a professional at dependency-management but I use it in my company so here's how I see it.
Inject everything is basically good. I make everything that is used somewhere else ( other modules, classes, packages ) injectable and only static things ( static classes with hidden constructor ), things that get only used internally non injectable.
What's the advantage of it?
Well The dependency system will take care of getting the instance and to discard it. It will clean up automatically. Also using scopes on the classes will enable you to make a class that always has only one instance in the whole application ( multiple threads access it) or make it reusable ( every thread that needs it get's an own instance ).
Also I think you could clean up your classes like this:
#Reusable (Maybe a good Idea?)
public class SavelArtist {
private MusicBrainzArtist mMusicBrainzArtist;
private DiscogsArtist mDiscogsArtist;
private List<SavelTweet> mTweetList;
private SpotifyArtist mSpotifyArtist;
private List<SavelInstagram> mInstaTimeline;
private List<SavelFacebook> mFacebookTimeline;
private List<SavelRelease> mReleases;
private Provider<SavelRelease> mReleaseProvider;
public SavelArtist() {
}
#Inject
public void init(Provider<SavelRelease> mReleaseProvider) {
this.mReleaseProvider = mReleaseProvider;
}
Think about always declaring the scope of the class. Is it a Singleton? Will it be reusable? This little detail can save you, once the application get's complex and big.
The advantage of using the method init to declare all injected variables is to have a clean looking code which is easy maintainable since everything injected is at this one location. But that's actually preference :)

Related

Is it good practice to inject variables in a Utility class?

I have the below Utility class in Java.
public class Utils {
private static Properties commonProps;
private Utils() {}
private static setCommonProps(Properties commonProps) {
Utils.commonProps = commonProps;
}
public static boolean staticMethod1() {
commonProps.get("xyz");
}
public static void staticMethod2() {
}
}
And we initialize "commonProps" with the help of Spring function org.springframework.beans.factory.config.MethodInvokingFactoryBean.
Is there anything wrong in this design of code? Can this have any bad effects?
Is it a good practice to have such variable initialization for Utility classes?
NOTE: Here "Properties commonProps" is just a placeholder. Any common member that need to be used in this class which has to be injected during startup.
In general, dependency injection is a good thing as it leads to better designs that are easier to test. In your particular case, you have to look at what you are trying to achieve.
It appears that you are trying to provide a single point to access properties through and add some value over the standard Java Properties API. For example, by providing a getBoolean() equivalent.
With regards to the single point of access you'll need to consider threading issues. However, as long as you can guarantee that your utility class is configured before you use its static methods you should be okay.
With regards to extending the Properties API, you might be better served using one of the existing libraries rather than incurring the cost of writing and maintaining your own. For example, I've found Apache Commons Configuration to be quite good.
Do not not have any mutability in static fields. That is an anti-pattern. Also do not inject static fields using Spring. Doing these things will make your code unwieldily to work with, and very hard to test.
You already have the ability to use #Value to inject fields with properties within beans. Although this is not dynamic but you really shouldn't have dynamic properties (although it's possible IMO it's not a good idea). Think of properties as startup constants or something. They shouldn't change.

Java - correct way to delegate methods

My program gets information from an external source (can be a file, a database, or anything else I might decide upon in the future).
I want to define an interface with all my data needs, and classes that implement it (e.g. a class to get the data from a file, another for DB, etc...).
I want the rest of my project to not care where the data comes from, and not need to create any object to get the data, for example to call "DataSource.getSomething();"
For that I need DataSource to contain a variable of the type of the interface and initialize it with one of the concrete implementations, and expose all of its methods (that come from the interface) as static methods.
So, lets say the interface name is K, and the concrete implementations are A,B,C.
The way I do it today is:
public class DataSource {
private static K myVar = new B();
// For **every** method in K I do something like this:
public static String getSomething() {
return myVar.doSomething();
}
...
}
This is very bad since I need to copy all the methods of the interface and make them static just so I can delegate it to myVar, and many other obvious reasons.
What is the correct way to do it? (maybe there is a design pattern for it?)
**Note - since this will be the backbone of many many other projects and I will use these calls from thousands (if not tens of thousands) code lines, I insist on keeping it simple like "DataSource.getSomething();", I do not want anything like "DataSource.getInstance().getSomething();" **
Edit :
I was offered here to use DI framework like Guice, does this mean I will need to add the DI code in every entry point (i.e. "main" method) in all my projects, or there is a way to do it once for all projects?
The classes using your data source should access it via an interface, and the correct instance provided to the class at construction time.
So first of all make DataSource an interface:
public interface DataSource {
String getSomething();
}
Now a concrete implementation:
public class B implements DataSource {
public String getSomething() {
//read a file, call a database whatever..
}
}
And then your calling class looks like this:
public class MyThingThatNeedsData {
private DataSource ds;
public MyThingThatNeedsData(DataSource ds) {
this.ds = ds;
}
public doSomethingRequiringData() {
String something = ds.getSomething();
//do whatever with the data
}
}
Somewhere else in your code you can instantiate this class:
public class Program {
public static void main(String[] args) {
DataSource ds = new B(); //Here we've picked the concrete implementation
MyThingThatNeedsData thing = new MyThingThatNeedsData(ds); //And we pass it in
String result = thing.doSomethingThatRequiresData();
}
}
You can do the last step using a Dependency Injection framework like Spring or Guice if you want to get fancy.
Bonus points: In your unit tests you can provide a mock/stub implementation of DataSource instead and your client class will be none the wiser!
I want to focus in my answer one important aspect in your question; you wrote:
Note - I insist on keeping it simple like "DataSource.getSomething();", I do not want anything like "DataSource.getInstance().getSomething();"
Thing is: simplicity is not measured on number of characters. Simplicity comes out of good design; and good design comes out of following best practices.
In other words: if you think that DataSource.getSomething() is "easier" than something that uses (for example) dependency injection to "magically" provide you with an object that implements a certain interfaces; then: you are mistaken!
It is the other way round: those are separated concerns: one the one hand; you should declare such an interface that describes the functionality that need. On the other hand, you have client code that needs an object of that interface. That is all you should be focusing on. The step of "creating" that object; and making it available to your code might look more complicated than just calling a static method; but I guarantee you: following the answer from Paolo will make your product better.
It is sometimes easy to do the wrong thing!
EDIT: one pattern that I am using:
interface SomeFunc {
void foo();
}
class SomeFuncImpl implements SomeFunc {
...
}
enum SomeFuncProvider implements SomeFunc {
INSTANCE;
private final SomeFunc delegatee = new SomeFuncImpl();
#Override
void foo() { delegatee.foo(); }
This pattern allows you to write client code like
class Client {
private final SomeFunc func;
Client() { this(SomeFuncProvider.INSTANCE); }
Client(SomeFunc func) { this.func = func; }
Meaning:
There is a nice (singleton-correctway) of accessing an object giving you your functionality
The impl class is completely unit-testable
Client code uses dependency injection, and is therefore also fully unit-testable
My program gets information from an external source (can be a file, a database, or anything else I might decide upon in the future).
This is the thought behind patterns such as Data Access Object (short DAO) or the Repository pattern. The difference is blurry. Both are about abstracting away a data source behind a uniform interface. A common approach is having one DAO/Repository class per business- or database entity. It's up to you if you want them all to behave similarly (e.g. CRUD methods) or be specific with special queries and stuff. In Java EE the patterns are most often implemented using the Java Persistence API (short JPA).
For that I need DataSource to contain a variable of the type of the
interface and initialize it with one of the concrete implementations,
For this initialization you don't want to know or define the type in the using classes. This is where Inversion Of Control (short IOC) comes into play. A simple way to archieve this is putting all dependencies into constructor parameters, but this way you only move the problem one stage up. In Java context you'll often hear the term Context and Dependency Injection (short CDI) which is basically an implementation of the IOC idea. Specifically in Java EE there's the CDI package, which enables you to inject instances of classes based on their implemented interfaces. You basically do not call any constructors anymore when using CDI effectively. You only define your class' dependencies using annotations.
and expose all of its methods (that come from the interface)
This is a misconception. You do want it to expose the interface-defined method ONLY. All other public methods on the class are irrelevant and only meant for testing or in rare cases where you want to use specific behavior.
as static methods.
Having stateful classes with static method only is an antipattern. Since your data source classes must contain a reference to the underlying data source, they have a state. That said, the class needs a private field. This makes usage through static methods impossible. Additionally, static classes are very hard to test and do not behave nicely in multi-threaded environments.

Is it bad to use constructor injection and default constructors together?

I'm currently trying to improve the testability of a legacy system, written in Java. The most present problem is the presence of “inner” dependencies which cannot be mocked out. The solution to this is pretty simple: Introduce dependency injection.
Unfortunately the code base is pretty large, so it would be a huge effort to introduce dependency injection throughout the whole application, up to the “bootstrapping”. For each class I want to test, I would have to change another hundred (maybe I’m exaggerating a bit here, but it definitely would be a lot) classes, which depend on the changed component.
Now to my question: Would it be ok, to use a two constructors, a default constructor which initialize the instance fields with default values and another one to allow the injection of dependencies? Are there any disadvantages using this approach? It would allow dependency injection for future uses but still doesn’t require the existing code to change (despite the class under test).
Current code (“inner” dependencies):
public class ClassUnderTest {
private ICollaborator collab = new Collaborator();
public void methodToTest() {
//do something
collab.doComplexWork();
//do something
}
}
With default / di constructor:
public class ClassUnderTest {
private ICollaborator collab;
public ClassUnderTest() {
collab = new Collaborator();
}
public ClassUnderTest(ICollaborator collab) {
this.collab = collab;
}
public void methodToTest() {
//do something
collab.doComplexWork();
//do something
}
}
This is absolutely fine, I do this occasionally also, especially with service-style classes where a default constructor is necessary because of legacy code or framework constraints.
By using two constructors, you're clearly separating the default collaborator objects while still allowing tests to inject mocks. You can reinforce the intent by making the second constructor package-protected, and keeping the unit test in the same package.
It's not as good a pattern as full-blown dependency injection, but that's not always an option.
I think this is perfectly OK. I would write the default-constructor in terms of the parametrized one, but that is probably a question of style and preference.
What I would be more cautious about is adding a setCollaborator()-function, because this radically changes the contract (and assumptions) for ClassUnderTest, which will lead to strange error-scenarios if called from code written by someone who doesn't know the history, haven't read the docs properly (or maybe there isn't any docs at all...)

annotation to make a private method public only for test classes [duplicate]

This question already has answers here:
How do I test a class that has private methods, fields or inner classes?
(58 answers)
Closed 5 years ago.
Who has a solution for that common need.
I have a class in my application.
some methods are public, as they are part of the api,
and some are private, as they for internal use of making the internal flow more readable
now, say I want to write a unit test, or more like an integration test, which will be located in a different package, which will be allowed to call this method, BUT, I want that normal calling to this method will not be allowed if you try to call it from classes of the application itself
so, I was thinking about something like that
public class MyClass {
public void somePublicMethod() {
....
}
#PublicForTests
private void somePrivateMethod() {
....
}
}
The annotation above will mark the private method as "public for tests"
which means, that compilation and runtime will be allowed for any class which is under the test... package , while compilation and\or runtime will fail for any class which is not under the test package.
any thoughts?
is there an annotation like this?
is there a better way to do this?
it seems that the more unit tests you write, to more your inforced to break your encapsulation...
The common way is to make the private method protected or package-private and to put the unit test for this method in the same package as the class under test.
Guava has a #VisibleForTesting annotation, but it's only for documentation purposes.
If your test coverage is good on all the public method inside the tested class, the privates methods called by the public one will be automatically tested since you will assert all the possible case.
The JUnit Doc says:
Testing private methods may be an indication that those methods should be moved into another class to promote reusability.
But if you must...
If you are using JDK 1.3 or higher, you can use reflection to subvert the access control mechanism with the aid of the PrivilegedAccessor. For details on how to use it, read this article.
Consider using interfaces to expose the API methods, using factories or DI to publish the objects so the consumers know them only by the interface. The interface describes the published API. That way you can make whatever you want public on the implementation objects and the consumers of them see only those methods exposed through the interface.
dp4j has what you need. Essentially all you have to do is add dp4j to your classpath and whenever a method annotated with #Test (JUnit's annotation) calls a method that's private it will work (dp4j will inject the required reflection at compile-time). You may also use dp4j's #TestPrivates annotation to be more explicit.
If you insist on also annotating your private methods you may use Google's #VisibleForTesting annotation.
An article on Testing Private Methods lays out some approaches to testing private code. using reflection puts extra burden on the programmer to remember if refactoring is done, the strings aren't automatically changed, but I think it's the cleanest approach.
Or you can extract this method to some strategy object. In this case you can easily test extracted class and don't make method public or some magic with reflection/bytecode.
Okay, so here we have two things that are being mixed. First thing, is when you need to mark something to be used only on test, which I agree with #JB Nizet, using the guava annotation would be good.
A different thing, is to test private methods. Why should you test private methods from the outside? I mean.. You should be able to test the object by their public methods, and at the end that its behavior. At least, that we are doing and trying to teach to junior developers, that always try to test private methods (as a good practice).
I am not aware of any such annotation, however the following may be of value: unit testing private methods
or the following: JMockit
You can't do this, since then how could you even compile your tests? The compiler won't take the annotation into account.
There are two general approaches to this
The first is to use reflection to access the methods anyway
The second is to use package-private instead of private, then have your tests in the same package (but in a different module). They will essentially be private to other code, but your tests will still be able to access them.
Of course, if you do black-box testing, you shouldn't be accessing the private members anyway.
We recently released a library that helps a lot to access private fields, methods and inner classes through reflection : BoundBox
For a class like
public class Outer {
private static class Inner {
private int foo() {return 2;}
}
}
It provides a syntax like :
Outer outer = new Outer();
Object inner = BoundBoxOfOuter.boundBox_new_Inner();
new BoundBoxOfOuter.BoundBoxOfInner(inner).foo();
The only thing you have to do to create the BoundBox class is to write #BoundBox(boundClass=Outer.class) and the BoundBoxOfOuter class will be instantly generated.
As much as I know there is no annotation like this. The best way is to use reflection as some of the others suggested. Look at this post:
How do I test a class that has private methods, fields or inner classes?
You should only watch out on testing the exception outcome of the method. For example: if u expect an IllegalArgumentException, but instead you'll get "null" (Class:java.lang.reflect.InvocationTargetException).
A colegue of mine proposed using the powermock framework for these situations, but I haven't tested it yet, so no idea what exactly it can do. Although I have used the Mockito framework that it is based upon and thats a good framework too (but I think doesn't solve the private method exception issue).
It's a great idea though having the #PublicForTests annotation.
Cheers!
I just put the test in the class itself by making it an inner class:
https://rogerkeays.com/how-to-unit-test-private-methods

Java Style / Best Practice - passing fields to methods vs accessing directly

In Java, given the following class:
public class MyClass {
private final Dependency dependency;
public MyClass(Dependency dependency)
{
this.dependency = dependency;
}
public void doWork()
{
// validate dependency...
}
The doWork method needs to invoke a method that uses dependency.
Which of the following two variations is considered "best practice", and why?
// Access dependency directly
void validateDependency()
{
this.dependency.something();
}
// access dependency as passed to the method
void validateDependency(Dependency dependency)
{
dependency.something();
}
I find myself favouring the latter, passing the dependency directly to the method, as it makes the method easier to test in isolation (albeit, marginally).
However, I'm interested in the java convention / best practice here.
A class exists because you have state and operations that are coupled to that state. There's no good reason to pass part of that state as a parameter to a class method.
In fact, it would indicate to me that that piece of state should not actually belong to the class. Or that the method doesn't belong to the class.
Using a parameter "so that it's easier to unit test" is a good indication that the latter holds (the method should not be in the class).
Well, in your example you are asking the function to do something with Dependency which lends itself to a static function, not a member function.
My rule of thumb is: Use members directly when calling a method on an object that owns the member but pass references when doing/testing something directly related to the dependency and favor static methods for the latter
That a bit verbose but I hope it helps. As always try to "do the right thing" and differences this small won't likely make a huge impact on maintenance or readability of your code.
There isnt a right way to do it. I prefer just putting the variable there.
Dependency injection. The second option is "best".
If you make your "Dependency" class an interface it makes code more modular, easier to test, less coupled.

Categories

Resources