2

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

Louise Eggleton
  • 969
  • 2
  • 15
  • 27
  • what kind of calculation do you consider to be "view-specific"? – trailmax Jan 22 '14 at 12:07
  • @trailmax For example, consider an event that has a start date/time and an end date/time. Duration, which can be calculated from these two inputs could be a view specifc calculation. – Louise Eggleton Jan 22 '14 at 12:26
  • I'd consider duration to be a business value. i.e. does it include weekends? Does it involve some other logic specific to your domain? I consider view specific operation is to find out what screen resolution is used. Anything else should be done in BLL. – trailmax Jan 22 '14 at 12:33
  • @trailmax So really what this comes down to is where is the diving line between what is considered business logic and what is presentational? I previously would have thought that duration is purely presentational, but now I am wondering. Maybe I should ask that as a separate question. – Louise Eggleton Jan 22 '14 at 13:00
  • I stopped doing any separation a while ago. My rule of thumb is: anything that you calculate is business logic. Views/ViewModels should not have any kind of operation on data, they should just spit out whatever was provided in a required format. – trailmax Jan 22 '14 at 13:05
  • @trailmix So you're saying that only things like pagination or as you mentioned screen resolution are presentational calculations and that if it involves calculation on business objects for presentational purposes it is considered business logic? – Louise Eggleton Jan 22 '14 at 13:17
  • @trailmax Your comments, answered my question better than any of the actual answers. You saw that the real problem was my definition of what constitutes presentation logic vs what is business logic. Previously I thought that if a calculation was only used for reporting purposes in a specific view it was presentation logic, but now I see presentation logic in a narrower scope. Now I see that the only calculations involving "how" info is presented belong in the presentation layer eg (pagination, screen resolution). If you can summarize your comments in an answer I will accept it. – Louise Eggleton Jan 22 '14 at 14:24

5 Answers5

3

I'm not a fan of any real logic in the controllers. So, I'd move it to the existing BLL, or even a new component in the BLL if you want to keep it separate.

The reasons I take this approach is two fold.

First, this sort of logic tends to grow out of control, and it will really clutter up your controller actions. I like them to be very concise. (I generally have three things happen in them - Authentication, Data Retrieval, ViewModel construction. These are each achieved by calling an individual method in some form of BLL.)

The second reason, is because controller actions are more difficult to unit test, especially if they have a lot of messy logic. Structuring my controller actions this way really lends itself to good unit testing practices.

SethMW
  • 1,062
  • 1
  • 9
  • 10
  • I also like my controllers to be concise which is why I have a mapping layer. So I even move the most of the view model construction to the mapping layer. So in my case view-specific calculations are never directly in the controller, but in the mapping layer. I phrased my question to include controllers so that my question can also be applicable to future readers who don't have a mapping layer. – Louise Eggleton Jan 22 '14 at 12:33
  • @LouiseEggleton this violates SRP for mapping layer - it does mapping AND some calculations. – trailmax Jan 22 '14 at 12:36
  • @SethMW So you are saying that even if a calculation is specific to a particular view it should go in the business logic layer even if it is purely presentational? Does that not violate separation of concerns? – Louise Eggleton Jan 22 '14 at 12:39
2

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 a String in format 2 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).

trailmax
  • 34,305
  • 22
  • 140
  • 234
1

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

Yes, Not only one time used calculation, but also calculations which are only used in presentation should go into Presentation layer itself. You business layer should be transparent to business needs and requirements. What you can do is create simple utilities or extensions folder and place all the most commonly used presentation layer calculations in there and reuse them.

if I can generalize a calculation and use it more than once it should go in the BLL,

Not exactly, if that calculation has got business relevance and importance, then it should go into BLL. Or else it should stay at presentation level itself.

ramiramilu
  • 17,044
  • 6
  • 49
  • 66
1

In my opinion is better to do all business logic at one place and divide your business layer vertically (i.e. more granular service layer classes) not horizontally (more layers). I think that it is not problem if some of your business logic is view specific as you are using it only on web presentation layer. Keep it simple stupid and not overdesign:)

Marian Ban
  • 8,158
  • 1
  • 32
  • 45
0

A generic function written as utility function and used in business layer should help. Let us hear from other people too