c# – How to deal with business rules?

Question:

I'm working on a C# WPF + EF6 application and I find myself at a loss when it comes to reusing business rules.

I'm using the repository + unit of work pattern, but I think copy-pasting complex filters in my repository calls seems like a bad idea to me… So I decided to move the business rules to a new layer, but something still doesn't it's looking good to me… I currently have the following layers:

ViewModel : Where View Interaction Logic and Validation Occur

BLL : Layer created to try to work around the above problem, it is responsible for composing the search/addition/removal logic of an entity.

DAL (Default repository+UOF): Here I just persist the POCO in the database.

As I said, something doesn't feel right to me… I feel that this approach will bring me future problems, I don't feel comfortable with it:

mesaBL.TransferirItens(mesaOrigem, mesaDestino, itensIds);

I feel that my application is not well structured for changes.

Thank you in advance for your attention.

Here's a little code:

public class FooViewModel
{
    private readonly IContaMesaComandaItemBL _contaMesaComandaItemBL;

    public FooViewModel(IContaMesaComandaItemBL contaMesaComandaItemBL)
    {
        _contaMesaComandaItemBL = contaMesaComandaItemBL;
    }

    public int ItemId { get; set; }

    // Outras propriedades, comandos, métodos, etc...


    public void RemoverItemExecute()
    {
        _contaMesaComandaItemBL
            .DeletePorId(ItemId)
            .Subscribe(removido =>
            {
                // Item removido com sucesso
            },
            ex =>
            {
                // Erro
            });
    }
}

public class ContaMesaComandaItemBL : BLBase<ContaMesaComandaItem>, IContaMesaComandaItemBL
{
    public ContaMesaComandaItemBL(IUnitOfWorkFactory unitOfWorkFactory) : base(unitOfWorkFactory)
    {
    }

    public IObservable<bool> DeletePorId(int id)
    {
        return Observable.Create<bool>(obs =>
        {
            try
            {
                using (var unitOfWork = UnitOfWorkFactory.Create())
                {
                    var repository = unitOfWork.ContaMesaComandaItemRepository;
                    repository.Delete(e => e.ComandaItemPizzaMaeId == id);
                    repository.Delete(e => e.ContaMesaComandaItemId == id);
                    obs.OnNext(unitOfWork.Save() > 0);
                    obs.OnCompleted();
                }
            }
            catch (Exception ex)
            {
                obs.OnError(ex);
            }
            return Disposable.Empty;
        });
    }
}

A little more code:


public class ContaMesaBL : BLBase, IContaMesaBL
{
    public ContaMesaBL(IUnitOfWorkFactory unitOfWorkFactory) : base(unitOfWorkFactory)
    {
    }

    public IObservable AdicionarComanda(int contaMesaId, ContaMesaComanda comanda)
    {
        return Observable.Create(obs =>
        {
            try
            {
                using (var unitOfWork = UnitOfWorkFactory.Create())
                {
                    var contaMesaRepository = unitOfWork.ContaMesaRepository;
                    var conta = contaMesaRepository.First(c => c.ContaMesaId == contaMesaId);
                    conta.DataMovimento = DateTime.Now;
                    conta.ContaMesaComandas.Add(comanda);
                    unitOfWork.Save();
                    obs.OnNext(Unit.Default);
                    obs.OnCompleted();
                }
            }
            catch(Exception ex)
            {
                obs.OnError(ex);
            }
            return Disposable.Empty;
        });
    }
}

Answer:

You can create parallel validation classes and you can use a lib like FluentValidation to add the rules you want to apply and validate before processing something.

Scroll to Top