andrebaltieri / Flunt

Validations and Notifications
https://github.com/andrebaltieri/flunt
MIT License
626 stars 162 forks source link

`Abstração` Criar uma abstração com a utilização de interfaces para Notifiable #110

Open OtavioVB opened 2 years ago

OtavioVB commented 2 years ago

Percebi a necessidade de criação de interfaces para a classe Notifiable para facilitar a realização de testes e herança entre contratos.

Algumas interfaces de meu projeto como essa:

public interface IRequestUser
{
    IEmail Email { get; }
    IName Name { get; }
    INickname Nickname { get; }
    IPassword Password { get; }
    IPasswordNotEncrypted PasswordNotEncrypted { get; }
    DateTime RegisterDate { get; }
    DateTime RegisterTime { get; }
    bool IsValid { get; }
    List<Notification> Notifications { get; }
}

Acaba precisando implementar

public interface IRequestUser
{
    bool IsValid { get; }
    List<Notification> Notifications { get; }
}

Para ter esses atributos utilizados normalmente em um GET. Sendo assim, acredito que seja necessário criar uma interface para Notifiable:


public interface INotifiable
{
    bool IsValid { get; }
    List<Notification> Notifications { get; }
}

Assim:

public interface IRequestUser : INotifiable
{
    IEmail Email { get; }
    IName Name { get; }
    INickname Nickname { get; }
    IPassword Password { get; }
    IPasswordNotEncrypted PasswordNotEncrypted { get; }
    DateTime RegisterDate { get; }
    DateTime RegisterTime { get; }
}

Nas próximas vezes, em outras classes não será necessário repetir a abstração dos atributos de Notifiable...

diegodrf commented 2 years ago

@OtavioVB,

public bool IsValid => _notifications.Any() == false;

e

public IReadOnlyCollection<T> Notifications => _notifications;

são implementados na classe abstrata Notifiable<T>. Sendo assim, ao herdar de Notifiable<T> sua classe já possuirá essas propriedades.

Em seu último exemplo você está herdando de notifiable pela sua interface IRequestUser. O correto seria herdar Notifiable<T> diretamente em sua implementação da classe RequestUser.

Segue um exemplo:

public class RequestUser : Notifiable<Notification>
{
    public RequestUser() { }

    public string Email { get; private set; }
    public string Name { get; private set; }
    public string Nickname { get; private set; }
    public string Password { get; private set; }
    public string PasswordNotEncrypted { get; private set; }
    public DateTime RegisterDate { get; private set; }
    public DateTime RegisterTime { get; private set; }
}

Desta forma ao instanciar sua classe, ela já possuirá as propriedades herdadas.

var requestUser = new RequestUser();
...
requestUser.Notifications;
requestUser.IsValid;

Você deve utilizar as Interfaces para definir contratos informando métodos. Caso precise definir propriedades, utilize uma classe abstrata para as propriedades e herde para definir os métodos de contrato.

Exemplo:

public interface UmaInterface
{
    void AlgumMetodo();
}

public abstract class ClasseAbstrata : UmaInterface
{
    public string AlgumaPropriedade { get; set; }
}

public class SuaClasseFinal : ClasseAbstrata
{
    public void AlgumMetodo()
    {

    }

var suaClasse = new SuaClasseFinal();

// Agora sua classe possui métodos e propriedades.
suaClasse.AlgumaPropriedade;
suaClasse.AlgumMetodo()
}