Why you need to keep business logic outside your aspx page
It wasn’t that long ago that everyone who wanted to write a web application stuffed server-side code in-between markup tags (ASP, PHP). Or, conversely, used echo or print in server-side code to output html tags (Perl CGI, Java servlets).
While small applications by their very nature (being small and all) don’t have to scale or be portable, larger applications quickly became a nightmare to scale and maintain.
Over time, we’ve lived and learned and created better designs. Enterprise-class platforms such as EJB, JSF, and ASP.NET support n-tiered designs. The IT deities declared that the separation of presentation and business logic is an ideal we should all strive for.
There is, of course, middle ground. Few of us work on critical, real-time systems such as bank websites or stock trading centers. However, the guiding principles that make such enormous applications work give smaller applications a wonderful boost (possibly your wallet, too, if you get a reputation for lightning-fast sites). We can all benefit from following any of the guidelines the behemoths use.
I use those design principles for my code whenever possible. Even my smaller sites. The more I practice them, the easier they become. I am cultivating the habit of writing efficient, maintainable code.
For the types of applications I write as a programmer, the important parts of that article are:
- Loosely coupled
- Highly cohesive
- Partitioned functionality
- Aquire late, release early
How do I do this?
- I don’t embed logic in my aspx page. I put page-specific logic in the event handlers of the code-behind, and business logic in a class that the code-behind uses. This allows me to easily re-use the logic on other pages, as well as change it without needing to change multiple pages.
- I use strongly typed datasets (xsd files) that can be used on any of my pages. If you’re like me, you have drop-down lists that have the same set of choices on several of your pages (perhaps a states or counties list). I create an xsd for the list, and use the resulting Table Adapter to fill my drop-downs. This also lets me take advantage of caching.
- I use stored procedures for database operations. This lets me wrap things in transactions. If someone unplugs the server in the middle of a giant statement, at least it won’t only do half the work (it would be dropped, and therefore, never changed).
- I use resources such as files and database connections carefully. I don’t open them until I need them, and I close them as soon as I’m done with them. (I use caching any time I can to prevent repeated queries.)
Think of it like a refrigerator on a hot day. You want to make a ham sandwich. You don’t want the cold to get out of the fridge, so you open it, get your food items, and close it immediately. You make the sandwich AFTER you close the fridge. You don’t stand there and make it while you leave the door open.
Two other things I do to help performance that don’t totally fit with the above are:
- I avoid the overhead of constant boxing and unboxing by using Generics.
- I avoid the overhead of the disposing of tons of strings (which are immutable) by using StringBuilder, String.Join, and String.Format instead of the overridden + operator (which creates and abandons Strings all over the place).
As programmers, we need to constantly learn and improve. I’m always looking for more ways to improve my code.
Share your tips with me in the comments!


August 31st, 2008 at 5:05 pm
Hi,
Point one: you could use ASP.Net MVC instead of WebForms to avoid statemanagement. You’d avoid the hidden viewstate that per defaults saves a ton of data, especially if you’re using a dataset which is the beast of the beasts.
You could leverage inversion of control to further loosely couple your app.
WebForms also has some amount of overhead. It allows for inline SQL in the tags as well which is an abdomination.
It doesn’t generate to web standards.
Point two: They are nice syntactic sugar, but creates an anaemic domain model, if a domain model at all. It becomes harder to expand application further if it’s really big. It’s hard to layer on top of it; domain layers, that is, not infrastructure layers (i.e. not talking about n-tier). Read Eric Evans’ Domain Driven Design for more about this. Datasets are also all of nothing afaik and consume vast amounts of memory to be filled; imagine scanning the USA White Pages; yeah - let’s load it all into an adapter first! (dang!)
How would you extend that dataset without the use of Visual Studio? You can’t. It’s as simple as that. But they create a lot of code; and that’s LOCs that have to be maintained.
It may also hamper your ability to communicate with ‘plain old c# objects’, or DTOs and doesn’t provide any real abilities to extend your model. Web Services returning data sets are crazy! Imagine a caller in Python — good bye weekend, for that programmer then.
Point three: Stored procedures risk to transfer business logic to the nth/third layer, the database, and modify state without your application code knowing about it. They are also a pain to maintain because you can’t do any static code verification on them or update them with refactoring tools. They are also another place you have to change if you e.g. change your domain objects.
Furthermore, you can run transactions even if you’re not using stored procedures. The ACID principle works even if you’re running a big SQL statement or multiple of them.
Point four: You shouldn’t use caching unless you know it’ll improve the performance for the cost of the memory you are using up, but you can indeed perform the queries at the beginning of the request/operation you’re wishing to perform to avoid transmitting many times.
You could have a look at an ORM if you’d like to; it’ll help with the domain modelling.
String.Format, if used on fewer arguments than around a hundred (tested myself) compared to string concatenation similarly, doesn’t provide any benefit. Nor does StringBuilder for
August 31st, 2008 at 7:15 pm
Hey there,
Point 1: ASP.NET MVC has its place and is a great alternative to webforms for some sites. However, it is not a replacement. Note that it is not event driven and doesn’t maintain state (requirements for some sites). Here is a feature comparison chart.
http://bloggingabout.net/blogs/mischa/archive/2008/02/04/asp-net-mvc-vs-asp-net-webforms-vs-ruby-on-rails.aspx
Point 2: Your point seems to assume someone loading a huge amount of data. That WOULD be a bad idea. You don’t want to do that — that’s why you use stored procs and paging.
Returning a dataset from a web service would also be a bad idea, I agree. An xsd can autogenerate a class with minimal effort. Adding a Serialize method to the class takes about 5 lines of code. All our web services return real xml so the consuming application can be Perl for all we care.
As far as domain modeling and extending datasets, if I was working on VERY large sites, I’d be using a BLL and a DAL, not datasets.
Point 3: I don’t know about you, but I don’t want to recode and redeploy an application because a database change has been made. Using stored procs eliminates this problem. It also allows for the database guy to fine tune them while you work on coding. As for modifying state, code decently and it isn’t an issue.
It also lets you finely tune permissions to help protect your database in the event of a security hole.
Point 4: Using caching responsibly and eliminating string concatenation sped up several sites I’ve worked on. In one more extreme example, the page went from taking over 40 seconds to load down to 3.
You do want to look at what you’re caching, of course. Data used in drop downs, at least in my experience, doesn’t change much. I.e lists of the states, or counties in a state, products, colors, or other similar choices of things. Not the result of some huge query.
Thanks for reading and commenting!