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.