Вот некоторый интерфейс IOrderSender
, который определяет бизнес-операцию (отправку заказа) с некоторой реализацией KafkaOrderSender
(через производителя Kafka в этом примере).
Код был переписан с C # с сохранением оригинального стиля ООП:
type CustomerId = string
type IOrderSender =
abstract SendOrders: CustomerId -> Order list -> unit
type KafkaOrderSender(config: IConfiguration) =
let streamConfig = config.GetSection("OrderStream")
let producerConfig = new ProducerConfig(BootstrapServers = streamConfig.GetValue("BootstrapServers"))
let producer = new Producer<string, string>(producerConfig)
let ordersTopic: string = streamConfig.GetValue("Topic")
interface IOrderSender with
member this.SendOrders customerId orders =
for order in orders do
let orderJson = JsonConvert.SerializeObject<Order>(order)
let msg = new Message<string, string>(Key = customerId, Value = orderJson)
do producer.BeginProduce(ordersTopic, msg)
interface IDisposable with
member this.Dispose() =
do producer.Flush(CancellationToken.None)
do producer.Dispose()
Здесь мы имеем:
интерфейс (IOrderSender
)
реализация (KafkaOrderSender
)
одна внешняя зависимость (IConfiguration
)
внутреннее состояние (producer
, необходимо разделить вызовы)
состояние должно быть закрыто / ликвидировано (IDisposable
)
Этот интерфейс и реализация зарегистрированы в некотором контейнере DI (например, ASP.NET Core с Giraffe):
let configureServices (services : IServiceCollection) =
services.AddGiraffe() |> ignore
services.AddSingleton<IOrderSender, KafkaOrderSender>() |> ignore
Этот объект затем разрешается через DI и используется в логике приложения:
let handleOrders (customerId: CustomerId) (orders: Orders): HttpHandler =
fun (next : HttpFunc) (ctx : HttpContext) ->
// Resolve
let orderSender = ctx.GetService<IOrderSender>()
// Use
do orderSender.SendOrders customerId orders
return! text "OK" next ctx
Есть ли лучший способ реализовать IOrderSender более идиоматическим функциональным способом (модуль вместо класса, частичное применение вместо зависимостей через конструктор)?
Как обрабатывать общее состояние (производитель) и как реализовать удаление общего состояния в этом случае?