Splitting into multiple modules

It is generally a good practice to split your project into multiple modules. A well organized project is easier to understand. The complexity of the project is broken down into separate parts, each of those parts can be studied individually. Separation also helps to reduce incremental compilation times.

We will now transform our one-module project into project with multiple modules. We will follow a pretty standard separation into Util, DAO, Services and Web modules. One extra module will be macros, because we want to ensure, that they always reside in a separate compilation unit. Here is, how we want our project to look like, once it is imported to IntelliJ:

Multi module build.sbt

Let’s take a look at the build.sbt file, one section at a time:

We start with defining some common settings. They will be reused in all modules.

Next, we define a root aggregator project. The concept is similar to Maven’s aggregator POM. This module is not really necessary for running the application. However, it comes handy, when we want to execute the same command for all modules, e.g. clean or test

Web module has been moved to a subdirectory. Sources are now located in modules/scalactica2d-web/app and modules/scalactica2d-web/conf. It depends on another sub-module: scalactica2dServices. It is also the only module with PlayScala plugin enabled.

Services, DAO, Util and Macros modules have a standard location of sources in src/main/scala directories.

Note, that sbt command run does not work anymore. There is no runnable class in the aggregator module. Instead, we will start PlayFramework server by running scalactica2dWeb/run. It is possible to create and alias in build.sbt:

Thin cake pattern

Now, we just need to wire everything together. For that, we will use the thin cake pattern. Let’s start from bottom up.

First of all, Macros and Util module do not expose any beans. Both contain Scala singletons (object) or classes, that do not have state and no dependencies. A friend of mine once argued, that Util classes should be included to dependency injection too, just so that we use the same approach the same in whole project. It’s up to you, how you will decide on this.

DAO module components trait contains two beans, both implementing the same interface. It also declares a dependency on a DataSource.

Services module components contains only one bean and one dependency:

Web module components contain router and controllers.

And finally, we mix in all components together. This is also the place, where we provide top level configuration of the whole application. In this example, we set up the datasource from configuration properties. We also choose which implementation of PlanetDAO will be used. And we also choose, which filters will be used, while processing HTTP requests (none in this case.

Next, we will have the DAO class access a real database, but before that, you might want to check my thoughts on database access patterns

Leave a Reply

Your email address will not be published. Required fields are marked *