ServiceComposer / ServiceComposer.AspNetCore

🧩 ServiceComposer, a ViewModel Composition API Gateway
https://milestone.topics.it/categories/view-model-composition
Apache License 2.0
73 stars 11 forks source link
composition-gateway hacktoberfest viewmodel-composition

ServiceComposer

ServiceComposer is a ViewModel Composition Gateway.

Designing a UI when the back-end system consists of dozens (or more) of (micro)services is challenging. We have separation and autonomy on the back end, but this all needs to come back together on the front-end. ViewModel Composition stops it from turning into a mess of spaghetti code and prevents simple actions from causing an inefficient torrent of web requests.

Contents

Technical introduction

For a technical introduction and an overview of the problem space, refer to the following presentation on YouTube.

Getting Started

Imagine an elementary e-commerce web page where it's needed to display details about a selected product. These details are stored in two different services. The Sales service owns the product price, and the Marketing service owns the product name and description. ServiceComposer solves the problem of composing information from different services into one composed view model that downstream clients can later display or consume.

To start using ServiceComposer, follow the outlined steps:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRouting();
        services.AddViewModelComposition();
    }

    public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
    {
        app.UseRouting();
        app.UseEndpoints(builder => builder.MapCompositionHandlers());
    }
}

snippet source | anchor

public class SalesProductInfo : ICompositionRequestsHandler
{
    [HttpGet("/product/{id}")]
    public Task Handle(HttpRequest request)
    {
        var vm = request.GetComposedResponseModel();

        //retrieve product details from the sales database or service
        vm.ProductId = request.HttpContext.GetRouteValue("id").ToString();
        vm.ProductPrice = 100;

        return Task.CompletedTask;
    }
}

snippet source | anchor

public class MarketingProductInfo: ICompositionRequestsHandler
{
    [HttpGet("/product/{id}")]
    public Task Handle(HttpRequest request)
    {
        var vm = request.GetComposedResponseModel();

        //retrieve product details from the marketing database or service
        vm.ProductName = "Sample product";
        vm.ProductDescription = "This is a sample product";

        return Task.CompletedTask;
    }
}

snippet source | anchor

The HTTP response should be a JSON result containing the properties and values defined in the composition handler classes.

NOTE: ServiceComposer uses regular ASP.NET Core attribute routing to configure routes for which composition support is required.

In this brief sample, the view model instance returned by GetComposedResponseModel() is a C# dynamic object. dynamic objects are handy because they allow request handlers to be entirely independent of each other; they share nothing. ServiceComposer supports using strongly typed view models if they are preferred. They have the advantages of strong typing and compiler checks and the disadvantage of a little coupling. Refer to the view model factory documentation for more information.

Documentation and supported platforms

ServiceComposer is available for the following platforms:

Philosophy

Service Boundaries

When building systems based on SOA principles, service boundaries are key, if not THE key aspect. If we get service boundaries wrong, the end result risks being a distributed monolith in the best case and a complete failure in the worst case.

Service boundary identification is a challenge on its own; it requires extensive business domain knowledge and confidence in high-level design techniques. Technical challenges, such as the lack of technical solutions to problems foreseen while defining service boundaries, might drive the solution design in the wrong direction.

The transition from the user mental model, described by domain experts, to the service boundaries architectural model in the SOA space raises many different concerns. If domain entities, as defined by domain experts, are split among several services:

This type of question leads systems to be designed using rich events, not thin ones, to share data between services and with cache-like things, such as Elastic Search, to satisfy UI query/visualization needs.

This is the beginning of a road that can only lead to a distributed monolith, where data ownership is a lost concept and every change impacts and breaks the whole system. In such a scenario, it’s easy to blame SOA and the toolset.

ViewModel Composition techniques are designed to address all these concerns. They bring the separation of concerns, designed at the back end, to the front end.

For more details and the philosophy behind a Composition Gateway, refer to the ViewModel Composition series of article available on milestone.topics.it.