Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lists the Scala Components and introduces DI in scala #559

Merged
merged 7 commits into from Mar 15, 2017

Conversation

ignasi35
Copy link
Contributor

Provides a summary of available Components and introduces briefly the cake pattern and how to use it to create an Application and an ApplicationLoader.
Each item of the list has a brief definition, link to scaladocs and, when possible, an x-ref to a refguide page.


[CircuitBreakerComponents](api/com/lightbend/lagom/scaladsl/client/CircuitBreakerComponents.html)

* implementors of a Service Locator will need to extend this to reuse the Circuit Breaker config provided by Lagom.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The section listing StaticServiceLocatorComponents, ConfigurationServiceLocatorComponents, RoundRobinServiceLocatorComponents and CircuitBreakerComponents could be extracted into a page of its own or merged into a single item of this, already long, list of Components.

@@ -0,0 +1,96 @@
# Scala Components

The Lagom scaladsl requires building an Application that mixes in all the `Components` that will enable the required features for your code. This means each `Application` will need a specific set of cake slices. Not only that but `Dev` mode and `Prod` mode need adjusting since the environments where the Service is run vary.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should briefly introduce the cake pattern. This might sound strange and confusing to someone who has never encountered it before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I was on cruise control and thought we had that explained in Implementing Services already. Just checked and that section is missing a link or an explanation too.

This page looks like an appropriate location for an intro to cake.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think this page would be a better place for it. We also have to consider the order that people will see things in, if they read through the docs linearly.


@[lagom-application](code/ServiceImplementation.scala)

That is a simple enough Application but it's not complete for running. It extends [`LagomApplication`](api/com/lightbend/lagom/scaladsl/server/LagomApplication.html) so it has all the basic bits and pieces but you need to specify at least a [[Service Locator|ServiceLocator]] for each environment Lagom supports:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might not be clear that loadDevMode specifies a ServiceLocator by way of mixing in LagomDevModeComponents.


This is a list of available `Components` you will need to build your application cake.

[LagomServerComponents](api/com/lightbend/lagom/scaladsl/server/LagomServerComponents.html)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's somewhat inconsistent use of backtick quoting in this file. The usual convention is to use them when quoting code or identifiers used in the code. So, I wouldn't expect "Components" above or "Component" below to be displayed as inline code, because there are no identifiers with those names, but I would expect LagomServerComponents to be quoted with backticks.


[LagomServerComponents](api/com/lightbend/lagom/scaladsl/server/LagomServerComponents.html)

* a main `Component` for any Lagom Service and is already mixed into [`LagomApplication`](api/com/lightbend/lagom/scaladsl/server/LagomApplication.html), you won't need to use it explicitly. Includes [LagomServiceClientComponents](api/com/lightbend/lagom/scaladsl/client/LagomServiceClientComponents.html). See [[Wiring together a Lagom application|ServiceImplementation#Wiring-together-a-Lagom-application]].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the "Wiring together a Lagom application" section will need to be rewritten a bit to refer to this page and remove duplication. I was thinking the outcome of this PR would be to take that section and elevate it to a top-level page that includes all of the details you have here. Then, the section within the "Implementing services" page could just refer to how to register services, leaving most of the rest of the content to this page.

I also think that "Wiring together a Lagom application" (or "Lagom service"? We are inconsistent with our terminology) is a better title for the page than "Scala Components". While "Scala Components" does describe what is in the page, it isn't descriptive to someone who doesn't already know about how Lagom Scala services are assembled. On more reflection, I think a title like "Bootstrapping a Lagom Scala service" or "Dependency Injection in Lagom" might be even better. The rule of thumb I like to use is to imagine the person we want to land on this page, and think about what they might have typed into Google to find it.


[MetricsServiceComponents](api/com/lightbend/lagom/scaladsl/server/status/MetricsServiceComponents.html)

* adds a `MetricsService` to your service so you can remotely track the status of the CircuitBreakers on your service. Using this only makes sense when you Application is consuming other services (hence using remote calls protected with Circuit Breakers)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should link to the docs on circuit breakers.


[ClusterComponents](api/com/lightbend/lagom/scaladsl/cluster/ClusterComponents.html)

