How to use an Ultra Thin Web UI with Play Framework

Many times I've seen fat UI layers and waded through molasses of unreadable business logic. Why are UI layers growing fat so fast? Because for most developers it seems to be the easiest thing to stuff code and logic into the web layer - I've done that too! No need to create new classes, no need to think, no need for architecture. This leads to bugs, cut & paste code all over the place and makes it really hard to understand what's going on. The worst I've seen is lots of programming language code in templates, but nearly as bad are fat controller classes.

Josh Symands writes in "Rails Worst Practices: 13 Coding Nightmares You Should Avoid" about chubby controllers:

There should be no business logic in a controller.

Read that again.

There should be no business logic in a controller.

Controllers do two things: they take data from the params or session and send it to the model. The MODEL performs all the necessary logic. Then, the controller does the other thing that's completely necessary: it decides what should be shown to the user. That's it. The sum total of a controller action is two steps long.

Send information to the model.
Decide what to display.
If you are doing ANYTHING ELSE in your action, you are doing it in the wrong place. The end.

Wherever I've seen a fat UI layer, I go on a crusade to thin the web layer. This is often hard and thorny, because it needs a lot of time to clean your UI layer. Why? Because a thin layer has

  1. better and easier unit testing
  2. more and better reuse
  3. and you will need to change your web framework in the future, which is usually not possible with a fat UI layer. Then you're screwed.

I've dabbled with ultra thin UI layers before, with the Editor/View pattern to easily support Swing/SWT frontends for the same code. And I came back to the topic recently when diving deeper into Domain Driven Design. As Eric Evans writes in his Domain Driven Design book, don't put logic in your UI layer if your following DDD (he says it might be ok to go with a "Smart-UI" and not do DDD, but then you need to adjust your development effort accordingly).

A way to keep your web layer thin is to introduce use case classes. Those do one thing and are application specific. They are not part of your domain layer, but use esxtensivly services and repositories from your domain layer.

A controller method in Play could look like this:

def newUser(templateId: String): Unit = {
    val user = use(new NewUserUseCase())

    val newList = use(new NewListUseCase(templateId,

    val listId =

It's not doing much beside calling two use case classes.

The neat implemantation of use() injects all domain layer dependencies into the use case classes, then executes the use case and returns it's result.

  def use[R](useCase: {def execute(): R}): R = {

An example use case from the example above that creates a new user does look like this:

class NewUserUseCase {
  @Inject var userRepository:UserRepository = _
  @Inject var idService:IdService = _

  def execute(): User = {
    var userId = idService.newId

With this setup, the web layer is ultra-thin, just calling use cases of the application layer. We now can

  1. easily unit test the use case classes
  2. reuse the use case classes in different controllers
  3. if we need, change the web framework by reusing all use case classes

Mission accomplished. How do you keep your web layer ultra thin?

Update:Found this here.

This one, simple, single line interface leads to many tangible benefits. The use of the ViewService interface completely decouples your code from your selection of which MVC framework you use. Your MVC selection no longer needs to be a strategic or organization-wide decision because switching, or even using a separate MVC framework per application, is now trivial. Each application you create now has the freedom and flexibility to use the best framework for the given requirements and technical circumstances.

The mixing MVC frameworks due to a thin web UI I completly forgot in the post.

Stephan Schmidt Administrator
CTO Coach , svese
Stephan is a CTO coach. He has been a coder since the early 80s, has founded several startups and worked in small and large companies as CTO. After he sold his latest startup he took up CTO coaching. He can be found on LinkedIn or follow him in Twitter.
follow me