I'm new to Scala and I'm trying to figure out the best approach for dependency injection. I have Java background and I used to use both Guice and Spring IoC.
I used to use a provider class with the #Provider annotation to chose implementation or use beans.xml in Spring and just use the #Inject annotation (or in Spring, #Autowired) to inject instances of a class into my services.
In Scala, I read about the cake pattern but it seems rather complicated to me. All I want to achieve is what I already have in Java: get a singleton of an interface type with specific implementation.
My question is whether using Scala object type would be sufficient.
Example:
trait TestDI { }
class Impl1 extends TestDI { }
class Impl2 extends TestDI { }
object TestDI extends Impl1 { }
So I'd just use TestDI in my service which would actually use the implementation of Impl1. So my initial interface (trait) and the singleton object would have the same name.
I think either Macwire or Scaldi matches Guice style quite closely. I like Macwire because it's standard Scala based framework based on macros, no other magical sauce is used (like byte manipulation).
Other ways to do DI are described in my answer here:
Scala - write unit tests for objects/singletons that extends a trait/class with DB connection
Related
When should I use an abstract class vs a regular class? More specifically, I'm trying to understand when constructor parameters should be preferred over abstract members.
For example:
sealed trait Client
abstract class BaseService {
def client: Client
}
class Service extends BaseService {
val client = ???
}
vs
sealed trait Client
class BaseService(client: Client) {}
class Service extends BaseService(client = ???)
As far as I can tell, both are valid.
As #Luis Miguel said, use abstract classes when you want to declare a common set of methods that need to be implemented by the sub-classes and/or share some limited functionality that will be used by all child classes.
Below, I'm listing some reasons why I considered you should pass your dependencies to the constructor rather than defining them in your classes/base-classes.
Use dependency injection
(IMHO) It is better to give the constructor the dependencies it needs to function properly AKA dependency injection.
Avoid tight coupling
When you declare a dependency inside your class or in your constructor, you are tightly coupling your Service with that specific implementation of the dependency, which is not ideal and is considered an antipattern.
Program to interfaces, not implementations
Injecting the dependencies gives you greater flexibility as you are not coupled to a specific implementation. This is true as long as your code relies on an interface/trait/abstract-class (consequently avoiding tight coupling).
When your class relies on an interface/trait/abstract-class can be very powerful as you can be passing a mock, a no-op, or different strategies of the client. So make sure you "Program to interfaces, not implementations".
I'm looking for a way to generate a class from a trait with all the methods implemented (throwing NotImplementedErrors). Having such class in place, I would be able to sub-class it to provide implementations for the methods I do need.
I consider this approach as a replacement for a mocking framework.
How to do that in scala-meta or scala-reflect?
Play Framework 2.4 has support for Google Guice Dependency Injection
What is the advantage of using
#Singleton class A
instead of
object A
for singletons?
I can see three advantages of using #Singleton class over object if A has no dependencies:
If you wanted to test A, and declare it as #Singleton class you have the option of subclassing it to mock out some of the functions in your test, whereas this is not possible with an object.
If you use object, it is very tempting for clients of A to reference it directly, leading to a strongly coupled system, but using #Singleton class forces them to think about where A is instantiated, probably leading to a more decoupled design.
If you later change your mind, and allow multiple instances of A, the refactoring will be much easier to do if you chose to use #Singleton class.
If A has dependencies, however, using #Singleton class allows them to be dependency injected on construction, whereas with an object this is only possible if you declare the dependencies as mutable (eg: a var with getter/setter methods) .
object PostgresDriver extends PostgresDriver
I see this in slick with no implementation whatsoever. I am wonder does that just automatically create a singleton class?
This is pretty standard practice, defining a trait to represent the abstraction and then providing a standard implementation of that trait as an object. If you just do it as the object you don't have an abstraction to refer to it as and stuff like that can make mocking and testing difficult at the least
To define a CDI stereotype, i would need to define a runtime annotation.
In scala, i tried this:
#Stereotype
#Target(Array(ElementType.METHOD))
#Retention(RetentionPolicy.RUNTIME)
//... my stereotype annotations
class MyStereotype extends ClassfileAnnotation{}
But found this problem:
Implementation restriction: subclassing Classfile does not make your
annotation visible at runtime. If that is what you want, you must
write the annotation class in Java.
Is it possible, using scala 2.9.1, to define runtime annotations?
This is purely a Scala issue where runtime renentive annotations must be done in Java. So CDI (as well as other stereotypes) should be done in Java.