The Cake walk

I come from a very Spring-heavy background in Java.  Spring is a bit of a loose, baggy monster, containing probably hundreds of features which aren’t all terribly well-connected to one another, but one thing that became second nature to me in Spring was the dependency-injection and IoC features.  Structuring software into composable components makes sense to me for scalability and ease of testing.

There are a few logical bits in random-album-cover that are clear candidates for components.  In particular,  the three distinct bits of information we’re getting from the web should probably each have a testing implementation and a live one (one which actually connects to the web and scrapes a page).  My Java instincts would probably structure the code something like the following:

interface Cover { ... }
class CoverImpl implements Cover { ... }

interface QuoteService {
    String getQuote();
}
class TestingQuoteServiceImpl implements QuoteService {
    String getQuote() { return "testing"; }
}
class LiveQuoteServiceImpl implements QuoteService {
    String getQuote() {
        // Fire up httpClient, connect to quote page, scrape for quote
        return result;
    }
}

interface CoverFactory {
    Cover generateNewCover();
}
class CoverFactoryImpl {
    QuoteService quoteService;
    Cover generateNewCover() {
        String quote = quoteService.getQuote();
        return new CoverImpl(quote);
    }
    void setImageService(QuoteService imageService) { ... }
}

Not shown: some Spring configuration that would wire up one of the two quote factory implementations into a CoverFactoryImpl instance.

None of this is rocket science. Translating it to idiomatic Scala is a bit trickier than it seemed at first. There are a few libraries which exist to do dependency injection in Scala, but there is also a method which relies on native library features, the Cake Pattern.  Adam Warski’s post from 2010 is a good summary of the idea, with code examples.

Digging a little more deeply into it, though, I found some discussion of the Cake Pattern which gave me pause.  In particular, the discussion on this post from Adam Warski, along with this post by Przemek Pokrywka and this one by Debasish Ghosh made me wonder if my understanding of what exactly the pattern does and how to implement it was not quite up to speed.

This had the salutary effect of driving me back to my primary sources (the Odersky et al “staircase book” and to a lesser extent, the O’Reilly book) for a refresher on self type annotations.  I’m still not entirely sure I grasp what the ultimate purpose of self types are; I can see the pragmatic effect of requiring that a concrete class which mixes in one trait must also mix in the trait that is referred to as a self type, but I don’t exactly see how to generalize this to more than a one-to-one trait relationship.  In some of the larger Spring projects I have worked on, literally hundreds of services (Java singleton instances) were composed and wired together — in the end there was an object graph.  If traits can only declare one self type, though, I don’t quite see how you would use this mechanism for anything other than an object list.  Clearly I’m missing something, but the staircase book is uncharacteristically terse on this point.

In any event, all was not lost, because chapter 29 of the staircase book essentially sets out to solve the exact problem I’d been working on: how best to structure and compose component-based software in Scala.  There seem to be a few ways of going about it, but for now I should have some simple examples to use as the basis for assembling my tiny services.  (It also opens up the possibility of comparing some of the more lightweight Scala DI frameworks down the road, which is something I’d probably enjoy.)

Advertisements
Previous Post
Next Post
Leave a comment

3 Comments

  1. Not sure if I understand you correctly when you say that “If traits can only declare one self type”, but you can do e.g.:

    trait NativeClientModule {
    this: MessageStorageModule with QueueStorageModule with MessageStatisticsStorageModule
    with VolatileTaskSchedulerModule with NowModule =>

    (example from the code of ElasticMQ)

    Adam

    Reply
  2. Hi Adam, thanks for the response, I wasn’t aware of that synax for multiple self types.

    Reply
  1. More delicious cake « Tim Gilbert's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: