I started developing my own dependency injection package in dart just for fun. The problem I came across is that when a class is in it's own file and is not imported anywhere, dart's tree shaking will remove it and make it inaccessible. This makes it impossible for me to map implementation of some interface to the interface so I cannot ask context to give me implementation when I supply the interface. Here is what I mean:
import 'context/context.dart';
void main() {
Context context = Context();
Interface interface = context.getInstance<Interface>();
interface.works();
}
abstract class Interface {
void works();
}
And here is the implementation of the "Interface" abstract class:
#Singleton()
class Implementation implements Interface {
#override
void works() {
print('works');
}
}
If I import the file that contains the "Implementation" class, context is able to find it and map it but I want to avoid doing that. Is there any way to turn off the tree shaking or preserve the class without importing it ?
Related
I am bit new to golang and I have a question about packages and interfaces.
If I have package1, that needs to use implementation of an interface that can be swapped in future with other implementation, would that be possible?
some pseudo code
package implementation contains current implementation of interface
type TestI interface {
M1()
}
package implementation
type Impl struct {}
funct (i *Impl) M1 ( ... do something )
package package1
import TestI somehow and call M1 method but with flexibility to swap it with other implementation of this interface in future?
package package1 should use implementation without knowing about it (something like DI in c# or java, package should only know about interface, and not about implementation)
Where should TestI interface be defined? Sorry if this is a bit confusing, just trying to get my head around it.
This is equivalent in c#
ITest {
SetClass(Class1 cl);
}
// package1
class Class1 {
private ITest test {get; set;}
public void SomeMethod() {
// i want to somehow set this in other package
test.SetClass(this);
}
}
// package2
class Test implements ITest {
private Class1 cl;
SetClass(Class1 c) {
this.c1 = c;
}
}
Unless you are writing an interface-first application, it is generally best to write the concrete implementations without declaring any interfaces. Then the users of that package can declare the necessary interfaces. For example:
type Implementation struct {
...
}
func (i Implementation) FuncA() {...}
func (i Implementation) FuncB() {...}
If some type that implements FuncA is required, you can declare:
type IntfA interface {
FuncA()
}
Any type that has the method FuncA implements IntfA, and Implementation fits that description, so you can pass an instance of Implementation to a function that needs IntfA.
Similarly, if you need an interface that has both FuncA and FuncB, you can declaret:
type IntfAB interface {
FuncA()
FuncB()
}
and Implementation also implements IntfAB.
So, ideally, you would declare the interface you need where you use it, and any type with a matching set of methods can be used for the implementation of that interface.
If you are writing based on an existing interface, then you can put that interface in a separate package than the implementation, or you can keep the interface and the implementation in the same package, whichever makes more sense for your use case.
If there are more than one implementation of an interface, then I would have to use #Qualifier to indicate which class I want to autowire with. Wouldn't it make more sense to autowire the class directly instead of interface?
This is what object oriented programming (especially abstraction and polymorphism) is about.
You build the classes independendent of concrete implementations and use an interface.
This allows you to change what implementation you use at any point.
Assume you have this:
public interface I{
void doSomething();
}
#Component("a")
public class A implements I{
public void doSomething(){
//...
}
public void doSomethingElse(){
//...
}
}
#Component("b")
public class B implements I{
public void doSomething(){
//...
}
}
If you use
#Autowired
private A yourVariable;
you might be tempted to use the doSomethingElse() method that is an implementation detail (by what reason whatsoever).
However, if you use
#Qualifier("a")
private I yourVariable;
this cannot happen as the method is not present in the interface.
This gives you the ability to swap the implementation at any time.
Wouldn't it make more sense to autowire the class directly instead of interface?
This pretty much depends on how exactly do you work with qualifiers but in general, the answer is "No", autowiring the class is a bad thing to do if you have an interface - you should always work by interface.
Here are the examples:
interface I { void foo(); }
class IImpl1 implements I {
void foo() {System.out.println("Impl1");
pubic void bar() {// another method - why not?}
}
class IImpl2 implements I { void foo() {System.out.println("Impl2"); }
Note, that an implementation IImpl1 has an additional method bar that doesn't belong to the interface I
Case 1:
#Component
public class Driver {
#Autowired
private IImpl1 i;
}
Here class Driver is tightly could to the concrete implementation IImpl1 in general I can call method bar from the Driver class because I have this implementation, but in this case if I'll have to switch the implementation of Driver in future you'll have to also change the code: both change the reference, and also get rid of calls to IImpl1.bar() that might be not that easy to do - its a change in logic. As a result, the whole polymorphic behavior is lost.
By far its the worst way to program.
Now, consider Case 2:
#Component
public class Driver {
#Autowired
#Qualifier("someLogicalName") // under the hood it spring will map it to IImpl1 but you don't know that here
I i;
}
In this case - the things are much better - you never couple the driver to the concrete implementation at the level of code. This means that in general its enough to change the qualifier to get another implementation. You can't call bar anymore - it won't compile.
You also do not know what the implementation will be injected. If in future the implementation of the component that actually implements the logic of "someLogicalName" will change (by that I mean that you'll create a new class IImpl3), you won't feel it here - you'll place that qualifier on that new class and all the places that use it will get that implementation automatically.
Case 3:
#Configuration
public class MyConfiguration {
#Bean
public Driver driver(#Qualifier("someLogicalName") I i) {
return new Driver(i);
}
}
public class Driver {
private final I i;
public Driver(I i) { // in real life this constructor can be generated by
// lombok or something, put it here for the sake of completeness
this.i = i;
}
}
This by far the most "clean" approach - conceptually its really similar to case 2, however in this case you don't place the qualifier at the level of Driver class at all, in fact, the class Driver is not even aware at the level of code / metadata that its related to Spring anyhow. Of course all the "advantages" of case 2 are also applicable here as well.
I have faced a well-known scenarios whereby I really need to move a number of utilities private functions (that should not have been there in the first place) from my Service class to a utility class. My question is around using service methods in a utility class. I have attempted at the following refactoring:
class Utils(
val serviceIneed : ServiceIneed) {
companion object {
private val someMapper = ObjectMapperConfig.mapper
}
fun someUtility(): ResponseEntity<Any> {
// lots of stuff
return serviceIneed.someFunction()
}
}
Then this is the other service where I need to use the method I have moved to the newly created utility class:
class anotherService(
private val serviceIneed: ServiceIneed
) {
fun someMethod() {
// lots of things happening
val utilityUsage = Utils(serviceIneed).someUtility()
}
}
Is this the correct way to go about this? Can you recommend any approach on refactoring service classes in a way that only service-oriented methods and not helper ones remain in my Service class?
Thank you
I am trying to close some test holes in my application and found that JaCoCo sonar plugin is giving me a smaller coverage in my enums because it thinks I should test the Package names.
Why is that?
It's showing me a 97% coverage in one of my enums and displaying a red line on top of the package declaration like this, telling me to test it... it does that in all Enums and on Enums only.
I came here looking for the answer to this, and after some more digging I discovered that it's due to some static methods that can be found in the bytecode of the compiled enum class which Jacoco is expecting to be covered. After some experimentation, I came up with the following superclass to use for unit tests which are focused on enums, with JUnit 4. This resolved my coverage problems with enums.
import org.junit.Test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static org.junit.Assert.assertEquals;
public abstract class EnumTest {
#Test
public void verifyEnumStatics() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class e = getEnumUnderTest();
Method valuesMethod = e.getMethod("values");
Object[] values = (Object[]) valuesMethod.invoke(null);
Method valueOfMethod = e.getMethod("valueOf", String.class);
assertEquals(values[0], valueOfMethod.invoke(null, ((Enum)values[0]).name()));
}
protected abstract Class getEnumUnderTest();
}
And then use it like this:
public class TravelTypeTest extends EnumTest {
#Override
protected Class getEnumUnderTest() {
return TravelType.class;
}
// other test methods if needed
}
This is a rough first attempt - it doesn't work on enums that for whatever reason don't have any entries, and doubtless there are better ways to get the same effect, but this will exercise the generated static methods by ensuring that you can retrieve the values of the enum, and that if you pass the name of the first enum entry to the valueOf() method you will get the first enum entry back.
Ideally we'd write a test that searches for all enums in the packages under test and exercise them in the same way automatically (and avoid having to remember to create a new test class for each new enum that inherits from EnumTest), but I don't have many enums so I haven't felt any pressure to attempt this yet.
Update: Is there a way to achieve what I'm trying to do in an IoC framework other than Windsor? Windsor will handle the controllers fine but won't resolve anything else. I'm sure it's my fault but I'm following the tutorial verbatim and objects are not resolving with ctor injection, they are still null despite doing the registers and resolves. I've since scrapped my DI code and have manual injection for now because the project is time sensitive. Hoping to get DI worked out before deadline.
I have a solution that has multiple classes that all implement the same interface
As a simple example, the Interface
public interface IMyInterface {
string GetString();
int GetInt();
...
}
The concrete classes
public class MyClassOne : IMyInterface {
public string GetString() {
....
}
public int GetInt() {
....
}
}
public class MyClassTwo : IMyInterface {
public string GetString() {
....
}
public int GetInt() {
....
}
}
Now these classes will be injected where needed into layers above them like:
public class HomeController {
private readonly IMyInterface myInterface;
public HomeController() {}
public HomeController(IMyInterface _myInterface) {
myInterface = _myInterface
}
...
}
public class OtherController {
private readonly IMyInterface myInterface;
public OtherController() {}
public OtherController(IMyInterface _myInterface) {
myInterface = _myInterface
}
...
}
Both controllers are getting injected with the same interface.
When it comes to resolving these interfaces with the proper concrete class in my IoC, how do I differentiate that HomeController needs an instance of MyClassOne and OtherController needs an instance of MyClassTwo?
How do I bind two different concrete classes to the same interface in the IoC? I don't want to create 2 different interfaces as that breaks the DRY rule and doesn't make sense anyway.
In Castle Windsor I would have 2 lines like this:
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>());
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>());
This won't work because I will only ever get a copy of MyClassTwo because it's the last one registered for the interface.
Like I said, I don't get how I can do it without creating specific interfaces for each concrete, doing that breaks not only DRY rules but basic OOP as well. How do I achieve this?
Update based on Mark Polsen's answer
Here is my current IoC, where would the .Resolve statements go? I don' see anything in the Windsor docs
public class Dependency : IDependency {
private readonly WindsorContainer container = new WindsorContainer();
private IDependency() {
}
public IDependency AddWeb() {
...
container.Register(Component.For<IListItemRepository>().ImplementedBy<ProgramTypeRepository>().Named("ProgramTypeList"));
container.Register(Component.For<IListItemRepository>().ImplementedBy<IndexTypeRepository>().Named("IndexTypeList"));
return this;
}
public static IDependency Start() {
return new IDependency();
}
}
I hope you can use service overrides.
Ex.
container.Register(
Component.For<IMyService>()
.ImplementedBy<MyServiceImpl>()
.Named("myservice.default"),
Component.For<IMyService>()
.ImplementedBy<OtherServiceImpl>()
.Named("myservice.alternative"),
Component.For<ProductController>()
.ServiceOverrides(ServiceOverride.ForKey("myService").Eq("myservice.alternative"))
);
public class ProductController
{
// Will get a OtherServiceImpl for myService.
// MyServiceImpl would be given without the service override.
public ProductController(IMyService myService)
{
}
}
You should be able to accomplish it with named component registration.
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>().Named("One"));
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>().Named("Two"));
and then resolve them with
kernel.Resolve<IMyInterface>("One");
or
kernel.Resolve<IMyInterface>("Two");
See: To specify a name for the component
Typically DI containers follow Register, Resolve and Release patterns. During the register phase there are two steps. The first is to specify the mapping as you are doing. The second step is to specify the rules which govern which to inject where.
This problem is very common when we try to address Cross cutting concerns using decorators. In these situations, you have multiple classes(decorators) implementing a single interface.
Briefly, we need to implement IModelInterceptorsSelector which allows you to write imperative code that decides which Interceptor to apply to which types or members.
This is elaborately described in the book Dependency Injection in .Net book by Mark Seemann. Look for chapter 9 interception or search for the above interface.
I am not an expert at this, but was searching for the exact same problem and found the ans in the above book.
Hope this helps.
Regards
Dev1