Is it possible to have the view implementation hidden in a Scala application?

72 views Asked by At

My goal is to have an MVC pattern in a simulation application where the controller knows there is a view (and interacts with it using an interface) but doesn't know how it is implemented:

object Controller extends App {
  View.initView()
  ...
}

object View {
  stage: Stage = ...
  
  def initView: Unit = {
    ...
  }
}

However I only managed to do so having the entry point of the program to extend scalafx.application.JFXApp, javafx.application.Application (example below) or swing.SimpleSwingApplication which forces the controller to know how the view is implemented. Is there any simple workaround?

def main(args: Array[String]): Unit = {
  Application.launch(classOf[SimulatorApp])
}

class SimulatorApp extends Application {
  override def start(stage: Stage): Unit = {
    View.initView(stage)
  }
}
1

There are 1 answers

1
Mateusz Kubuszok On BEST ANSWER

Well, you can design your application as abstract e.g.

class MyApplication(dependency1: Dependency1, dependency2: Dependency2)
  extends Application {

  // code using things
}

and then pass implementations somewhere else

class MyApplicationImplemented 
  extends MyApplication(implementation1, implentation2)

Application.launch(classOf[MyApplicationImplemented])

where dependencies could be:

  • instances
  • recipes for instances (functions)
  • configs

etc.

You can also make some methods abstract and implement them in some top level.

In general you treat your final Application implementation as class with main method - this is not an object you pass dependencies into but a place where you finally wire them together. So in the end you have to design it to be your main. (launch methods' signatures confirm that this is the intent).

That said a lot of logic can be extracted into traits or abstract classes or components so that you could have some general logic somewhere else, have it rely on dependency injection, create several implementations, and wire them in separate "mains" for e.g. production code and end-to-end tests.