2
respostas

Isto é aplicavel para todos cenários? Qual parte da logica precisa ser encapsulada?

Eu estou acompanhando o curso e aplicando os conceitos novos que estou aprendendo na minha aplicação, eu não consigo ver como criar este serviço pode ser aplciavel em todos os casos. O padrão é fazer toda a a lógica de gravação no banco de dados em um service?

veja bem a minha adaptação:

[Route("api/register")]
[HttpPost]
public async Task<IActionResult> Register([FromBody] CreateUserDto userDto)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    var emailexists = await _userManager.FindByEmailAsync(userDto.Email);
    if (emailexists != null)
    {
        ModelState.AddModelError("Email", "Email Alrealdy Exists");
        return BadRequest(ModelState);
    }

    var user = _mapper.Map<User>(userDto);
    var result = await _userManager.CreateAsync(user, userDto.Password);
    foreach(SocialProfileDto socialProfileDto in userDto.SocialProfiles)
    {
        var socialProvider = _context.SocialProviders.FirstOrDefault(x => x.Name.ToLower() == socialProfileDto.Provider.ToLower());
        var socialProfile = new SocialProfile()
        {
            UserId = user.Id,
            SocialProviderId = socialProvider.Id,
            Profile = socialProfileDto.Profile

        };
        await _context.SocialProfiles.AddAsync(socialProfile);
        await _context.SaveChangesAsync();
    }
    return CreatedAtAction("GetUser", user);





}

Em um contexto que o usuário que estou criando vai também estar cadastrando seus perfis em redes sociais, o da lógica eu envio para os serviços?

2 respostas

Olá, Clausemberg!

Entendo sua dúvida. O conceito de encapsular a lógica de gravação no banco de dados em um serviço é uma prática comum em muitos cenários, especialmente quando se busca uma arquitetura limpa e uma separação clara de responsabilidades. No entanto, é importante notar que nem todos os cenários são iguais e, às vezes, pode ser necessário adaptar essa abordagem para atender às necessidades específicas do seu projeto.

No exemplo que você compartilhou, a lógica de criação do usuário e o cadastro de seus perfis em redes sociais estão todos no mesmo método. Em uma abordagem de arquitetura limpa, você poderia considerar a criação de um serviço separado para lidar com a lógica de criação dos perfis de redes sociais.

Por exemplo, você poderia ter algo como:

[Route("api/register")]
[HttpPost]
public async Task<IActionResult> Register([FromBody] CreateUserDto userDto)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    var emailexists = await _userManager.FindByEmailAsync(userDto.Email);
    if (emailexists != null)
    {
        ModelState.AddModelError("Email", "Email Already Exists");
        return BadRequest(ModelState);
    }

    var user = _mapper.Map<User>(userDto);
    var result = await _userManager.CreateAsync(user, userDto.Password);
    
    if (result.Succeeded)
    {
        await _socialProfileService.CreateSocialProfiles(userDto.SocialProfiles, user.Id);
    }
    
    return CreatedAtAction("GetUser", user);
}

E em seu serviço de perfis sociais:

public class SocialProfileService
{
    private readonly YourDbContext _context;

    public SocialProfileService(YourDbContext context)
    {
        _context = context;
    }

    public async Task CreateSocialProfiles(IEnumerable<SocialProfileDto> socialProfileDtos, string userId)
    {
        foreach(SocialProfileDto socialProfileDto in socialProfileDtos)
        {
            var socialProvider = _context.SocialProviders.FirstOrDefault(x => x.Name.ToLower() == socialProfileDto.Provider.ToLower());
            var socialProfile = new SocialProfile()
            {
                UserId = userId,
                SocialProviderId = socialProvider.Id,
                Profile = socialProfileDto.Profile
            };
            await _context.SocialProfiles.AddAsync(socialProfile);
        }
        await _context.SaveChangesAsync();
    }
}

Dessa forma, a lógica para a criação dos perfis sociais está encapsulada em seu próprio serviço, tornando o código mais modular e mais fácil de manter e testar.

Espero ter ajudado e bons estudos!

Olá, Clausemberg! Como vai?

A ideia de encapsular a lógica de gravação no banco de dados em um serviço é uma prática comum quando se trabalha com a arquitetura MVC (Model-View-Controller). Isso porque o controlador deve ser responsável apenas por receber as requisições, delegar as ações e devolver as respostas, evitando assim que ele fique sobrecarregado de responsabilidades.

No seu caso, você está lidando com um cenário um pouco mais complexo, onde além de criar um usuário, você também está criando perfis de redes sociais para esse usuário. Nesse caso, a lógica de criação dos perfis de redes sociais também poderia ser encapsulada em um serviço.

Por exemplo, você poderia ter um serviço SocialProfileService que seria responsável por criar os perfis de redes sociais. Sua função Register ficaria mais ou menos assim:

[Route("api/register")]
[HttpPost]
public async Task<IActionResult> Register([FromBody] CreateUserDto userDto)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    var emailexists = await _userManager.FindByEmailAsync(userDto.Email);
    if (emailexists != null)
    {
        ModelState.AddModelError("Email", "Email Alrealdy Exists");
        return BadRequest(ModelState);
    }

    var user = _mapper.Map<User>(userDto);
    var result = await _userManager.CreateAsync(user, userDto.Password);
    if (result.Succeeded)
    {
        foreach(SocialProfileDto socialProfileDto in userDto.SocialProfiles)
        {
            await _socialProfileService.CreateSocialProfile(user, socialProfileDto);
        }
    }
    return CreatedAtAction("GetUser", user);
}

O serviço SocialProfileService teria um método CreateSocialProfile que ficaria responsável por toda a lógica de criação dos perfis de redes sociais:

public class SocialProfileService
{
    // ... outros códigos

    public async Task CreateSocialProfile(User user, SocialProfileDto socialProfileDto)
    {
        var socialProvider = _context.SocialProviders.FirstOrDefault(x => x.Name.ToLower() == socialProfileDto.Provider.ToLower());
        var socialProfile = new SocialProfile()
        {
            UserId = user.Id,
            SocialProviderId = socialProvider.Id,
            Profile = socialProfileDto.Profile
        };
        await _context.SocialProfiles.AddAsync(socialProfile);
        await _context.SaveChangesAsync();
    }
}

Dessa forma, você mantém a lógica de criação dos perfis de redes sociais isolada em um serviço, facilitando a manutenção e a reutilização desse código.

Lembrando que essa é uma sugestão de abordagem. Dependendo do contexto do seu projeto, outras abordagens podem ser mais adequadas.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.