I'm developing an application (Java) in a modular architecture. I have two approaches in mind and I'm not sure which one will be "better code" in case of maintenance and conventions.

I have two main modules that I want to wire them up:

  1. CORE - backend stuff
  2. UI - frontend stuff

I can think of two approaches:

  • APPROACH 1: CORE module will expose Engine class, UI will expose UserInterface class. UserInterface will need an Engine in its constructor. Creation of both objects will take place in the third module called LAUNCHER.

  • APPROACH 2: CORE module will expose Engine class, UI will expose UserInterface class. The difference is both modules with expose those classes ONLY to PRELAUNCHER module that will create objects and pass them to the LAUNCHER module as interfaces.

The second approach looks promising, because it won't allow any module create the instantion of UI/CORE module classes (as Java offers sealed interface - that means I can choose which class can implement it). That's kind of dependency injection - the needed items will be created in one place and passed as interfaces.

On the other hand - the approach introduces more code - one more module and at least two new interfaces.

Any ideas which one is better in terms of maintenance and conventions?

  • 2
    Have you considered a standard dependency injection framework? How are the unit tests going to instantiate these things?
    – pjc50
    Feb 24, 2022 at 14:37
  • What is the advantage of not being able to create new engines and new user interfaces?
    – user253751
    Mar 23, 2022 at 13:28

2 Answers 2


Going by the names you assigned to your classes it does not seem the engine depends on the UI in any way. If the dependency is indeed one way (UI uses engine) there is no point in abstracting away the UI for any client to address it through a interface. You may be better of by just having the UI instantiate the engine and by focusing on making the engine's interface useful to the UI.


Modularisation aims to decompose a software into replaceable and reusable components that are based on well-defined interfaces.

Approach 1 partially achieves this objective : UserInterface depends on a Engine via an implicit interface that encapsulates its implementation details. You could therefore replace the implementation of Engine with another implementation or even a subclass of it. But you are cannot reuse UserInterface independently of Engine.

Approach 2 completely achieves the objectives of the modularization: according to your explanations UserInterface no longer depends on Engine but on an interface that abstracts away the engine and could easily be replaces with other implementations.

The use of a prelauncher and a launcher to further fine-tune accessibility control would of course enforce the proper use of the interface. But it might be an overkill in your case:

  • Instead, you may consider to just modularize the interface, i.e having an EngineInterface defined independently of the Engine, and that could safely be consumed by the UserInterface and the Launcher. This would be simpler. The launcher could still do the wiring as above since its goal is to make the glue between your modules and not be independent.
  • Adding an EngineFactory to the interfaces could make sense if engines are constructed in a lot of places but seem not absolutely required in your context.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.