0

I'm working on multi SBT project in Scala. I extracted core things into separate SBT project. This includes handling config, third party libraries (init RMQ client, init Redis client etc) and some models.

So I organised some things like loading config in trait and I then mix this trait where I need it and just use config method defined in Configuration trait, which loads config for specific environment (based on environment variable). I did same for database, so I load PostgreSQL, open connection and then mix that trait where I need it and just use database method which I can use for executing queries and other.

Is this good approach in you opinion? Advantage is that I do not have to handle database connection and initialisations in each project and also code is much shorter. However, there is one issue with closing connection. Where to close connection in trait where Database is mixed?

Any help on the topic is appreciated. Thanks

Amer

1 Answer 1

1

Regarding connections, you should be closing them (returning to pool) whenever you are done with them, that is orthogonal to mix-in implementation.

As for configuration and such, I like this approach, but the problem with it is that most of the time you want things like loaded config to be singletons, but if you simply do something like

 trait Configuration { val config = loadConfig } class Foo with Configuration class Bar with Configuration val f1 = new Foo val f2 = new Foo val b1 = new Bar val b2 = new Bar 

then, you'll end up loading four different copies of the config. One way around this is to delegate loadConfig to a singleton object:

 object Configuration { val config = loadConfig } trait Configuration { def config = Configration.config } 

This works, but makes it much harder to unit-test and override the functionality (what if I want my config loaded from a database sometimes?)

Another possibility is a proxy class:

trait Configuration { def loadConfig: Config lazy val config: Config = loadConfig } class ConfigurationProxy(cfg: Configuration) extends Configuration { def loadConfig = cfg.config } object Main extends App with Configuration { def loadConfig = ??? // executed only one per application ... } class Foo extends ConfigurationProxy(Main) class Bar extends ConfigurationProxy(Main) val f1 = new Foo val f2 = new Foo val b1 = new Bar val b2 = new Bar 

Now, all four variables are looking at the same Config instance. But if you have a function somewhere that wants a Configuration, you can still pass any of these in:

def connectToDB(cfg: Configuration) = ??? connectToDB(Main) connectToDB(f1) connectToDB(b2) 

etc.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.