views:

27

answers:

2

The majority of the Application Architecture advice seems to advise strongly that only Presentation Layer should have access to HTTPContext (to promote loose coupling, decrease dependencies, increase testability etc).

So, how do people deal with Caching and Session? Very specific DataAccess and Business Logic knowledge is required to determine what items need caching to best benefit application performance. However, and an ASP.Net web application, access to these is provided via the HTTPContext.

One option would be to create a CacheFactory and a SessionFactory, and an ICache and ISession interface - and then somehow use DI principle to pass and ISession and ICache to each method in the BLL and subsequently DA Layer that needs it.

Is this really what developers end up doing? Is there another, easier, way to deal with this?

Thanks for any advice.

+1  A: 

Personally, if I'm developing for ASP.NET (web) only, and I know the class libraries are only going to target the web, I have no issues referencing System.Web or any other assembly as needed. Sometimes practicality should come first.

On the other hand if you know, or are unsure if the BLL, DAL or other layers may be reused in a client-server or other environment, you may need to look at using a more flexible approach such as a session handler interface, etc.

The main thing is you clearly understand what best practice recommends. At that point you can make rational decisions about what should apply to each project or situation. It won't always fit like a glove.

KP
A: 

In my experience caching is done ata certain layer - and what you're caching applies within the scope of that layer, so:

  • You might cache data in the DAL so that the DAL returns it from memory and not by hitting the DB again; so here we're caching "raw" data at the data level.
  • The BL might cache similar data (say POCO's) - in other words "logical" data that has had BL applied to it; so here we're caching BL data in the BL level.
  • Your UI might cache (you guessed it) information that is built at the UI layer - liek a presentation of data as a webpage, XML, etc.

When you look at caching, as the architect / designer of the system you'll make decisions about what things are worth caching, generally this will be driven by a need to balance:

  • Performance needs to hit a specific target.
  • What time (and cost) options you have.

Assuming we're caching to increase performance, you'll want to analyse your system and identify the bottlenecks that need to be removed or avoided - the first pass of this analysis should at least identify which layer to focus on first.

Another thing to consider is that the more you can cache closer to the consumer - the less overall processing there is that needs to occur; in otherwords, if you can cache at the UI layer then the BL and DAL layers won't even get a look-in (you won't need to add caching there).

At this point I want to ask you what exactly it is that you're trying to achieve.

While everything I've said is true (as far as I am aware) it's all based on the assumption that we're delivering "vertical" slices of the systems functionality (like "creating an invoice", "adding a product" etc); there's another model you can apply - the cross-cutting concerns model.

Think about something like logging - every part of you system (UI / BL / DAL) should be able to log system events; my favourite tool for this is the MS Enterprise Libraries (MSEntLibs). When I work with them I consider them to be a "black-box" - a self contained unit. I (by choice) have no idea how they are architected - the thing that is important is that they are isolated and have dependencies which are relativly easy to manage.

The MSEntLibs can log to a database, but if I call an MSEntLibs logging method (to log to the DB) direct from my UI (and skipping over my BL) I don't care.

So depending on what you're trying to do the right anmswer will either be:

  • Simply identifying what needs to be cached at letting the appropriate layer handle it.
  • You don't need to try using DI to pass stuff to you BL at all - a cross-cutting black-box component might be appropriate?
Adrian K