I am building an ASP.Net MVC web application using an n-tier approach. My structure looks like this:
Business Objects - Model
Data Access Layer - DAL
Business Logic Layer - BLL
Mapping Layer
ViewModels
Controllers
Views
I usually put calculations in the business layer, but what about calculations that are only used for presentation purposes? For example, on a view in my application I show the Invoice Total, any Payments made and the Balance Owing. Balance Owing is a calculated amount. Since I use Balance Owing many times in my application I am inclined to create a generic BalanceOwing method in my BLL, but there are other cases where a calculation is only ever going to be used for one view. In this case should the calculation instead go in the controller or in my case the mapping layer? (I have a mapping layer which I use to convert domain models to viewmodels. It keeps the controller tidier).
Is that really the dividing line? That is, if I can generalize a calculation and use it more than once it should go in the BLL, but if it is specific to one view it should be in the controller or mapper?
SUMMARY:
I went with @trailmax's answer because he saw that some things that I thought of as presentation logic were in fact business logic and therefore belong in the BLL. In cases where something really is presentation logic and involves calculations such as pagination, I would put these in a utility class or extension method as mentioned by @ramiramilu
It all comes down to what you consider to be a "view-specific". If that is a calculation of screen resolution or browser version - then absolutely. If you are talking about duration that is simple enough, I'd think twice. It might look simple, but actually in the future can evolve - just keep it in BLL.
In comments you mentioned period duration. This might look simple just now
(End - Start).Date
. But this might evolve later into calculate the duration of this period excluding Weekends (for example). And this is definitely BLL, not even Mapping layer.I've done a views with logic embedded. And then I've seen these views evolving. This was not pretty. Ended up gutting ALL the logic out of views and placing that into a
QueryHandler<T>
. So my rule of thumb is to do all calculations in BLL (or Query Handlers if you are using CQRS). And just give prepared data to a view. (Also this approach minimises the need for mapping layer). This way your view only has a Single Responsibility - display data in the required format.As for mapping layer, again I prefer to have minimum logic there. I allow for
DateTime
to be converted to aString
in format2 Feb 2014
, but anything more than that and you are in trouble again.Paging is a spread-out concept. It is not really Business Logic, but also not a responsibility of a View. But because it goes so deep into the application, it ends up with BLL anyway (Or Query Handlers in our case).