Skip to content

Instantly share code, notes, and snippets.

@mkulak
Last active March 19, 2023 13:36
Show Gist options
  • Save mkulak/0877c1dfeee7b14f6da5c1b0dd115224 to your computer and use it in GitHub Desktop.
Save mkulak/0877c1dfeee7b14f6da5c1b0dd115224 to your computer and use it in GitHub Desktop.
fun main() {
val s3Client = S3Client()
val httpClient = HttpClient()
val rabbitMqClient = RabbitMqClient()
val jsonMapper = JsonMapper()
val userRepo = UserRepo()
val orderRepo = OrderRepo()
val auth = Auth()
val inventoryClient = InventoryClient(httpClient, jsonMapper)
val taxesClient = TaxesClient(httpClient, jsonMapper)
val orderReportUploader = OrderReportUploader(s3Client)
val priceCalculator = PriceCalculator(inventoryClient, taxesClient)
val orderService = OrderService(orderRepo, priceCalculator, orderReportUploader)
val userService = UserService(orderService, userRepo, rabbitMqClient, jsonMapper)
val httpApi = HttpApi(userService, orderService, jsonMapper, auth)
httpApi.startServer(8080)
}
class S3Client
class HttpClient
class RabbitMqClient
class JsonMapper
class UserRepo
class OrderRepo
class Auth
class OrderReportUploader(val s3Client: S3Client)
class InventoryClient(val httpClient: HttpClient, val jsonMapper: JsonMapper)
class TaxesClient(val httpClient: HttpClient, val jsonMapper: JsonMapper)
class PriceCalculator(val inventoryClient: InventoryClient, val taxesClient: TaxesClient)
class OrderService(
val orderRepo: OrderRepo,
val priceCalculator: PriceCalculator,
val orderReportUploader: OrderReportUploader
)
class UserService(
val orderService: OrderService,
val userRepo: UserRepo,
val rabbitMqClient: RabbitMqClient,
val jsonMapper: JsonMapper
)
class HttpApi(
val userService: UserService,
val orderService: OrderService,
val jsonMapper: JsonMapper,
val auth: Auth
) {
fun startServer(port: Int) {}
}
import com.google.inject.AbstractModule
import com.google.inject.Guice
import com.google.inject.Inject
class AppModule : AbstractModule() {
override fun configure() {
bind(S3Client::class.java)
bind(HttpClient::class.java)
bind(RabbitMqClient::class.java)
bind(JsonMapper::class.java)
bind(UserRepo::class.java)
bind(OrderRepo::class.java)
bind(Auth::class.java)
bind(OrderReportUploader::class.java)
bind(InventoryClient::class.java)
bind(TaxesClient::class.java)
bind(PriceCalculator::class.java)
bind(OrderService::class.java)
bind(UserService::class.java)
bind(HttpApi::class.java)
}
}
fun main() {
val injector = Guice.createInjector(AppModule())
val httpApi = injector.getInstance(HttpApi::class.java)
httpApi.startServer(8080)
}
class S3Client @Inject constructor()
class HttpClient @Inject constructor()
class RabbitMqClient @Inject constructor()
class JsonMapper @Inject constructor()
class UserRepo @Inject constructor()
class OrderRepo @Inject constructor()
class Auth @Inject constructor()
class OrderReportUploader @Inject constructor(val s3Client: S3Client)
class InventoryClient @Inject constructor(val httpClient: HttpClient, val jsonMapper: JsonMapper)
class TaxesClient @Inject constructor(val httpClient: HttpClient, val jsonMapper: JsonMapper)
class PriceCalculator @Inject constructor(val inventoryClient: InventoryClient, val taxesClient: TaxesClient)
class OrderService @Inject constructor(
val orderRepo: OrderRepo,
val priceCalculator: PriceCalculator,
val orderReportUploader: OrderReportUploader
)
class UserService @Inject constructor(
val orderService: OrderService,
val userRepo: UserRepo,
val rabbitMqClient: RabbitMqClient,
val jsonMapper: JsonMapper
)
class HttpApi @Inject constructor(
val userService: UserService,
val orderService: OrderService,
val jsonMapper: JsonMapper,
val auth: Auth
) {
fun startServer(port: Int) {}
}
fun main() {
val s3Client = S3Client()
val httpClient = HttpClient()
val rabbitMqClient = RabbitMqClient()
val jsonMapper = JsonMapper()
val userRepo = UserRepo()
val orderRepo = OrderRepo()
val auth = Auth()
with(s3Client) {
with(httpClient) {
with(rabbitMqClient) {
with(jsonMapper) {
with(userRepo) {
with(orderRepo) {
with(auth) {
val inventoryClient = InventoryClient()
val taxesClient = TaxesClient()
val orderReportUploader = OrderReportUploader()
with(inventoryClient) {
with(taxesClient) {
val priceCalculator = PriceCalculator()
with(priceCalculator) {
with(orderReportUploader) {
val orderService = OrderService()
with(orderService) {
val userService = UserService()
with(userService) {
HttpApi().startServer(8080)
}
}
}
}
}
}
}
}
}
}
}
}
}
}
class S3Client
class HttpClient
class RabbitMqClient
class JsonMapper
class UserRepo
class OrderRepo
class Auth
context(S3Client)
class OrderReportUploader
context(HttpClient, JsonMapper)
class InventoryClient
context(HttpClient, JsonMapper)
class TaxesClient
context(InventoryClient, TaxesClient)
class PriceCalculator
context(OrderRepo, PriceCalculator, OrderReportUploader)
class OrderService
context(OrderService, UserRepo, RabbitMqClient, JsonMapper)
class UserService
context(UserService, OrderService, JsonMapper, Auth)
class HttpApi {
fun startServer(port: Int) {}
}
fun main() {
with(S3Client(), HttpClient(), RabbitMqClient()) {
with(JsonMapper(), Auth(), UserRepo(), OrderRepo()) {
with(InventoryClient(), TaxesClient(), OrderReportUploader()) {
with(PriceCalculator()) {
with(OrderService()) {
with(UserService()) {
HttpApi().startServer(8080)
}
}
}
}
}
}
}
// Without @Suppress it fails to compile in 1.8.10: Subtyping relation between context receivers is prohibited
@Suppress("SUBTYPING_BETWEEN_CONTEXT_RECEIVERS")
fun <A, B, R> with(a: A, b: B, f: context(A, B) () -> R): R =
f(a, b)
@Suppress("SUBTYPING_BETWEEN_CONTEXT_RECEIVERS")
fun <A, B, C, R> with(a: A, b: B, c: C, f: context(A, B, C) () -> R): R =
f(a, b, c)
@Suppress("SUBTYPING_BETWEEN_CONTEXT_RECEIVERS")
fun <A, B, C, D, R> with(a: A, b: B, c: C, d: D, f: context(A, B, C, D) () -> R): R =
f(a, b, c, d)
class S3Client
class HttpClient
class RabbitMqClient
class JsonMapper
class UserRepo
class OrderRepo
class Auth
context(S3Client)
class OrderReportUploader
context(HttpClient, JsonMapper)
class InventoryClient
context(HttpClient, JsonMapper)
class TaxesClient
context(InventoryClient, TaxesClient)
class PriceCalculator
context(OrderRepo, PriceCalculator, OrderReportUploader)
class OrderService
context(OrderService, UserRepo, RabbitMqClient, JsonMapper)
class UserService
context(UserService, OrderService, JsonMapper, Auth)
class HttpApi {
fun startServer(port: Int) {}
}
// this "with val" syntax doesn't exist currently
fun main() {
with val s3Client = S3Client()
with val httpClient = HttpClient()
with val rabbitMqClient = RabbitMqClient()
with val jsonMapper = JsonMapper()
with val userRepo = UserRepo()
with val orderRepo = OrderRepo()
with val auth = Auth()
with val inventoryClient = InventoryClient()
with val taxesClient = TaxesClient()
with val orderReportUploader = OrderReportUploader()
with val priceCalculator = PriceCalculator()
with val orderService = OrderService()
with val userService = UserService()
HttpApi().startServer(8080)
}
class S3Client
class HttpClient
class RabbitMqClient
class JsonMapper
class UserRepo
class OrderRepo
class Auth
context(S3Client)
class OrderReportUploader
context(HttpClient, JsonMapper)
class InventoryClient
context(HttpClient, JsonMapper)
class TaxesClient
context(InventoryClient, TaxesClient)
class PriceCalculator
context(OrderRepo, PriceCalculator, OrderReportUploader)
class OrderService
context(OrderService, UserRepo, RabbitMqClient, JsonMapper)
class UserService
context(UserService, OrderService, JsonMapper, Auth)
class HttpApi {
fun startServer(port: Int) {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment