2023-03-18 12:41:35

Scenario

There will be situations where a group of related functions are required to create a new microservice. However, the functions are embedded deep within your monolith. They may even be fragmented.

In this instance, we can use the Branch By Abstraction Pattern.

1 Create Abstraction

If the grouped functions are distributed around the monolith use the Facade Design Pattern to create a facade class.

Create an interface to represent the grouped functions to be used in the new microservice. Skip this step if an interface is already present, but bear in mind if the desired functions can be represented by a sub-set of method signations on the interface it may be useful to create an additional interface just for the functions.

2 Use Interface

3. Create Abstraction

Feature Toggle Pattern

Use Feature Toggle Pattern to easily switch between branches.

Link to Feature Toggle Pattern knowledge base article

4. Create New Web Service

Functions to Call the New Functionality

Use the repository design pattern as inspiration to create our functionality.

For Example

using AccountsManager_Domain.DataAccess;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace MyDomain.RemoteDataRepositories
{
    public class CustomerRepositoryService : ICustomerRepository
    {
        private static readonly HttpClient _client = new HttpClient();

        public CustomerRepositoryService(IConfiguration configuration)
        {
            // use https://localhost:#### for CustomerManagerAPI while developing
            _client.BaseAddress = new Uri($"{configuration.GetValue("CustomerManagerAPI")}");
            _client.Timeout = new TimeSpan(0, 0, 30);
            _client.DefaultRequestHeaders.Accept.Clear();
        }

        public async Task DeleteCustomer(Customer Customer)
        {
            // Setup HttyRequestMessage
            var request = new HttpRequestMessage(HttpMethod.Delete, $"/api/customer/{Customer.Id}");
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            // Get HttyResponseMessage
            var response = await _client.SendAsync(request);
            response.EnsureSuccessStatusCode();
            var content = await response.Content.ReadAsStringAsync();

            return content.Length == 0;
        }

        public async Task GetAllCustomersAsync()
        {
            // Setup HttyRequestMessage
            var request = new HttpRequestMessage(HttpMethod.Get, $"/api/customer/");
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            // Get HttyResponseMessage
            var response = await _client.SendAsync(request);
            response.EnsureSuccessStatusCode();
            var content = await response.Content.ReadAsStringAsync();
            var entities = JsonConvert.DeserializeObject(content);

            return entities;
        }

        public async Task GetCustomerAsync(int id)
        {
            // Setup HttyRequestMessage
            var request = new HttpRequestMessage(HttpMethod.Get, $"/api/customer/{id}");
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            // Get HttyResponseMessage
            var response = await _client.SendAsync(request);
            response.EnsureSuccessStatusCode();
            var content = await response.Content.ReadAsStringAsync();
            var entities = JsonConvert.DeserializeObject(content);

            return entities;
        }

        public async Task StoreNewCustomerAsync(Customer Customer)
        {
            // Setup HttyRequestMessage
            var entityToCreate = JsonConvert.SerializeObject(Customer);
            var request = new HttpRequestMessage(HttpMethod.Post, $"/api/customer/");
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            request.Content = new StringContent(entityToCreate);
            request.Content.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");

            // Get HttyResponseMessage
            var response = await _client.SendAsync(request);
            response.EnsureSuccessStatusCode();
            var content = await response.Content.ReadAsStringAsync();
            var newEntity = JsonConvert.DeserializeObject(content);

            return newEntity.Id > 0;
        }

        public async Task UpdateCustomerAsync(Customer Customer)
        {
            // Setup HttyRequestMessage
            var entityToUpdate = JsonConvert.SerializeObject(Customer);

            var request = new HttpRequestMessage(HttpMethod.Put, $"/api/customer/{Customer.Id}");
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            request.Content = new StringContent(entityToUpdate);
            request.Content.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");

            // Get HttyResponseMessage
            var response = await _client.SendAsync(request);
            response.EnsureSuccessStatusCode();
            var content = await response.Content.ReadAsStringAsync();
            var newEntity = JsonConvert.DeserializeObject(content);

            return newEntity.Id > 0;
        }
    }
}

The IConfiguration instance is usually passed to this class using inversion of control.

Copyright © 2024 delaney. All rights reserved.