Should I inject an interface or its implementation ?
I came across the below code in a tutorial and I am wondering why inject the interface but register it as its implementation when you can just directly inject its implementation?
SIGNINBLOC
#injectable
class SignInBloc extends Bloc<SignInEvent, SignInState> {
final IAuthFacade _authFacade;
SignInBloc(this._authFacade) : super(SignInState.initial());
FIREBASEAUTH
#LazySingleton(as: IAuthFacade)
class FirebaseAuthFacade implements IAuthFacade {
INJECTION CONFIG
gh.lazySingleton<IAuthFacade>(
() => FirebaseAuthFacade(get<FirebaseAuth>(), get<GoogleSignIn>()));
You want to separate the implementation details and dependency to a specific implementation. It will be easier to switch between different implementations and also easier to mock the interface when testing.
You can for example configure GetIt to use different implementations for the interface depending on if it is e.g. development environment, production environment, test environment etc.. You only have to change one line and it will change everywhere.
Related
I am trying to use the in built methods of MongoRepository<T,ID> interface to interact with mongo.
interface MovieRepository : MongoRepository<Movie, String> {
}
But when I try to implement the "MovieRepository" using class. Its asking me to implement all the member functions defined in "MongoRepository" as well
class ControllerClass(private val MovieRepository: MovieRepository): MovieRepository {}
This is what i get when i initialize my controller class:
Class 'ControllerClass' is not abstract and does not implement abstract member public abstract fun <S : Movie!> save(entity: S): S
Is there any way so that i do not need to defined all those MongoRepository's functions again in my ControllerClass?
You don't usually implement a repository interface yourself: you let Spring do it for you!
First, you define your interface, as you have done:
interface MovieRepository : MongoRepository<Movie, String> {
// Add any abstract methods you'll need here…
}
Then, you autowire a property of that type. In Kotlin, you can either do it in the primary constructor, e.g.:
#Controller
class ControllerClass #Autowired constructor(
private val movieRepository: MovieRepository
) {
// …code…
}
Or as a plain property. (In this case, because you can't specify an initial value, you have to make the property a var; it must either be nullable — requiring !! everywhere you use it — or, better, make it lateinit.)
#Controller
class ControllerClass {
#Autowired private lateinit var movieRepository: MovieRepository
// …code…
}
Spring will then create some synthetic class implementing that interface, and set your property to it. (You don't need to worry about how it does that — just as you don't need to worry about all the other magic it does, much of which involves creating synthetic subclasses. That's why Spring objects generally need to be made open — and why there's a Spring plugin which takes care of doing that.)
It's more usual to use the repository in a service class, and then call that from your controller class — at least, that pattern tends to scale better, and be easier to follow and to test. But doing so directly should work too. Either way, you can call whichever repository method you need, e.g. movieRepository.findAll().
See the Spring docs; they use Java, but it's mostly trivial to convert to Kotlin.
I am trying to understand the best practices in Dart and I saw in couple of instances that people declare singletons without the getit package and also the factory declarations are also a bit confusing for me. So let's assume I have these two classes below:
class Singleton {
static final Singleton _singleton = Singleton._internal();
factory Singleton() {
return _singleton;
}
Singleton._internal();
}
class RegularClass {
RegularClass();
}
I have two questions here:
What is the difference between
Singleton() and GetIt.I.registerSingleton<RegularClass>(() => RegularClass());
What is the difference between RegularClass() and GetIt.I.registerFactory<RegularClass>(() => RegularClass());
If these cases don't really matter, then what cases matter? What are the different use cases for these?
There is no real difference.
But as your app grows, using getIt (especially together with e.g. injectable) will make your app a lot easier to work with and save you a lot of time.
Edit (in response to requested elaboration):
As an example. Consider having a class setup as below, that use an API which you have setup as an interface (abstract class)
#Injectable
class MyClass {
MyClass(this.myApi);
final IApi myApi;
...
}
#LazySingleton(as: IApi)
class MyApi implements IApi {
...
}
You will then be able to let getIt and injectable solve these dependencies, factories and singletons where needed and appropriate, so that when you want to use e.g. MyClass, you don't have to consider what needs to be injected where, and what type of parameters that needs to be injected where.. All you have to call is:
final instaceOfMyClass = getIt<MyClass>();
And on top of this, if you want to have e.g. a Mock implementation of IApi, or a separate implementation for production and some test environment, you can define that with the annotations, so that your entire setup is handled based on one single input parameter when you launch your app. So, instead of what I wrote above for the singleton, you could as an example do two separate implementations of the API, and let getIt solve everything for you based on your environment. Meaning you can still just call getIt<MyClass>() to get MyClass, but your instance of IApi will differ based on your setup:
#LazySingleton(as: IApi, env: ['dev'])
class MyTestEnviromentApi implements IApi { ... }
#LazySingleton(as: IApi, env: ['prod'])
class MyProductionEnvironementApi implements IApi { ... }
I am trying to understand how mocking works with dart and mockito.
Image I have the below declarations:
void foo(){}
and similarly a class
class BarClass {
void bar(){}
}
and then my widget accesses the first one directly as foo(); and the second one as BarClass().
What would be the way to mock these two? Should I be accessing them through something like getit to mock them properly or is there actually a way?
You can easily mock classes by creating a new class that implements the functionality of your old one using the mockito package
example code:
class MockBarClass extends Mock implements BarClass {}
you can mock methods of your BarClass in the following way:
final mock = MockBarClass();
when(() => mock.boo()).thenAnswer((_) {
// your mocked response
print("hello world");
});
you can mock functions that are in no classes the same way:
when(boo()).thenReturn();
source by Remi Rousselet
additional information if you ask yourself what's the difference between .thenReturn(...) and .thenAnswer((){...}):
I recommend reading this explanation: https://stackoverflow.com/a/36627077/12165405 (even though it's for java, the same applies for that flutter package)
I see the Plugin class is now deprecated (as of 2.4.x version of play)... In the api documentation it says I should use modules instead... so that's my question.
How do I write a module, and how do I plug that module into the play lifecycle of the main app?
You don't specify which language you're using, so I'll quickly cover both. I'm basing both answers on the following repositories:
https://github.com/schaloner/deadbolt-2-java
https://github.com/schaloner/deadbolt-2-scala
Java
Write your functionality any way you want - there are no specific classes to extend. If you have dependencies on Play components such as Configuration, you should inject them.
#Singleton
public class MyModuleCode {
private final boolean enableWidgets;
#javax.inject.Inject
public MyModuleCode(final Configuration configuration) {
this.enableWidgets = configuration.getBoolean("widgets.enabled", false);
}
}
Note that dependency injection is used in place of static reference. Also, note that I've given this example a #Singleton annotation, but it's also possible to have, for example, per-request scope.
See the Play DI docs for more information
Expose the components of your module. To do this, extend the play.api.inject.Module class and implement public Seq<Binding<?>> bindings(final Environment environment, final Configuration configuration).
package com.example.module;
public class MyModule extends Module
{
#Override
public Seq<Binding<?>> bindings(final Environment environment,
final Configuration configuration)
{
return seq(bind(MyModuleCode.class).toSelf().in(Singleton.class));
}
}
Here, you can also bind implementations to interfaces, configure instance providers and so on.
If it's something you're publicly releasing the module, let's assume you do this here - it's out of scope of the question. Let's also assume you've added a dependency for the module in whichever project you're working on.
Enable the module in application.conf.
play {
modules {
enabled += com.example.module.MyModule
}
}
The components exposed via your module - just MyModuleCode in this example - is now available for injection into your controllers, actions, etc.
If you need a shutdown hook, just inject ApplicationLifecycle into the component and register the hook; see https://playframework.com/documentation/2.4.x/JavaDependencyInjection#Stopping/cleaning-up for details.
Scala
Write your functionality any way you want - there are no specific classes to extend. If you have dependencies on Play components such as CacheApi, you should inject them.
#Singleton
class DefaultPatternCache #Inject() (cache: CacheApi) extends PatternCache {
override def apply(value: String): Option[Pattern] = cache.getOrElse[Option[Pattern]](key = s"Deadbolt.pattern.$value") { Some(Pattern.compile(value)) }
}
Note that dependency injection is used in place of static reference. Also, note that I've given this example a #Singleton annotation, but it's also possible to have, for example, per-request scope.
See the Play DI docs for more information
Expose the components of your module. To do this, extend the play.api.inject.Module class and implement def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]].
package com.example.module
import com.example.module.cache.{DefaultPatternCache, PatternCache}
import play.api.inject.{Binding, Module}
import play.api.{Configuration, Environment}
class MyModule extends Module {
override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = Seq(bind[PatternCache].to[DefaultPatternCache])
}
Here, you can also bind implementations to traits, configure instance providers and so on.
If it's something you're publicly releasing the module, let's assume you do this here - it's out of scope of the question. Let's also assume you've added a dependency for the module in whichever project you're working on.
Enable the module in application.conf.
play {
modules {
enabled += com.example.module.MyModule
}
}
The components exposed via your module - just MyModuleCode in this example - is now available for injection into your controllers, actions, etc.
If you need a shutdown hook, just inject ApplicationLifecycle into the component and register the hook; see https://playframework.com/documentation/2.4.x/ScalaDependencyInjection#Stopping/cleaning-up for details.
Summary
Modules are no longer anything special - they're just a way of grouping injectable components.
I am currently using guice with play, so in my controllers I inject a service like:
class UserController #Inject()(userService: UserService) ....
And my service looks like:
class UserServiceImpl #Inject(userDao: UserDao) extends UserService {
}
My UserDao uses slick for database access.
My question is, if I didn't want to use slick, exactly how could I write up my dependencies?
Currently my UserService is a singleton.
Can someone show me how I could wire things up without using DI? I know someone is going to say 'use the cake pattern' but pratically can someone show how to do this from within the playframework?