Which Pattern is used to validate business rule?

Asked

Viewed 1,269 times

6

I use Repository Patterns for searches,save and delete

I wonder where is the best validation of my business...

Ex:

I need to check if the item is in a contrato of a prestador, and bill him with the commission that is in the contract.

There is a business rule there, where would it fit better to do it? In Dao classes? in Repository itself(I don’t know if it can be done) Here where I work are passing this rule in the controller, what I do not think is right, I would like opinions

2 answers

5

The most commonly used pattern (even without knowledge) is the Service Layer (Service layer).

Design Pattern Service Layer

The architecture of an application is usually divided into layers ranging from the database to the user interface or external systems.

In the middle of it all there are business rules. They are not part of the data model, although I use it. Nor would it be the responsibility of the controllers and much less of the views, although they need to access the business rules.

This is well represented in the following image:

Service Layer Pattern

The service layer should implement the system’s core functionalities and provide all of them to the "outside world" through a well-defined interface.

This prevents the system core from being exposed directly to the "higher" layers of architecture, otherwise the coupling would make maintenance a real nightmare.

References

  • Nice that Pattern, I did not know, but could give examples of code? There in the image is architecture, where in . net, would be a new class library

  • @Rod I don’t know the architecture well . Net... Sorry :(

  • Search on BLL C#, is the responsible layer.

4


The @utluiz response is correct within a context in 3 layers (presentation, service and data), but as we are talking about MVC, the validation should be done, essentially, in the Model, but not just in it.

Why?

The essential function of Model is to model how information circulates within the system, from the point of view of each entity. The essential function of the Controller is to harmonize and coordinate information flows - coming from the presentation, the data layer or some external service.

Therefore, validation functions of any data are normally generated at the level of Model. The Controller only interprets this result of the validations. It is done so because the validation is an aspect at the level of the data. Elegantly, this is done in ASP.NET MVC using Attributes.

However, relationships between entities (Models) are resolved at the level of Controller (comparisons, insertions, exclusions, ordering, etc.).

Examples

Consider the Model Pessoa down below:

public class Pessoa 
{
    [Key]
    public Guid PessoaId {get;set;}

    [Display(Name = "Nome")]
    [Required(ErrorMessage = "O preenchimento do nome da pessoa é obrigatório.")]
    public String Nome {get;set;}

    [Required(ErrorMessage = "O preenchimento do CPF da pessoa é obrigatório.")]
    [CPF]
    public Decimal Cpf {get;set;}

    public virtual ICollection<Produto> Produtos {get;set;}
}

By saving a Pessoa bank, I don’t need to write a single validation line in my Controller because all aspects of data are being processed within the Model succinctly: the CPF has an attribute that validates the CPF, the name cannot be filled out empty and the primary key needs to be unique ([Key]).

The Controller does nothing here but check through another class if the Model is valid:

[HttpPost]
public ActionResult Create(Pessoa pessoa)
{
    // Se o Model for válido
    if (ModelState.IsValid) 
    {
        // Gera a chave, salva e retorna
        pessoa.PessoaId = Guid.NewGuid();
        context.Pessoas.Add(pessoa);
        context.SaveChanges();
        return RedirectToAction("Index");
    }

    // Se não for válido, simplesmente retorna o objeto Pessoa de novo.
    // O resultado das validações está dentro da classe ModelState.

    return View(pessoa);
}

Suppose now I want to grant a discount on one Produto acquired by the user. This aspect is dealt with in Controller because we are dealing with a Pessoa and the Produtos acquired by her:

public class PessoasController : Controller 
{
    ...

    public ActionResult ConcederDescontoUltimoProduto(Guid? id) 
    {
        var pessoa = context.Pessoas.Include(p => p.Produtos).SingleOrDefault(p => p.PessoaId == id);

        if (pessoa.Produtos.Count > 5) 
        {
            var produto = pessoa.Produtos.Last();
            // Vou conceder 10% de desconto no valor do produto
            produto.Preco -= produto.Preco * 0.1;
            context.Entry(produto).State = EntityState.Modified;
            context.SaveChanges();
        }

        return RedirectToAction("Index");
    }
}

It is still possible to leave this negotiating aspect to other specific classes, but I consider it a long and unnecessary effort, in which nothing contributes to the security and responsibility of classes in the system.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.