* registers the node to the Akka Cluster. Tha Akka Cluster is required by Pub-Sub and Persistent Entity support and you will rarely need to use it explicitly.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it should link to the clustering docs.


You can mix in `Components` from other frameworks or libraries, for example:

* [ConductRApplicationComponents](https://github.com/typesafehub/conductr-lib/blob/master/lagom1-scala-conductr-bundle-lib/src/main/scala/com/typesafe/conductr/bundlelib/lagom/scaladsl/ConductRApplicationComponents.scala)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we link to documentation that describes how to use this? Maybe http://www.lagomframework.com/documentation/1.3.x/scala/ConductR.html

You can mix in `Components` from other frameworks or libraries, for example:

* [ConductRApplicationComponents](https://github.com/typesafehub/conductr-lib/blob/master/lagom1-scala-conductr-bundle-lib/src/main/scala/com/typesafe/conductr/bundlelib/lagom/scaladsl/ConductRApplicationComponents.scala)
* [AhcWSComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.libs.ws.ahc.AhcWSComponents): provides Async HTTP communication
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear when users would need to bring this in... from what I can see, in practice all Lagom services include it.

This is a bit tangential to this PR, but it makes me wonder if we should be extending it in LagomApplication or LagomClientComponents. It seems like an implementation detail that we shouldn't expose to end users. The only other implementation I can find is the deprecated NingWSComponents. WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, I've thought about doing this a number of times, but there's every chance that Play will soon add an Akka HTTP implementation, and maybe users might want to select that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But shouldn't LagomApplication have AhcWSClient (or other) as default and let users override that at will. LagomApplication requires a WSClient in any case.

* [DBComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.DBComponents)
* [HikariCPComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents)

You can find a complete list of inherited `Components` in [Play docs](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the right link?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to use https://www.playframework.com/documentation/2.5.x/api/scala/play/api/db/HikariCPComponents.html, scaladoc automatically redirects to the frames version, but using the direct link has two advantages, it means our external link validation task (not run by CI but can be run manually) will pick up if the link is wrong, and also improves SEO.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant more that it links directly to HikariCPComponents, but the surrounding text talks about a complete list of components. Looks like a mistaken copy/paste from the previous link, but I'm not sure what a better link is, since there's no supertype for all of the components traits, and scaladoc doesn't seem to generate permalinks for searches. Maybe it should just go to the index?

* [ConductRApplicationComponents](https://github.com/typesafehub/conductr-lib/blob/master/lagom1-scala-conductr-bundle-lib/src/main/scala/com/typesafe/conductr/bundlelib/lagom/scaladsl/ConductRApplicationComponents.scala)
* [AhcWSComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.libs.ws.ahc.AhcWSComponents): provides Async HTTP communication
* [DBComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.DBComponents)
* [HikariCPComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When would you want to bring these in explicitly? DBComponents is implicitly included by JdbcPersistenceComponents.

Is HikariCPComponents required when using it? Should we include it implicitly, too? We don't really have any good examples of Scala + JDBC.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if HikariCPComponents should be included implicitly - the question is whether we want to allow users to pull in a different connection pool. If it gets included implicitly, then it makes that impossible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH, I added this too after seeing some issues related to that on support channels. IIUC it's necessary to include DBComponents and/or HikariCPComponents to complete the cake correctly.
I didn't to raise this discussion but it's interesting.

@ignasi35
Copy link
Contributor Author

ignasi35 commented Mar 1, 2017

Fixes #558

jroper
jroper previously requested changes Mar 6, 2017

[LagomServiceClientComponents](api/com/lightbend/lagom/scaladsl/client/LagomServiceClientComponents.html)

* a main `Component` for any Lagom Service or application consuming Lagom Services. It is already mixed into [`LagomClientApplication`](api/com/lightbend/lagom/scaladsl/client/LagomClientApplication.html), you won't need to use it explicitly. See [[Binding a service client|ServiceClients#Binding-a-service-client]].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually there are a number of use cases for using in explicitly. See:

https://github.com/lagom/online-auction-scala/blob/master/item-impl/src/main/scala/com/example/auction/item/impl/ItemApplication.scala

Often you may want to break your cake up into isolated layers that can be independently tested. In the example above, I've created a trait called ItemComponents which contains everything necessary to implement ItemServiceImpl. What it doesn't do is subscribe to the bidding service, that's done in ItemApplication. This allows me to use ItemComponents to instantiate ItemServiceImpl in tests, without needing to worry about mocking the BiddingService.

* [ConductRApplicationComponents](https://github.com/typesafehub/conductr-lib/blob/master/lagom1-scala-conductr-bundle-lib/src/main/scala/com/typesafe/conductr/bundlelib/lagom/scaladsl/ConductRApplicationComponents.scala)
* [AhcWSComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.libs.ws.ahc.AhcWSComponents): provides Async HTTP communication
* [DBComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.DBComponents)
* [HikariCPComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if HikariCPComponents should be included implicitly - the question is whether we want to allow users to pull in a different connection pool. If it gets included implicitly, then it makes that impossible.

You can mix in `Components` from other frameworks or libraries, for example:

* [ConductRApplicationComponents](https://github.com/typesafehub/conductr-lib/blob/master/lagom1-scala-conductr-bundle-lib/src/main/scala/com/typesafe/conductr/bundlelib/lagom/scaladsl/ConductRApplicationComponents.scala)
* [AhcWSComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.libs.ws.ahc.AhcWSComponents): provides Async HTTP communication
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, I've thought about doing this a number of times, but there's every chance that Play will soon add an Akka HTTP implementation, and maybe users might want to select that?

* [DBComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.DBComponents)
* [HikariCPComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents)

You can find a complete list of inherited `Components` in [Play docs](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to use https://www.playframework.com/documentation/2.5.x/api/scala/play/api/db/HikariCPComponents.html, scaladoc automatically redirects to the frames version, but using the direct link has two advantages, it means our external link validation task (not run by CI but can be run manually) will pick up if the link is wrong, and also improves SEO.

ignasi35 and others added 3 commits March 7, 2017 18:08
**TODO** There's still a couple of comments to be addressed:

 * whether `wiring together a lagom app` should be removed and merged
   with this.
 * whether db and hikari components should be refactored and/or
   listed here.
@ignasi35 ignasi35 force-pushed the 558-summary-list-of-components branch from deefebe to 8f3e2ba Compare March 7, 2017 17:09
@ignasi35
Copy link
Contributor Author

ignasi35 commented Mar 7, 2017

TODO There's still a couple of discussions to be addressed:

  • whether db/hikari/AhcWS components should be refactored and/or listed here
  • whether wiring together a lagom app should be removed and merged with this. I've worked on explaining the cake pattern and also included a section on creating the pattern in small parts to allow testing and clarity/decoupling. I haven't worked on removing wiring together a lagom app yet, when doing so I may have to improve the content in Scala Components. I am postponing the section rename until this merging is complete. Also, I'll have to reconsider what to do with the dead links (if any) once wiring together a lagom app is moved/gone. Finally, I liked @TimMoore suggestion wrt wiring together a lagom service ( s/application/service ), but I'm not sure we'd be abusing the term service .

@ignasi35 ignasi35 changed the title Lists the components available to build the Application cake [WIP] Lists the components available to build the Application cake (see TODO) Mar 7, 2017
@ignasi35
Copy link
Contributor Author

ignasi35 commented Mar 7, 2017

I've reformatted the content to group the Components into categories mirroring the contents of the Reference Guide and reordered to keep a similar order too.

@ignasi35
Copy link
Contributor Author

ignasi35 commented Mar 7, 2017

Formatted the groups into tables:

screen shot 2017-03-07 at 18 21 22
screen shot 2017-03-07 at 18 21 30

@ignasi35 ignasi35 dismissed jroper’s stale review March 7, 2017 17:22

Applied comments (fixed links and added content as commented)

@rstento
Copy link
Contributor

rstento commented Mar 7, 2017 via email

@TimMoore
Copy link
Contributor

TimMoore commented Mar 7, 2017

whether db/hikari/AhcWS components should be refactored and/or listed here

I think we can take refactoring out of scope for this pull request. We should list them in the meantime.

whether wiring together a lagom app should be removed and merged with this.

I think we should do this as part of this change, as otherwise this page does not make much sense on its own, especially if people read through the docs linearly and encounter this page before the service implementation page.

I've worked on explaining the cake pattern and also included a section on creating the pattern in small parts to allow testing and clarity/decoupling.

👍

I haven't worked on removing wiring together a lagom app yet, when doing so I may have to improve the content in Scala Components. I am postponing the section rename until this merging is complete.

Sure thing, but I'm conscious of the fact that if we put this out into the world, and then rename later, it could just mean more broken links.

Also, I'll have to reconsider what to do with the dead links (if any) once wiring together a lagom app is moved/gone.

There's not a whole lot we can do... no way to redirect an anchor. The best we could do, if this is a big concern, is leave the heading in the original page (perhaps moving it to the end) with a link back to this new page.

Finally, I liked @TimMoore suggestion wrt wiring together a lagom service ( s/application/service ), but I'm not sure we'd be abusing the term service .

After thinking about it more, I think we should name the page "Dependency injection in Lagom". I think the term "dependency injection" is probably more familiar and more Google-friendly than "wiring together", and it sidesteps the entire application/service issue while still being clear. 😄 It also subtly emphasizes that this is a cross-cutting concern, rather than something specific to the service API.

@TimMoore
Copy link
Contributor

TimMoore commented Mar 7, 2017

Also, WRT the title "Dependency injection in Lagom", we should also create an analogous page in the Java documentation that gives an overview of how Guice is used. I think it can be a separate PR.

@TimMoore
Copy link
Contributor

TimMoore commented Mar 8, 2017

@rstento I'll chime in with comments since @ignasi35 is probably offline for the day.

The Lagom scaladsl requires building an Application that mixes in all the
Components that will enable the required features for your code. This means
each Application will need a specific set of cake slices. Not only that but
Dev mode and Prod mode need adjusting the cake since the environments
where the Service is run will vary.

A few questions:

  • Not sure what the scaldsl is, is there a different name for it, or could
    you explain what it is?

That's Lagom's Scala API. The package name in the code is scaladsl. I agree with you that it should be spelled out in the documentation. We should avoid using shortcuts and jargon as much as possible.

  • Would the following intro make sense instead:

"Lagom offers several service components that you can include in your
application. When using using one of these components, you also need to
provide any functionality that it requires. Since the development and
production environments are often quite different, you need to make sure
that both environments have met dependencies in the correct way. One way to
do this is to use the "cake pattern".

I think it's an improvement.

I wonder if we should go even more fundamental. Can we assume that everyone is familiar with dependency injection as a general pattern? I don't want to distract with too much detail, but maybe we should link to http://di-in-scala.github.io/ and perhaps quote or paraphrase a few excerpts.

Here's my take:


When building services in Lagom, your code will have dependencies on Lagom APIs and other services that need to be satisfied by concrete implementations at runtime. Often, the specific implementations will vary between development, test and production environments, so it's important not to couple your code tightly to a concrete implementation class. A class can declare constructor parameters with the abstract types of its dependencies --- usually represented by traits in Scala --- allowing the concrete implementations to be provided when the class is constructed. This pattern is called "dependency injection" and is fundamental to the way Lagom applications are assembled. Read "Dependency Injection in Scala using MacWire" for more background on this pattern and its benefits.

Your service's dependencies will have their own dependencies on other APIs in turn. Taken all together, these form a dependency graph that must be constructed when your application starts up. This process is called "wiring" your application, and is performed by creating a subclass of LagomApplication that contains initialization code.


then I would remove the subhead and just follow with your next para

👍

+The cake pattern is a design pattern for Dependency Injection in scala
where an application (the cake) is built as by mixing in several traits
(the cake slices). Each trait may declare unimplemented def methods
stating what it requires to run. Each trait may provide implementations the
final application will need. To present an example, many Lagom Components
(or cake layers) declare a need for a ServiceLocator and as a developer
you are required to provide one when using one of those Components. If you
don't fulfill all the declared requirements for the cake slices you mix
into your cake, it will be incomplete and compilation will fail.

suggested edit to prev para - note that I changed slices to layers, but if
this is incorrect, please fix

Reading through all of "DI in Scala", Jonas's original cake pattern article and Martin's "Scalable Component Abstractions" paper, none of them either "slice" or "layer" in this context. I think "layer" is a more accurate description, but I'm wary of introducing terminology if it isn't in common use and doesn't correspond to the naming conventions in the API, which always uses "component".

+The cake pattern is a design pattern used in a number of languages,
including Scala.

I'm pretty sure it's specific to Scala. Have you found references to it being used in other languages? In any case, it's a bit immaterial to this page, so I think we should keep something closer to the original wording here.

The cake pattern offers a good model for Dependency
Injection. Think of an application as if it were a layered cake. To build
the cake, you add layers.

I think the original metaphor was more about mixing ingredients together. I think we should avoid metaphors, though, as in this context I don't think they'll help developers understand what they need to do in their code.

In fact, the more I read about this, the more I think that we should mostly avoid calling this the "cake pattern" and generally avoid using cake metaphors throughout the documentation. The pattern we have adopted is fairly different from the cake pattern as originally described by Jonas, which relied on self types and nested traits. What we're using is closer to the "thin cake" pattern as described by Adam Warski in "DI in Scala" and his earlier blog post.

Some influential people even call the cake pattern an anti-pattern, but this is referring to the original cake pattern, not the thin cake pattern we have adopted. A Quora answer for "What is the Scala Cake Pattern?" even says "Now it’s considered an anti-pattern and its usage is discouraged. I would recommend checking MacWire or Scaldi if you need dependency injection." This could easily confuse people, since we do use MacWire and not the version of the cake pattern that he is calling an anti-pattern.

So, my recommendation is that we should strike "cake pattern" from our vocabulary in favor of more specific descriptions of what to do in Lagom, and refer only in passing to the "thin cake pattern" that Warski describes, just so that people can understand the relationship to the "DI in Scala" site (I suggest) we reference earlier.

In the code, unimplemented def methods state
what is required.

I think "abstract methods" would be a more conventional and accurate way to refer to these.

Scala traits define a particular requirement for running
the application. Each trait may provide implementations the final
application will need. For example, many Lagom Components (or cake layers)
declare a need for a ServiceLocator. You are required to provide the
trait that you want to use in each environment. If you don't fulfill all of
the declared requirements for the layers you want in the cake, it will be
incomplete and will not compile.

Here's my suggested version of the paragraph:


It is common to have clusters of interdependent classes that together form a larger logical component. It can be useful to modularize wiring code in a way that reflects these groupings. You can do so in Scala by defining a "component" trait that includes a combination of lazy val declarations that instantiate concrete implementations of interfaces that the component provides. Some of their constructor parameters may be declared as abstract methods, indicating a dependency that must be provided by another component or your application itself. Your application can then extend multiple components to mix them together into a fully assembled dependency graph. If you don't fulfill all of the declared requirements for the components you include in your service, it will not compile.

In "Dependency Injection in Scala using MacWire" this method of mixing components together to form an application is referred to as the "thin cake pattern".


I think this would be a good place to bring over some of the content from "Implementing services" and introduce MacWire.

I agree with the rest of your suggestions, Ruth.

* [DBComponents](https://www.playframework.com/documentation/2.5.x/api/scala/play/api/db/DBComponents.html)
* [HikariCPComponents](https://www.playframework.com/documentation/2.5.x/api/scala/play/api/db/HikariCPComponents.html)

You can find a complete list of inherited `Components` in [Play docs](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copying this comment so it doesn't get lost in the outdated diff:

I meant more that it links directly to HikariCPComponents, but the surrounding text talks about a complete list of components. Looks like a mistaken copy/paste from the previous link, but I'm not sure what a better link is, since there's no supertype for all of the components traits, and scaladoc doesn't seem to generate permalinks for searches. Maybe it should just go to the index?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't understand your comment the first time. ;-)




You can mix in `Components` from other frameworks or libraries, for example:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment from the previous iteration is still not fully addressed:

There's somewhat inconsistent use of backtick quoting in this file. The usual convention is to use them when quoting code or identifiers used in the code. So, I wouldn't expect "Components" above or "Component" below to be displayed as inline code, because there are no identifiers with those names, but I would expect LagomServerComponents to be quoted with backticks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slipped through the cracks.


This is a list of available `Components` you may use to build your application cake. This list contains Components provided by Lagom, Play and other projects or libraries. You may develop your own Components and use those instead of the provided on this list as long as the contracts are fulfilled.

| Service Components ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table headers should be broken out of the table and rendered as markdown headings, so that they have individual anchors, and also because they logically don't form part of the table data.


## Components

This is a list of available `Components` you may use to build your application cake. This list contains Components provided by Lagom, Play and other projects or libraries. You may develop your own Components and use those instead of the provided on this list as long as the contracts are fulfilled.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really just provided by Lagom, Play and ConductR.


#### Building a cake step by step

`LagomServerComponents` and `LagomServiceClientComponents` are a bit special because they are already mixed into `LagomApplication` and `LagomClientApplication` respectively so you will rarely need to explicitly mix either of them into your Application. The reason why `LagomServerComponents` and `LagomServiceClientComponents` exist is so that you can build your Application cake as the sum of middle-sized portions. Instead of creating a single `abstract class` where you mix in all the Componenets, you may create one trait `MyPartialFooTrait` where you mix in `LagomServerComponents` and parts of your logic and then you could create `MyPartialBarTrait` with some other parts. Then you would build a `MyApplication` mixing in `MyPartialFooTrait` and `MyPartialBarTrait`. so far it's not very different from having a single Application where all Components are mixed. The key advantage of partially creating your cake is that you can use `MyPartialTrait` in isolation in your tests (instead of using a complete `MyApplication`) which will be lighter and provide decoupling.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This paragraph seems strangely stuck in the middle of the reference tables. I think it could be moved up and titled something like "Defining your own components traits". It should start with the "why" — what is the problem to be solved — and then continue on to the "how".

I would recommend naming examples with the Components suffix rather than Trait, since that's the established convention.

I'm also not a big fan of using "Foo" and "Bar" as example names, as it can make it difficult to comprehend what a realistic example might be. Better to elaborate a real-world use case for the technique and use meaningful names in that context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great idea. I didn't like how it was breaking the flow but wanted to present LagomServerComponents and LagomServiceClientComponents first.

Starting with the why is exactly what I needed.

Will think of a replacement for Foo and Bar.

@jroper
Copy link
Member

jroper commented Mar 8, 2017

So, my recommendation is that we should strike "cake pattern" from our vocabulary in favor of more specific descriptions of what to do in Lagom, and refer only in passing to the "thin cake pattern" that Warski describes, just so that people can understand the relationship to the "DI in Scala" site (I suggest) we reference earlier.

I think using the word thin cake pattern is fine, and I agree that we shouldn't push the metaphor too hard, or even at all. The big question that this leaves is, what do we call it when you add a components trait to your application? Should it be just that? "To use Kafka, you need to add the KafkaComponents trait to your application"? Is that descriptive enough? Currently, the documentation says things like "To use Kafka, you need to mix the KafkaComponents trait into your application cake". This is more specific. The nice thing about calling it a cake is that we have a name for it that we can unambiguously refer to throughout the documentation, "mix X into your cake" is something that very quickly a Lagom developer will become familiar with and know exactly what that means. Without having a name, it will become more ambiguous, and if a developer jumps into a part of the docs that tells them to add KafkaComponents to their application, but they don't understand what that means, what do they search for on the docs/google/stack overflow/mailing list to find out?

So I think in this case, there is enough value to introduce a name for the pattern that is being implemented, so my preference would be to simply use it as a name, and not to go into too much detail about the meaning of the name (we can link to other resources such as Warski's blog post).

Also something to note, I think over time, the thin cake pattern will become known as the cake pattern, and the "original" cake pattern will be forgotten. Play refers to it as the cake pattern, we discuss it as the cake pattern everywhere. I think over time the issues of the original cake pattern will not be a problem. We can aid this by publishing blog posts, contributing to existing stack overflow questions about it, updating resources that mention it, etc.

@TimMoore
Copy link
Contributor

TimMoore commented Mar 8, 2017

The big question that this leaves is, what do we call it when you add a components trait to your application? Should it be just that? "To use Kafka, you need to add the KafkaComponents trait to your application"? Is that descriptive enough? Currently, the documentation says things like "To use Kafka, you need to mix the KafkaComponents trait into your application cake". This is more specific. The nice thing about calling it a cake is that we have a name for it that we can unambiguously refer to throughout the documentation, "mix X into your cake" is something that very quickly a Lagom developer will become familiar with and know exactly what that means.

OK, yeah, that's a good point. I don't mind this specific use and agree that it makes things clearer.

That said, to pick on a specific point:

Without having a name, it will become more ambiguous, and if a developer jumps into a part of the docs that tells them to add KafkaComponents to their application, but they don't understand what that means, what do they search for on the docs/google/stack overflow/mailing list to find out?

My feeling is that everywhere in the docs where we talk about adding some trait to your application cake, we should link back to this page as background information. In general, I like liberal use of links both within the documentation and to external references. People shouldn't have to Google things to understand what they mean.

Agree with your overall conclusion.

@ignasi35
Copy link
Contributor Author

ignasi35 commented Mar 8, 2017

I ended up splitting the page in two as suggested. It was getting too big anyway.
Now there a page in DI and a page with the content I originally had in mind: a simple concise list of available components.

In "[Dependency Injection in Scala: guide](http://di-in-scala.github.io/#modules)" this method of mixing components together to form an application is referred to as the "thin cake pattern". The guide also introduces [Macwire](http://di-in-scala.github.io/#macwire) which we'll use in the next steps.

## Wiring together a Lagom application

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved Wiring together a lagom app and merged it with content on DI.

@@ -0,0 +1,43 @@
# Scala Components

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A page of it's own.

* [[Persistence and Cluster Components|ScalaComponents#Persistence-and-Cluster-Components]]
* [[Broker API Components|ScalaComponents#Broker-API-Components]]
* [[Service Locator Components|ScalaComponents#Service-Locator-Components]]
* [[Third party Components|ScalaComponents#Third-party-Components]]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As @rstento suggested, the DI page ends on a list of quick links to each group of components. Since this is already provided I made it so the next: of DI would be Service Metadata (instead of Scala Components.

Reading the guide top to bottom (or in the right-hand side index) the user will see:

  • Service descriptors
  • Implementing services
  • Dependency Injection
  • Scala Components
  • Service Metadata
  • Consuming services
  • Testing Services
  • Message serializers
  • Header Filters
  • Error handling

But in the index.toc I set it so Dependency Injection's next was not Scala Components but Service Metadata.

@@ -1,5 +1,7 @@
ServiceDescriptors:Service descriptors
ServiceImplementation:Implementing services
DependencyInjection:Dependency Injection;next=ServiceInfo
ScalaComponents:Scala Components
ServiceInfo:Service Metadata
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment above.

@ignasi35 ignasi35 dismissed TimMoore’s stale review March 9, 2017 19:46

I think all comments were addressed.

@ignasi35 ignasi35 changed the title [WIP] Lists the components available to build the Application cake (see TODO) Lists the Scala Components and introduces DI in scala Mar 9, 2017
@jroper jroper merged commit 8cab4d0 into lagom:master Mar 15, 2017
@TimMoore
Copy link
Contributor

@ignasi35 do you think we should backport this to 1.3.x?

@ignasi35
Copy link
Contributor Author

@ignasi35 do you think we should backport this to 1.3.x?

Sure, on it.

ignasi35 added a commit that referenced this pull request Mar 22, 2017
* Lists the components available to build the Application cake in scaladsl

* Fixed `other other`

* Introduce the cake pattern. Categorise and display in tables.

**TODO** There's still a couple of comments to be addressed:

 * whether `wiring together a lagom app` should be removed and merged
   with this.
 * whether db and hikari components should be refactored and/or
   listed here.

* Fix some PR comments (table title, 'define your components', ...). WIP

* Improves DI and moves it into a separate page

* Moves ScalaComponents and DependencyInjection into services/.

 * moved 'wiring a lagom app' into DependencyInjection

* Final cleanup. Remove dead code and docs duplicates.
@ignasi35
Copy link
Contributor Author

backport to 1.3.x f2d5274

@ignasi35 ignasi35 deleted the 558-summary-list-of-components branch June 29, 2017 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

None yet

4 participants