I have a PropertiesModule that extends AbstractModule and contains application constants that I use throughout the project:
class PropertiesModule: AbstractModule(), Serializable {
companion object {
const val APP_NAME = "MyAppName"
...
}
override fun configure() {
...
}
}
Then I use the PropertiesModule to create the injector:
...
val injector = Guice.createInjector(
PropertiesModule(),
...
)
And later when I use the injector to get the property value, I have multiple choices. I could do:
val appName = injector.getInstance(
Key.get(String::class.java, Names.named(PropertiesModule.APP_NAME))
)
or
val appName = injector.getExistingBinding(
Key.get(String::class.java, Names.named(PropertiesModule.APP_NAME))
).provider.get()
or
val appName = injector.getProvider(
Key.get(String::class.java, Names.named(PropertiesModule.APP_NAME))
).get()
I read that in general getInstance should be avoided. But I'm not sure what is the difference among them.
If you've just created your Injector, use getInstance. Otherwise, try to get your object from a narrower injection.
getBinding and getExistingBinding are effectively both for reflective purposes:
[Binding is] a mapping from a key (type and optional annotation) to the strategy for getting instances of the type. This interface is part of the introspection API and is intended primarily for use by tools.
Though it would probably work to some degree, I'd recommend against getExistingBinding, if only because it has the counterintuitive behavior of not creating Just-In-Time bindings if they do not already exist, as described in the getExistingBinding docs:
Unlike getBinding(Key), this does not attempt to create just-in-time bindings for keys that aren't bound.
This method is part of the Guice SPI and is intended for use by tools and extensions.
getProvider(Class<T>) will procure a Provider<T> from the graph, which is like a single-key Injector that can only create or retrieve instances of a single key from the Injector. Think of it as creating a lambda that calls getInstance for a specific Key, and nothing more.
getInstance is the most important method on Injector, and I expect all Guice applications to call it at least once. If you've just created your Injector, you'll presumably want to either get an instance from it, or inject the #Inject fields of an object. The former happens with getInstance, and the latter with injectMembers. In my opinion, that's the best way to get the first object out of your graph.
However, and this is where the advice you heard comes in: You should probably not use the Injector after that first getInstance or injectMembers call. This is because the goal in Guice is to make independent components that express their dependencies narrowly so you can replace those dependencies easily. This is the major benefit of dependency injection. Though you have the options of stashing the Injector somewhere static, or injecting the Injector itself into your dependencies, that prevents you from knowing exactly what your class's dependencies are: with an Injector injection, you can inject anything in the world.
To demonstrate (please forgive my Kotlin inexperience):
class BadIdea #Inject constructor(injector: Injector) {
fun doSomething() {
// Bad idea: you don't express this dependency anywhere, and this code
// is nearly unusable without a real Guice Injector
val appName = injector.getInstance(
Key.get(String::class.java, Names.named(PropertiesModule.APP_NAME))
)
}
}
class WorseIdea {
fun doSomething() {
// Worse idea: same as the above, but now you rely on a static!
val appName = StaticInjectorHolder.getInjector().getInstance(
Key.get(String::class.java, Names.named(PropertiesModule.APP_NAME))
)
}
}
class GoodIdea #Inject constructor(#Named(PropertiesModule.APP_NAME) appName: String) {
fun doSomething() {
// Good idea: you express your dep, and anyone can call the constructor
// manually, including you in your unit tests.
}
}
Related
I've recently started to learn Dagger. In order to do that, i've decided to write a simple console application to get the feeling of how various dagger features (like modules, component, subcomponents and component dependencies) fit together in an app architecture. As I don't really understeand it and given how hard it is to find an application sample created with dagger2 which is not Android app, i've decided to open a question here.
The first and probably most important question is: is dagger2 even ment to be used outside android?
If yes, then lets consider a simple application architecture: we have the data layer, service layer and ui layer
Data layer might consist of some kind of facade:
(Following code snippets will be written in Kotlin)
class Entity(var id: Int)
interface Repository {
fun findEntityById(id: Int): Entity?
fun deleteEntity(entity: Entity): Boolean
fun saveEntity(entity: Entity): Boolean
fun findAllEntities(): List<Entity>
}
Then i could have a couple of implementations of this facade:
class InMemoryRepository #Inject constructor() : Repository {
private val entities: MutableList<Entity> = LinkedList()
override fun findEntityById(id: Int): Entity? = entities.firstOrNull { it.id == id }
override fun deleteEntity(entity: Entity) = entities.remove(entity)
override fun saveEntity(entity: Entity) = entities.add(entity)
override fun findAllEntities(): List<Entity> = LinkedList(entities)
}
For which i would have modules:
#Module
interface InMemoryPersistenceModule {
#Singleton
#Binds
fun bindRepository(rep: InMemoryRepository): Repository
}
Service layer would be simpler:
#Singleton
class Service #Inject constructor(repository: Repository) {
fun doSomeStuffToEntity(entity: Entity) {}
}
#Singleton
class AnotherService #Inject constructor(repository: Repository) {
fun doSomeStuffToEntity(entity: Entity) {}
}
But it gets a little bit unlcear when it comes to the UI layer. Lets say i have some kind of android-like activity:
interface Activity : Runnable
And some kind of class that manages those activities:
class UserInterfaceManager {
val activityStack: Stack<Activity> = Stack()
val eventQueue: Queue<Runnable> = LinkedList()
fun startActivity(activity: Activity) = postRunnable {
activityStack.push(activity)
activity.run()
}
fun postRunnable(callback: () -> Unit) = eventQueue.add(callback)
fun stopActivity() { TODO() }
//other
}
How does dagger fit into this scenario? The articles i have read about the the dagger with android suggest createing the application component to inject my activites:
#Singleton
#Component(modules = [InMemoryPersistenceModule::class])
interface ApplicationComponent {
fun injectSomeActivity(activity: SomeActivity)
// and more
}
But then, where would the injection go to? It does't really make sense to put it in the UserInterfaceManager as Activities will most likely need an instance of it, which would create a circular dependency.
I also do not like the idea of the component being obtained from some kind of static method/property and injecting the activity from inside of it at the startup, as it creates duplicate lines of code in each activity.
Also, where do components and subcomponents fit in this kind of architecture? Why not create the separate
component for the data layer and expose just the repository and declare it as a dependency of the app component which would further isolate the details from abstraction? Maybe i should declare this component a dependcy of a service component which would enforce the layer architecure, as components can only use the types exposed in component interface? Or maybe i should use compoenent only when i need a custom scope and use the modules everywhere elsewhere?
I just overally think I am missing the bigger picture of the dagger. I will be really greatefull for answers, explanations and links to articles and other resouces that will let me understeand it better.
From the perspective of an Android developer, I fully understand your point. I asked myself this question too. The way how you construct an object in plain Java/Kotlin world is a little bit different. The main reason is due to the fact basic Android components (Activity/Fragment) don't allow constructor injection.
The answer to your question is, though, pretty straightforward. The Dagger Component is responsible for object creation, and you, as a developer, control what objects specific component provides. Let's use it in your scenario and provide some of the objects you might be interested in:
#Singleton
#Component(modules = [InMemoryPersistenceModule::class])
interface ApplicationComponent {
val service: Service
val anotherService: AnotherService
}
ApplicationComponent should be understood as a component for your whole application. It's not related to Android's Application class in any way. Now, you can simply create your component and let Dagger instantiate your objects:
val component = DaggerApplicationComponent.create()
val anotherService: AnotherService = component.anotherService
val service: AnotherService = component.service
The Code A is from the project android/architecture-components-samples.
The author place the code of instance a class DefaultServiceLocator in the interface ServiceLocator.
In my mind , normally a interface should not include any implement code.
Is it a good idea to place the code of instance a class in a interface in Kotlin?
Code A
interface ServiceLocator {
companion object {
private val LOCK = Any()
private var instance: ServiceLocator? = null
fun instance(context: Context): ServiceLocator {
synchronized(LOCK) {
if (instance == null) {
instance = DefaultServiceLocator(
app = context.applicationContext as Application,
useInMemoryDb = false)
}
return instance!!
}
}
/**
* Allows tests to replace the default implementations.
*/
#VisibleForTesting
fun swap(locator: ServiceLocator) {
instance = locator
}
}
...
}
open class DefaultServiceLocator(val app: Application, val useInMemoryDb: Boolean) : ServiceLocator {
...
}
In my mind , normally a interface should not include any implement code.
Welcome back from hibernation ;) Yes, you could achieve the same with interface + abstract class but you can have default implementation also as part of the interface for some time now in many languages. Which way you go is up to you, but if you have only one abstract class implementing your interface then it is often handy to be able to merge this into one file for sake of ease of future maintenance.
As per kotlin interfaces documentation:
Interfaces in Kotlin can contain declarations of abstract methods, as well as method implementations. What makes them different from abstract classes is that interfaces cannot store state. They can have properties but these need to be abstract or to provide accessor implementations.
So... there's no problem in using method implementations on the interfaces. That feature might offer you extra power (if you like and need to use it).
I'm a newbie in Kotlin. I want to ask what private constructor in Kotlin for? class DontCreateMe private constructor () { /*...*/ }. I mean what class is supposed to be if we can't create its instance?
Well, the answers in the comments are correct, but since nobody wrote a full answer. I'm going to have a go at it.
Having a private constructor does not necessarily mean that an object cannot be used by external code. It just means that the external code cannot directly use its constructors, so it has to get the instances through an exposed API in the class scope. Since this API is in the class scope, it has access to the private constructor.
The simplest example would be:
class ShyPerson private constructor() {
companion object {
fun goToParty() : ShyPerson {
return ShyPerson()
}
}
}
fun main(args: String) {
// outside code is not directly using the constructor
val person = ShyPerson.goToParty()
// Just so you can see that you have an instance allocated in memory
println(person)
}
The most common use case for this that I've seen is to implement the Singleton pattern, as stated by Mojtaba Haddadi, where the external code can only get access to one instance of the class.
A simple implementation would be:
class Unity private constructor() {
companion object {
private var INSTANCE : Unity? = null
// Note that the reason why I've returned nullable type here is
// because kotlin cannot smart-cast to a non-null type when dealing
// with mutable values (var), because it could have been set to null
// by another thread.
fun instance() : Unity? {
if (INSTANCE == null) {
INSTANCE = Unity()
}
return INSTANCE
}
}
}
fun main(args: Array<String>) {
val instance = Unity.instance()
println(instance)
}
This is often used so that classes that are resource consuming are only instantiated once or so that certain pieces of data are shared by the entire codebase.
Be aware that kotlin uses the object keyword to implement this pattern, with the advantage of being thread-safe. Also some developers consider Singletons to be an anti-pattern
Another use case for private constructors would be to implement Builder patterns, where classes that have complex initialization can be abstracted into a simpler API, so the user doesn't have to deal with clunky constructors. This other answer addresses its uses in kotlin.
One of the simplest uses in real life kotlin code that I've seen is on the Result implementation from the stdlib, where it's being used to change the internal representation of the object.
I have something like:
interface Options {
fun load(conf: JsonObject)
}
object BasicOptions : Options { }
object PersonOptions : Options { }
object CarOptions : Options { }
then I would like to get all Objects that implements Options interface and call load forEach.
fun main(args: Array) {
configFuture.whenComplete { config ->
options.forEach { it.load(config) }
}
}
This is not supported by the language, this is why there are Dependency Injection, Registry, or Service Lookup solutions.
If all objects are registered in a Dependency Injection framework, you may be able to iterate all objects registered to the framework and find the instances of your Interface.
This is likely to be rather inefficient - so cache the results to avoid the extra overhead.
Another approach is to use custom class loader and add this custom functionality. The simplest way is probably using the Reflections library, to scan and load these classes. E.g.:
val reflections = Reflections("my.project.prefix")
val allClasses = reflections.getSubTypesOf(Options::class.java)
The simplest, and most commonly used solution would be simply maintain your own "registry" e.g. a static object holding the list of all instances. It will require manually adding any new class implementing the interface - but it will be simple, performant, and robust solution.
Of course, you can!
Using the Reflections library it's really easy:
First, you need to find all the java classes that implement your interface "Objects". Then you convert the java classes to kotlin classes (KClass).
KClass has the property objectInstance that is null if the class does not have an object instance... otherwise IS the singleton object instance.
So:
val reflections = Reflections(ConfigurationBuilder())
val jList = reflections.getSubTypesOf(Options::class.java)
val kList = jList.map { it.kotlin }
val oList = kList.map { it.objectInstance }.filterNotNull()
;-)
You can always use the Factory pattern for creating new instances of Options, that way you can have your own OptionsFactory and your own caching mechanism.
That OptionsFactory after instantiating an object keeps it in cache (could be in-memory cache or DB..etc), then anytime you can ask the factory for it's cached instances when needed.
This is fairly better when your Options objects are created in run-time/upon demand.
If I am modeling my value objects using Kotlin data classes what is the best way to handle validation. Seems like the init block is the only logical place since it executes after the primary constructor.
data class EmailAddress(val address: String) {
init {
if (address.isEmpty() || !address.matches(Regex("^[a-zA-Z0-9]+#[a-zA-Z0-9]+(.[a-zA-Z]{2,})$"))) {
throw IllegalArgumentException("${address} is not a valid email address")
}
}
}
Using JSR-303 Example
The downside to this is it requires load time weaving
#Configurable
data class EmailAddress(#Email val address: String) {
#Autowired
lateinit var validator: Validator
init {
validator.validate(this)
}
}
It seems unreasonable to me to have object creation validation anywhere else but in the class constructor. This is the place responsible for the creation, so that is the place where the rules which define what is and isn't a valid instance should be. From a maintenance perspective it also makes sense to me as it would be the place where I would look for such rules if I had to guess.
I did make a comment, but I thought I would share my approach to validation instead.
First, I think it is a mistake to perform validation on instantiation. This will make the boundary between deserialization and handing over to your controllers messy. Also, to me, if you are sticking to a clean architecture, validation is part of your core logic, and you should ensure with tests on your core logic that it is happening.
So, to let me tackle this how I wish, I first define my own core validation api. Pure kotlin. No frameworks or libraries. Keep it clean.
interface Validatable {
/**
* #throws [ValidationErrorException]
*/
fun validate()
}
class ValidationErrorException(
val errors: List<ValidationError>
) : Exception() {
/***
* Convenience method for getting a data object from the Exception.
*/
fun toValidationErrors() = ValidationErrors(errors)
}
/**
* Data object to represent the data of an Exception. Convenient for serialization.
*/
data class ValidationErrors(
val errors : List<ValidationError>
)
data class ValidationError(
val path: String,
val message: String
)
Then I have a framework specific implementations. For example a javax.validation.Validation implementation:
open class ValidatableJavax : Validatable {
companion object {
val validator = Validation.buildDefaultValidatorFactory().validator!!
}
override fun validate() {
val violations = validator.validate(this)
val errors = violations.map {
ValidationError(it.propertyPath.toString(), it.message)
}.toMutableList()
if (errors.isNotEmpty()) {
throw ValidationErrorException(errors = errors)
}
}
}
The only problem with this, is that the javax annotations don't play so well with kotlin data objects - but here is an example of a class with validation:
import javax.validation.constraints.Positive
class MyObject(
myNumber: BigDecimal
) : ValidatableJavax() {
#get:Positive(message = "Must be positive")
val myNumber: BigDecimal = myNumber
}
Actually, it looks like that validation is not a responsibility of data classes. data tells for itself — it's used for data storage.
So if you would like to validate data class, it will make perfect sense to set #get: validation on arguments of the constructor and validate outside of data class in class, responsible for construction.
Your second option is not to use data class, just use simple class and implement whole logic in the constructor passing validator there
Also, if you use Spring Framework — you can make this class Bean with prototype scope, but chances are it will be absolutely uncomfortable to work with such kind of spaghetti-code :)
I disagree with your following statement :
Seems like the init block is the only logical place since it executes after the primary constructor.
Validation should not be done at construction time, because sometimes, you need to have intermediate steps before getting a valid object, and it does not work well with Spring MVC for example.
Maybe use a specific interface (like suggested in previous answer) with a method dedicated to executing validation.
For the validation framework, I personnaly use valiktor, as I found it a lot less cumbersome that JSR-303