I have a poroject that was developed by other developer. There are a lot of public static fields, arrays and etc. And this public static fields are being called like from everywhere(every class). It causes a lot of crashes. I need some architectural advice. Anyway, im gonna need to refactor all this code. How can i avoid using static fields? I know how to do it using interface, espessially when dealing with activity-fragment communication. Maybe you can suggest some libraries for this purposes?
You can use Dagger 2 for dependency injection.
Introduction from http://code.tutsplus.com/, also this is a very good tutorial for using dagger.
When you have an object that needs or depends on another object to do its work, you have a dependency. Dependencies can be solved by letting the dependent object create the dependency or asking a factory object to make one. In the context of dependency injection, however, the dependencies are supplied to the class that needs the dependency to avoid the need for the class itself to create them. This way you create software that is loosely coupled and highly maintainable.
Also check this tutorial too for better understanding.
Related
I am learning DI with Dagger2 and Hilt and I've got a question:
When creating android app I notice that I use lots of utility classes with static methods(i.e. a function that receives temperature in Celsius and return it in Fahrenheit). BUT, also I use a class (say NetworkUtils) with a static utility method for performing network call to get data from API (as what Android Nanodegree course's instructors were doing):
What I do is like:
class NetworkUtils{
public static String fetchCityName(double latitude, double longitude){
// code for API call
}
}
And now, while I am learning DI principles from Developer Docs, I notice that network calls are made in an instance class within an instance method and its parameters are injected using Dagger.
Why does this make difference from what I was doing?
I read that static methods make testing not easy, however, suppose I used DI like the docs shows,
Why do I have to instantiate a new object of the NetworkUtils whenever I need to perform API call while creating multiple instances is useless?
Also, the official docs says that our use of #Singleton annotation to set function scope (i.e. for a REST API call function) should be very rare, then:
Am I supposed to create instances for everything I need to use even tho it doesn't need to? (except for expensive object instantiation)
Eventually, could you please clarify the difference between a utility class and a normal class that I should not use static methods in it?
Thanks.
And now, while I am learning DI principles from Developer Docs, I
notice that network calls are made in an instance class within an
instance method and its parameters are injected using Dagger.
Why does this make difference from what I was doing? I read that static methods make testing not easy, however, suppose I used DI like
the docs shows,
I see two main reasons:
First, of course, is that the static calls make the code hard to test. But yes, there are some testing frameworks that can do the work for you and mock static calls. But whenever you are using them - it most likely means that you are doing something wrong or you are working with legacy code. This leads me to the second topic.
The idea of TDD - Test Driven Development is that you write the tests first, the code second. But the tests "are not important". Actually, the real result is the better code! The unit test just helps, but they are subproducts. Most of the time there is a high correlation between a good code and a testable code. When you have static calls and singletons it is easy for you to call this code from wherever you want. The result is that you stop thinking about design, about the real OOP principles - what is what. You do not think about extra objects, the relation between objects, etc. And you end up with a spaghetti code. Everything is tied to everything else.
Why do I have to instantiate a new object of the NetworkUtils whenever I need to perform API call while creating multiple instances
is useless? Also, the official docs says that our use of #Singleton
annotation to set function scope (i.e. for a REST API call function)
should be very rare, then:
You are saying something which is contradictory - "creating multiple instances is useless". Obviously creating an instance and not using a static call helps you to achieve better and testable code. Maybe you are wondering if it is a performance hit. Here I will quote.. maybe Martin Fowler... but in his book about Refactoring he is explaining that 9 out of 10 times the optimizations are just useless. You are overdoing it. You need to write good code. Then evaluate. Then if there is a need for optimization - you have the good code - the optimization will be relatively easy.
In your case - do not worry. Wrapping the network calls in instance classes will cause how many instances? 3? 5? It is not a problem when you evaluate the benefits.
About the Singleton - you do not need a shared state - so no need for a singleton. You will shoot yourself in the foot. You will keep things that can be garbage collected, add extra code for singleton creation, etc. Just plain object and that's all.
Am I supposed to create instances for everything I need to use even tho it doesn't need to? (except for expensive object
instantiation)
This is a huge question. You should read a few books and still will not know the answer. Try with Uncle Bob's Clean Code and also Martin Fowler's Refactoring. Then read a few articles of people who think that they are overdoing it and find the balance for yourself. In general, you should no be using "new" and any static calls.. But for example, there are a lot of discussions about how useful are really unit tests on Android and there are a lot of people who tend to go in the direction that you need mostly integration and End to End tests. I will not argue what is the right approach.
4. Eventually, could you please clarify the difference between a utility class and a normal class that I should not use static methods
in it?
Basically, you should not be using "Utility classes". Their idea is to wrap some code, which is used in many places, but there is no state involved. You do not need instance variables so the static methods were a good idea. But it will totally kill your testing. So in your case, you should make one type of class and if you need state - add, if you do not need state - just don't. Then you can call the classes whatever you want.
In Clean Architecture, Robert Martin says:
It is in your Main component that dependencies should be injected by a
Dependency Injection framework. Once they are injected into Main, Main
should distribute those dependencies normally, without using the
framework.
Martin, Robert C.. Clean Architecture (Robert C. Martin Series) (p.
232). Pearson Education. Kindle Edition.
However, Dagger doesn't work this way. Once you set up your dependencies in your application, you still need to depend on it as a framework, e.g. write #Inject annotations to get the dependencies into your classes. There is no way to 'distribute these dependencies' normally, by which I assume he means passing them through a constructor?
Can anyone help clear up my understanding and how best to use Dagger with a Clean style?
On Android, exactly following the advice you quoted from Robert Martin is rather difficult.
This is because there is no precise main entry point. Application, Service and Activity are quasi-entry points as your app will start with the OS instantiating one of these.
However, you don't have control over the constructor or anything really before the lifecycle callbacks. Hence, Dagger 2 on Android has had to rely on manually calling requesting a Component and calling Component#inject() inside lifecycle callbacks quasi-entry points.
However, there have been some measures to address this problem. Dagger-Android goes some way to address this by making you depend on AndroidInjector rather than some series of calls to the Application in order to retrieve the Component manually.
Even further, there is now FragmentFactory that allows control over the constructor of a Fragment, making Fragments amenable for constructor injection. If we use this then we have gone some way to following Robert Martin's advice.
To clarify the original quotation, I believe Robert Martin means that classes apart from the component root should not be polluted with logic for obtaining dependencies (e.g., by reaching into the Application, pulling out the Dagger Component). He is not prohibiting the use of the #Inject annotation which is lightweight meta-data (part of JSR-330) that simply marks a constructor as a site for injection.
In summary, yes - the current way of using Dagger 2 on Android doesn't exactly comply with Robert Martin's excellent recommendation. Nevertheless, this is a known problem and some progress has been made towards solving it.
I saw this question, but it was from the point of testability.
In my case, I see Dagger as an additional complexity for code (create #Provides methods, inject methods, remember all the right annotations). Should I still use Dagger if I just want to inject singletons like SharedPrefUtils? Is it really faster for this case?
Dagger was not made for creating Singletons and if creating a singleton is the reason you want to add Dagger to your project, then its an overkill. Dagger is a dependency injection framework that helps make the process of providing and injecting dependencies easier in a complex project. The #Singleton would help you ensure that only a single instance of a class is created when satisfying your dependencies it is not an alternative to the Kotlin object, they could even be used together. So like other answers and comments suggest if you have a small project and you could use simple design patterns like Singleton, Factory, and Abstract factory pattern.
Dagger is a dependency injection framework. For very simple applications, you can go with manual injection which will save you time because dagger can be difficult to set up and work with from the beginning. However, if you are planning on a production application which has a very long life span and will contain multiple UIs and multiple classes, then you are definitely going to need a dependency injection framework or strategy along the line.
There is an alternative for Kotlin which is Koin. Koin works more like a Service Locator and is easier to set up than Dagger but I will prefer dagger because it has survived the test of time.
It is up to you whether you want to use automatic dependency injection or manual injection so in the end you weigh your options and see what best fits your use case.
It seems to be impossible but I can't find it written explicitly. Is there a clear reason for that ?
Thanks
That's not possible. A component can either inject everything at once or the compilation will fail with a cannot be provided error, listing what it's missing.
After all you can't partially call a constructor (if using constructor injection) and also partially injecting fields would be rather indeterministic about which objects were injected when, how, or with which scope. If both components could supply a dependency, which should provide it? Do you create and inject the object twice? What if another object depends on it in the other component? It would create more confusion than any good it could do and provide a source for a lot of errors and unexpected behavior.
Only one component can be used to inject inside a given class. You can have several subcomponents dependencies installed on it though.
I have an android app which encrypts and uploads various files to AWS. The boiler plate code for AWS is a singleton, and I use that throughout my app. I have an encryption class as well, and I am currently instantiating encryption objects in various places, encrypting the file, and passing it to the singleton instance of the AWS upload class.
I am wondering if this is the best approach? Should i make the instance of the encryption object static? And have just one instantiated, and then call the encrypt method from different classes? In some places it is recommended, in others people say using static can be dangerous? Or is there a better way than either of these options?
Should note the app works fine as is, but I am a self taught Android dev, and I am trying to get better, but none of the tutorials go into heaps of detail about things like this.
Static is not dangerous, it's to share operations that don't depend on instances of objects. Like the Math class.
Singleton pattern is for controlling instances of objetcs of some class. If you want an instance, and only one instance, you use singletons. Generally, people use it to get that instance at a global scope. I think the Application class would fit this.
I prefer to use dependency injection if I am working with a lot of service classes. Encryption is a service to me, but you have to do the mechanism for dependency injection, or use a framework, but this is overkill to your problem.
I would go for the static methods this time.
Creating a Singleton class or making your object static, both are good options if you have to use the method of a class on various places. It's better to have a static object then creating the same object again and again.
So according to me the "Singleton" class is the best option to make your code efficient, but if you want to go with a static method/class then there is no harm in it. Static can be dangerous in some situations, like when you have to assign different values and get different values in different situations. Then there is a chance you can get wrong value in wrong situation. But in your case it's fine.