Skip to content

Instantly share code, notes, and snippets.

@emadb
Last active March 4, 2023 22:39
Show Gist options
  • Save emadb/d2a0337faa0cfc942317e5a32fc103f2 to your computer and use it in GitHub Desktop.
Save emadb/d2a0337faa0cfc942317e5a32fc103f2 to your computer and use it in GitHub Desktop.
Validation and domain
// Controller HTTP
public class Controller
{
public UserResponse Post(UserRequest req)
{
User user = createUserValidator.Validate(req);
// Fino a qui sono nel contesto HTTP
// Qui entro nel dominio. Forse sarebbe meglio usare un gateway per accedere al dominio
// ma dipende dal tipo di applicazione.
user.Create();
// Qui torno nel contesto HTTP
return CreateUserResponse(user);
}
}
// Valiratore dell'operazione di creazione di un utente (sono ancora nel contesto HTTP)
public class CreateUserValidator
{
private IUserRepository repo;
public CreateUserValidator(IUserRepository repo)
{
this.repo = repo;
}
public User Validate(UserRequest req)
{
if (String.IsNullOrEmpty(req.Email)
{
throw MissingEmailException();
}
// Potrei verificare anche se l'email è univoca
IList<Roles> roles = req.Roles.Select(r => repo.GetRole(r));
if (roles.Some(r => r == RoleNotFound.Value))
{
throw MissingRoleException();
}
return UserFactory.create(req.email, roles);
}
}
// DM: classe di dominio
public class User : AggregateRoot
{
public User(/*varie dipendenze: repo, serivizi, ecc...*/)
{}
public User Create(User user)
{
// Fai qualcosa con l'utente:
// - schedula l'invio di una mail tramite apposito servizio
// - fa qualcos'altro
return this.userRepository.save(user);
}
}
@arialdomartini
Copy link

arialdomartini commented Mar 4, 2023

class EmaDB
{
    class Controller : ASP.ControllerBase
    {
        private Context _db;

        [ASP.HttpPost]
        public ASP.IActionResult CreateUser(ApiUser apiUser)
        {
            return DbUser
                .WithEmail(apiUser.Email)
                .ForAll(apiUser.Roles, LoadRole)
                .Match<ASP.IActionResult>(u =>
                    {
                        _db.Users.Add(u);
                        _db.SaveChanges();
                        return NoContent();
                    },
                    () => BadRequest("Roles not found"));
        }

        Option<Role> LoadRole(ApiRole apiRole) =>
            _db.Roles.SingleOrDefault(r => r.Name == apiRole.Name);
    }
}

static class UserExtensions
{
    internal static Option<DbUser> ForAll(this DbUser dbUser, IEnumerable<ApiRole> roles, Func<ApiRole, Option<Role>> loadRole) =>
        roles.Select(loadRole).Sequence().Select(roles => dbUser with { Roles = roles.ToArray() });
}

internal record ApiUser(String Email, IEnumerable<ApiRole> Roles);
internal record ApiRole(String Name);

internal record DbUser(String Email, IEnumerable<Role> Roles = null)
{
    public static DbUser WithEmail(string email) => new(Email: email);
}

internal record Role(Guid Id, String Name);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment