4 Recomendações Práticas para Projetos de Microsserviços em .NET

Neste post, gostaria de compartilhar a estrutura que venho adotando em meus projetos com microsserviços. São algumas ideias que tenho adotado com êxito e que podem ajudar você a ter mais sucesso em seus próprios projetos.

Se tiver interesse em entender mais sobre microsserviços, recomendo que acesse o Guia de Conteúdo para Microsserviços deste site.

1. Adote arquitetura hexagonal

Gosto muito do conceito de arqutitetura hexagonal (leia o post relacionado se não está familiarizado com o cenceito) e, para microsserviços, entendo que o conceito se ajusta perfeitamente.

Seguindo essa ideia, sempre que começo a criar um microsserviço em .NET, crio dois projetos. Um que irá operar conter a aplicação (entenda-se: código do domínio) e outro que irá expor essa aplicação para meios externos (geralmente um cliente de mensageria ou uma web api)

2. Organize seu código em Feature folders

Nunca me senti confortável com a separação de código em pastas técnicas (entenda-se Controllers, Views e Models). No lugar disso, prefiro organizar meu código por Features.

A idéia é manter Controller, Views, InputModels e ViewModels todos em uma única pasta agrupados pela feature que está sendo implementada.

Asp.Net Core é suficientemente inteligente para conseguir entender o que está ocorrendo com os Controllers e com as Models automaticamente. O único ajuste necessário é para explicitar onde estão as Views. De qualquer forma, algo simples:

using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Razor;

namespace Web.Features
{
    public class FeaturesLocationExpander  : IViewLocationExpander
    {
        public void PopulateValues(ViewLocationExpanderContext context)
        {
            // nothing
        }

        public IEnumerable ExpandViewLocations(
                ViewLocationExpanderContext context, 
                IEnumerable viewLocations)
        {
            return new[]
            {
                "/Features/{1}/{0}.cshtml",   // feature specific content
                "/Features/Shared/{0}.cshtml" // shared
            };
        }
    }
}

Este código instrui o ASP.net core sobre onde localizar as Views. Para ativar esse código, basta modificar a configuração do Razor.

public void ConfigureServices(IServiceCollection services)
{
    services.AddIdentityApplication(_configuration);
    //
    services.AddMvc();
    services.Configure<RazorViewEngineOptions>(options =>
    {
        options.ViewLocationExpanders.Add(new FeaturesLocationExpander());
    });
}

3. Identifique claramente as interfaces da aplicação (CommandSide e QuerySide)

Sou adepto a ideia de separar claramente interfaces de comando (que mudam o estado da aplicação) e consulta (que apenas recuperam informações) – entenda-se CQRS.

Essa segregação explícita ajuda a explicar melhor o conceito e tornar tudo mais evidente para quem vai interpretar o código.

4. Adote Swagger

Documentar a API é fundamental. Por isso, defendo a ideia de já começar o projeto usando Swagger. Por convenção, todos os meus microsserviços (apenas API), em seu endereço raiz, redirecionam para a interface Swagger.

using Microsoft.AspNetCore.Mvc;

namespace WebApi.Features.Home
{
    public class HomeController : Controller
    {
        public IActionResult Index() =>
            new RedirectResult("~/swagger");
    }
}

Além disso, utilizo os pacotes Swashbuckle.AspNetCore e Swashbuckle.AspNetCore.Examples para fornecer uma experiência mais rica, fornecendo, inclusive, exemplos para dados que precisam ser enviados para o servidor.

[Authorize]
[Route("addpf")]
[HttpPut]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType(typeof(ClientePF), (int)HttpStatusCode.OK)]
[SwaggerRequestExample(typeof(IncluirClientePFCommand), typeof(IncluirClientePFCommandExample))]
public async Task<IActionResult> AddPF(
    [FromBody] IncluirClientePFCommand data,
    [FromHeader(Name = "x-requestid")] string requestId
)
{
    if (!ModelState.IsValid)
    {
        return ModelState.GenerateBadRequestFromExceptions();
    }

    Guid.TryParse(requestId, out var guid);
    var commandResult = await _mediator.Send(new IdentifiedCommand<IncluirClientePFCommand, ClientePF>(
        data,
        guid
    ));

    return commandResult != null
        ? (IActionResult)Ok(commandResult)
        : BadRequest();
}

Aliás, todos meus projetos de API contem uma pasta dedicada para códigos de exemplo para Swagger.

Concluindo

Sempre afirmo que “São as Cicatrizes que contam a história do guerreiro”. Essas recomendações são oriundas de algumas cicatrizes. Há muitas outras que poderia compartilhar, mas, por agora, gostaria de saber sua opinião. Quais dessas práticas você já adota?

Compartilhe este insight:

Elemar Júnior

Sou fundador e CEO da EximiaCo e atuo como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia.

Elemar Júnior

Sou fundador e CEO da EximiaCo e atuo como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia.

Mais insights para o seu negócio

Veja mais alguns estudos e reflexões que podem gerar alguns insights para o seu negócio:

Are you interested to know more about the internals of the .NET Runtime? So you should spend some time reading...
In this post, I’m going to share with you one of the RavenDB 4 features that I like the most:...
So, I decided to learn how to code using R. That’s something I wrote: ## defining a function makeCacheMatrix <-...
Há algum tempo aponto o “abuso” do GC é uma das principais causa para problemas de performance em produção. Nesse...
Um de meus temas de estudo preferidos no campo de desenvolvimento é design patterns. Isso sempre me levou a refletir...
What kind of optimizations could we expect from the C# compiler and the JIT? In this post, I would like...
Oferta de pré-venda!

Mentoria em
Arquitetura de Software

Práticas, padrões & técnicas para Arquitetura de Software, de maneira efetiva, com base em cenários reais para profissionais envolvidos no projeto e implantação de software.

× Precisa de ajuda?