Home > Enterprise >  What is a right design for a such injection?
What is a right design for a such injection?

Time:12-18

I have two classes of a one interface:

interface TimeUtils { ... }
class TimeUtilsImpl : TimeUtils { ... }
class TimeUtilsSimulation : TimeUtils { ... }

TimeUtils binding is in the module A:

bind(TimeUtils::class.java).to(TimeUtilsImpl::class.java).`in`(Singleton)

TimeUtilsSimulation binding is in the module B:

bind(TimeUtils::class.java).to(TimeUtilsSimulation::class.java).`in`(Singleton)

and these modules A and B are used in different binaries.

I injected TimeUtils in a common code like:

class SomeClass @Inject constructor(
  private val timeUtils: TimeUtils
)

And now I have a problem that when I have a request to start simulation I need to set an initial time in the TimeUtilsSimulation object. I can do it like this:

class RequestHandler @Inject constructor(
  private val someObject: SomeClass
)
onRequest(simulationStartTime: LocalDateTime) {
   if (timeUtils instanceof TimeUtilsSimulation) {
       // Set start time in a singleton timeUtils object
       (timeUtils as TimeUtilsSimulation).setStartTime(simulationStartTime)
   }
   someObject.run()
}

but it looks ugly. Can you suggest something to solve this bad design?

CodePudding user response:

Maybe add setStartTime to TimeUtils interface and do not implement it in TimeUtilsImpl? It all depends on the context. For unit testing for example I think your solution would be fine. But for other, "normal" business logic is seems fishy. It's almost like the interface does not really abstract the concept properly

CodePudding user response:

I don't know Kotlin, but pure OOP speaking, the best would be to define a TimeUtilsWrapper interface that extends TimeUtils and adds setStartTime(...) method. Then you would have 2 classes implementing this interface:

  • 1 that embeds a TimeUtils object with empty setStartTime() that delegates all other methods to the embedded object,
  • second that embeds a TimeUtilsSimulation and delegates all methods to it, including setStartTime() calls to it.

Then SomeClass method should have a property of type TimeUtilsWrapper instead of TimeUtils and onRequest(...) should just always call TimeUtilsWrapper's setStartTime(...).

  • Related