Structure your Play application with the cake pattern (and test it)
-
Upload
yanns -
Category
Technology
-
view
1.654 -
download
0
description
Transcript of Structure your Play application with the cake pattern (and test it)
![Page 1: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/1.jpg)
Structure your Playapplication withthe cake pattern
and test it
![Page 2: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/2.jpg)
Structure a Play application like a cake
![Page 3: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/3.jpg)
We'll build a website for
Toys Basketball Association
![Page 4: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/4.jpg)
Architecture
![Page 5: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/5.jpg)
Player Backend
GET http://localhost:9001/players/1
HTTP/1.1 200 OKContent-Type: application/json; charset=utf-8Content-Length: 91
{"id":1,"name":"James P. Sullivan","height":"34 cm","weight":"370 g","team":"Monstropolis"}
![Page 6: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/6.jpg)
Player Backend
GET http://localhost:9001/players/1/photo
HTTP/1.1 200 OKLast-Modified: Thu, 12 Dec 2013 13:11:02 GMTEtag: "4911f28b55213..."Content-Length: 1753583Cache-Control: max-age=3600Content-Type: image/jpegDate: Mon, 23 Dec 2013 10:01:15 GMT
<binary>
![Page 7: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/7.jpg)
Video Backend
GET http://localhost:9002/videos/top
HTTP/1.1 200 OKContent-Type: application/json; charset=utf-8Content-Length: 83
[{"id":1,"summary":"dunk","players":[1]},...]
![Page 8: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/8.jpg)
Video Backend
GET http://localhost:9002/videos/1/stream.mp4range: bytes=200-280
HTTP/1.1 206 Partial ContentContent-Range: bytes 200-280/2154777Accept-Ranges: bytesConnection: keep-aliveContent-Length: 81Content-Type: video/mp4
http:////www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0
![Page 9: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/9.jpg)
Let's code
• first version
![Page 10: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/10.jpg)
Proud of ourselves?
let's refactor
![Page 11: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/11.jpg)
Tests with the new version?
![Page 12: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/12.jpg)
Test pyramid
unit tests
def f(input): output
assert output
![Page 13: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/13.jpg)
Test pyramid
component tests
![Page 14: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/14.jpg)
Test pyramid
integration tests
![Page 15: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/15.jpg)
Which tests are possible?
with the actual version
![Page 16: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/16.jpg)
Component hierarchy
how to avoid that?
![Page 17: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/17.jpg)
Introducing components
• Live coding
![Page 18: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/18.jpg)
Dependencies between components
class TopVideoService {
val videoGateway = new VideoGateway val playerGateway = new PlayerGateway
def topVideos(): [...] = { videoGateway.top() [...] }}
trait TopVideoServiceComp extends PlayerGatewayComp with VideoGatewayComp {
val topVideoService = new TopVideoService
class TopVideoService { def topVideos(): [...] = { videoGateway.top() [...] } }}
Dependencies
Provided service
![Page 19: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/19.jpg)
Introducing components
![Page 20: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/20.jpg)
Introducing components
✔ Components expose services only to other components
✔ One component must depend from another one to use the exposed service
![Page 21: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/21.jpg)
Testing with components
unit tests
![Page 22: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/22.jpg)
Testing with components
component tests
![Page 23: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/23.jpg)
Testing with components
component tests
![Page 24: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/24.jpg)
components as traits
✔ Components with exposed services and dependencies
✔ Unit tests
✔ Component tests
✔ Integration tests
![Page 25: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/25.jpg)
But...
• Testing is not optimal
• Which dependency should be mocked?
• The compiler can check that for us
some drawbacks
![Page 26: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/26.jpg)
Exposed service abstract
trait TopVideoServiceComp extends PlayerGatewayComp with VideoGatewayComp {
def topVideoService: TopVideoService
[...]}
trait TopVideoServiceComp extends PlayerGatewayComp with VideoGatewayComp {
val topVideoService = new TopVideoService
[...]}
Dependencies
Provided service
![Page 27: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/27.jpg)
Defining the desired service
trait TopVideoServiceComp extends PlayerGatewayComp with VideoGatewayComp {
def topVideoService: TopVideoService
[...]}
trait Application extends Controller with TopVideoServiceComp {
def index = [...]}
object Application extends Application
![Page 28: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/28.jpg)
Defining the desired service
trait TopVideoServiceComp extends PlayerGatewayComp with VideoGatewayComp {
def topVideoService: TopVideoService
[...]}
trait Application extends Controller with TopVideoServiceComp {
def index = [...]}
object Application extends Application
compilation error
compilation error
![Page 29: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/29.jpg)
Defining the desired service
trait TopVideoServiceComp extends PlayerGatewayComp with VideoGatewayComp {
def topVideoService: TopVideoService
[...]}
trait Application extends Controller with TopVideoServiceComp {
def index = [...]}
object Application extends Application
compilation error
compilation error
object Application extends Application { override val topVideoService = new TopVideoService}
![Page 30: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/30.jpg)
Defining the desired service
trait TopVideoServiceComp extends PlayerGatewayComp with VideoGatewayComp {
def topVideoService: TopVideoService
[...]}
trait Application extends Controller with TopVideoServiceComp {
def index = [...]}
object Application extends Application
compilation error
compilation error
object Application extends Application { override val topVideoService = new TopVideoService}trait TopVideoServiceCompImpl
extends TopVideoServiceComp { override val topVideoService = new TopVideoService}
object Application extends Application with TopVideoServiceCompImpl
![Page 31: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/31.jpg)
Introducing Registry
object Application extends Application with PlayerGatewayCompImpl with VideoGatewayCompImpl with HttpClientCompImpl with TopVideoServiceCompImpl
object Players extends Players with PlayerGatewayCompImpl with VideoGatewayCompImpl with HttpClientCompImpl with TopVideoServiceCompImpl
trait Registry extends HttpClientComp with PlayerGatewayComp with VideoGatewayComp with TopVideoServiceComp
trait RuntimeEnvironment extends Registry with VideoGatewayCompImpl with HttpClientCompImpl with PlayerGatewayCompImpl with TopVideoServiceCompImpl
object Application extends Application with RuntimeEnvironment
object Players extends Players with RuntimeEnvironment
![Page 32: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/32.jpg)
Runtime and Test Registries
trait Registry extends HttpClientComp with PlayerGatewayComp with VideoGatewayComp with TopVideoServiceComp
trait RuntimeEnvironment extends Registry with VideoGatewayCompImpl with HttpClientCompImpl with PlayerGatewayCompImpl with TopVideoServiceCompImpl
trait MockEnvironment extends Registry with Mockito { override val httpClient = mock[HttpClient] override val playerGateway = mock[PlayerGateway] override val videoGateway = mock[VideoGateway] override val topVideoService = mock[TopVideoService]}
![Page 33: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/33.jpg)
Traits with abstract methods
✔ Components with exposed services and dependencies
✔ Dependencies checked by compiler
✔ Unit tests
✔ Component tests
✔ Integration tests
![Page 34: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/34.jpg)
drawback of traits inheritance
![Page 35: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/35.jpg)
Introducing self type
trait TopVideoServiceComp extends PlayerGatewayComp with VideoGatewayComp {
def topVideoService: TopVideoService
[...]}
trait TopVideoServiceComp { self: PlayerGatewayComp with VideoGatewayComp =>
def topVideoService: TopVideoService
[...]}
Dependencies
Provided service
![Page 36: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/36.jpg)
self type annotation
„Any concrete class that mixed in the trait must ensure that its type conforms to the trait's self type“
source: http://docs.scala-lang.org/glossary/#self_type
![Page 37: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/37.jpg)
Traits with self types
✔ Components with exposed services and only explicit dependencies
✔ Unit tests
✔ Component tests
✔ Integration tests
![Page 38: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/38.jpg)
Parallel @Inject / traits
trait HttpClientComp { def httpClient: HttpClient
class HttpClient { ... }}
trait PlayerGatewayComp { self: HttpClientComp =>
<use httpClient>}
trait VideoGatewayComp { self: HttpClientComp =>
<use httpClient>}
public class HttpClient { ...}
public class PlayerGateway {
@Inject private HttpClient httpClient;
<use httpClient>}
public class VideoGateway {
@Inject private HttpClient httpClient;
<use httpClient>}
![Page 39: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/39.jpg)
Dependencies Injection
• „side effect“ of Cake pattern
• dependencies checked by compiler
![Page 40: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/40.jpg)
Alternatives for DI
• Spring, Guice...
• DI with macros: macwirehttp://typesafe.com/activator/template/macwire-activator
![Page 41: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/41.jpg)
Resolving dependencies at runtime
source: http://apmblog.compuware.com/2013/12/18/the-hidden-class-loading-performance-impact-of-the-spring-framework/
![Page 42: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/42.jpg)
Resolving dependencies at runtime
source: http://apmblog.compuware.com/2013/12/18/the-hidden-class-loading-performance-impact-of-the-spring-framework/
![Page 43: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/43.jpg)
Resolving dependencies at runtime
source: http://apmblog.compuware.com/2013/12/18/the-hidden-class-loading-performance-impact-of-the-spring-framework/
![Page 44: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/44.jpg)
Resolving dependencies at runtime
source: http://apmblog.compuware.com/2013/12/18/the-hidden-class-loading-performance-impact-of-the-spring-framework/
![Page 45: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/45.jpg)
DI with cake pattern
• dependencies are resolved at compile time
• no surprise at runtime
![Page 46: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/46.jpg)
traits with self type and implementation
• mix interface / implementation
• difficult to provide alternative runtime implementation
• cannot provide component dependency only for one implementation
some drawbacks
![Page 47: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/47.jpg)
traits with self type and implementation
ex with top videos
![Page 48: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/48.jpg)
traits with self type and implementation
• decouple interface / implementation
Let's fix it
![Page 49: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/49.jpg)
Decouple service definition / impl
trait TopVideoServiceComp { def topVideoService: TopVideoService
trait TopVideoService { def topVideos(): Future[Option[Seq[TopVideo]]] }}
trait TopVideoServiceCompImpl extends TopVideoServiceComp {
self: PlayerGatewayComp with VideoGatewayComp =>
override val topVideoService = new TopVideoServiceImpl
class TopVideoServiceImpl extends TopVideoService { def topVideos(): Future[Option[Seq[TopVideo]]] = videoGateway.top() [...] }}
trait TopVideoServiceComp {
self: PlayerGatewayComp with VideoGatewayComp =>
def topVideoService: TopVideoService
[impl of TopVideoService]}
trait TopVideoServiceCompImpl extends TopVideoServiceComp {
self: PlayerGatewayComp with VideoGatewayComp =>
override val topVideoService = new TopVideoService}
![Page 50: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/50.jpg)
Decouple service definition / impl
trait TopVideoServiceComp {
def topVideoService: TopVideoService trait TopVideoService { def topVideos(): Future[Option[Seq[TopVideo]]] }}
trait TopVideoServiceCompImpl extends TopVideoServiceComp {
self: PlayerGatewayComp with VideoGatewayComp =>
override val topVideoService = new TopVideoServiceImpl
class TopVideoServiceImpl extends TopVideoService { def topVideos(): Future[Option[Seq[TopVideo]]] = { videoGateway.top() [...] } }}
Dependencies specific to impl
Provided servicedefinition
service impl
![Page 51: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/51.jpg)
comparison of all variants
trait VideoGatewayComp extends HttpClientComp {
val videoGateway = new VideoGateway
sealed trait TopVideosResponse [...]
class VideoGateway { def top(): Future[TopVideosResponse] = [...] }}
✔ simple✗ alternative impl very difficult✗ forget what to override (in tests)
1st version
![Page 52: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/52.jpg)
comparison of all variants
trait VideoGatewayComp extends HttpClientComp {
def videoGateway: VideoGateway
sealed trait TopVideosResponse [...]
class VideoGateway { def top(): Future[TopVideosResponse] = [...] }}
trait VideoGatewayCompImpl extends VideoGatewayComp { override val videoGateway = new VideoGateway}
✔ dependencies checked by compiler✗ invisible inheritance of other
dependencies
2nd version
![Page 53: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/53.jpg)
comparison of all variants
trait VideoGatewayComp {
self: HttpClientComp =>
def videoGateway: VideoGateway
sealed trait TopVideosResponse [...]
class VideoGateway { def top(): Future[TopVideosResponse] = [...] }}
trait VideoGatewayCompImpl extends VideoGatewayComp { self: HttpClientComp => override val videoGateway = new VideoGateway}
✔ explicit dependent components✗ no separation interface / impl✗ boilerplate
3rd version
![Page 54: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/54.jpg)
comparison of all variants
trait VideoGatewayComp {
def videoGateway: VideoGateway
sealed trait TopVideosResponse [...]
trait VideoGateway { def top(): Future[TopVideosResponse] }
}
trait VideoGatewayCompImpl extends VideoGatewayComp {
self: HttpClientComp =>
override val videoGateway: VideoGateway = new VideoGatewayImpl
class VideoGatewayImpl extends VideoGateway { def top(): Future[TopVideosResponse] = [...] }}
✔ separation interface / impl✔ flexibility✗ boilerplate ++
4th version
![Page 55: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/55.jpg)
Number of traits in app
components with abstract methods
components with self type
annotations
components with self type annotations and real separation
interface / implementation
16 16 20
![Page 56: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/56.jpg)
Downside of Cake pattern (1)
![Page 57: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/57.jpg)
What do you need?
• only DI?
• multiple alternative implementations of same service?
![Page 58: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/58.jpg)
Downside of Cake pattern (2)
• compiler error
• let's minimize it
![Page 59: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/59.jpg)
Reducing # of compiler errors
class RuntimeEnvironment extends Registry with HttpClientCompImpl with VideoGatewayCompImpl with PlayerGatewayCompImpl with TopVideoServiceCompImpl
trait RuntimeEnvironment extends Registry with HttpClientCompImpl with VideoGatewayCompImpl with PlayerGatewayCompImpl with TopVideoServiceCompImpl
![Page 60: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/60.jpg)
Downside of Cake pattern (3)
• compilation speed
✔ minimize it with (abstract) class
✔ let's remove some traits
![Page 61: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/61.jpg)
Removing some traits
class RuntimeEnvironment extends Registry with HttpClientCompImpl with VideoGatewayCompImpl with PlayerGatewayCompImpl with TopVideoServiceCompImpl
trait HttpClientCompImpl extends HttpClientComp { override val httpClient = new HttpClient}
trait VideoGatewayCompImpl extends VideoGatewayComp { self: HttpClientComp => override val videoGateway = new VideoGateway}
trait PlayerGatewayCompImpl extends PlayerGatewayComp { [...]}
trait TopVideoServiceCompImpl extends TopVideoServiceComp { [...]}
class RuntimeEnvironment extends Registry {
override val httpClient = new HttpClient override val playerGateway = new PlayerGateway override val videoGateway = new VideoGateway override val topVideoService = new TopVideoService}
![Page 62: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/62.jpg)
Number of traits
components with abstract methods
components with self type
annotations
components with self type
annotations and real separation
interface / implementation
16 12 20
![Page 63: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/63.jpg)
About testing
different strategies
![Page 64: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/64.jpg)
About testing
![Page 65: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/65.jpg)
About testing
![Page 66: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/66.jpg)
Do no over-use it!
DI ease unit testing
![Page 67: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/67.jpg)
further discussion
• make cake pattern more manageable with https://github.com/sullivan-/congeal
trait UService extends hasDependency[URepository] { ...}
![Page 70: Structure your Play application with the cake pattern (and test it)](https://reader036.fdocuments.net/reader036/viewer/2022062405/55840cf1d8b42ab4608b4638/html5/thumbnails/70.jpg)
Credits
• http://www.flickr.com/photos/cefeida/2306611187/62/366: Cake, redux (Magic Madzik)
• http://www.flickr.com/photos/jason_burmeister/2125022193Iced Tree (Jason)
• http://www.flickr.com/photos/leandrociuffo/6270204821Berlin skyline (Leandro Neumann Ciuffo)
• http://www.flickr.com/photos/8047705@N02/5668841148/Slow and steady (John Liu)
• http://www.flickr.com/photos/jcapaldi/4201550567/Bon Appetit (Jim, the Photographer)
• http://www.epicfail.com/2012/07/17/about-to-fail-26/