Scott Hanselman

A reminder on "Three/Multi Tier/Layer Architecture/Design" brought to you by my late night frustrations.

June 1, '04 Comments [16] Posted in ASP.NET | Learning .NET | Web Services | DasBlog | XML | HttpHandler
Sponsored By

I was going over some C# code that was written for a non-profit earlier this year.  It was fairly typical code and that's what disturbed me so.  It consisted of a single ASP.NET Application with most of the work happening in the Page_Load.  Although there was only one database, the connection string to that database appeared in at least a dozen places throughout the code.  There were a few places where a SELECT * from WHATEVER occurred and they spun through a DataReader in order to set a boolean called "HasRows" to true. 

So, I had to do something.  I understand that not everyone cares, and that not everyone had (or chose to have) any formal Computer Science or Software Engineering academic life (not that there's anything wrong with that.)

Disclaimer: This post is just general advice.  I know that reams of paper have been written on how to design software, layers, tiers, services, etc.  This post is just to remind a few people that you can't have multiple layers until you start thinking about the responsibility of each layer - the contract and binding.  Life has hierarchies and layers and responsibility - and so should most software.

That being said, here's little reminder about layers of abstraction.  They are typically a good thing.  Remember though, that in "Scott World" (which is hopefully your world also :) ) a "Tier" is a unit of deployment, while a "Layer" is a logical separation of responsibility within code.  You may say you have a "3-tier" system, but be running it on one laptop.  You may say your have a "3-layer" system, but have only ASP.NET pages that talk to a database.  There's power in precision, friends.

  • The Presentation Layer: For the vast majority of programmers who are doing ASP.NET, your pages live for one reason, to present an interface to the user.  That is usually HTML/XML. (ya, ya, I know you might produce WML, CHTML, or GIFs with HttpHandlers but this whole post is a generalization)
    • Things your pages shouldn't know about: Your pages shouldn't know that a physical data store exists.  DasBlog does a lovely job of abstracting away the data store and presenting only an object model to the user.  Your ASP.NET pages shouldn't know about connection strings, Connections, Commands, or anything like that.
    • Things your pages should know about: Your pages should know about your Domain Model.  Your objects, your stuff.  If you're a librarian, I suspect you'll have a Book object.  Perhaps a Librarian Service that knows how to Get and CheckOut books.  He/She (the Service) no doubt knows how to Search for Books also. 
  • The Business Logic Layer: 
    • Things your BizLogic Layer shouldn't know about: Ideally your business logic layer shouldn't know there is a database.  It shouldn't know about connection strings or SQL.  It shouldn't know about much of anything except whatever format you choose to represent your objects in (preferably NOT DataSets.)
    • Things your BizLogic Layer should know about: It should know about business rules (This payment will need 5 days of lead-time to be paid, or that book can't be checked out by two people at once) but not the details of storage.  It might present public methods like "GetBookByISBN" or "CheckOutBook(Book b)" or "ReturnBook(Book b)."
  • The Data Access Layer: Depending on how "purist" you want to get, you can merge the DAL with the Business Layer.  At a minimum you should be able to perform CRUD operations.  Create, Read, Update, Delete.  Fundamentally most apps are just GETS of stuff and PUTS of stuff.  Keep it simple.  If your backing data store is XML files, or a Web Service or a Database, it shouldn't matter, and ideally your Business Layer (above) doesn't even know!  It knows there's a DAL to talk to, but it's all about responsibility.  If you are designing a layer, know your in's and out's and for Goodness' Sake know your responsibility.  If you don't, back to the drawing board until you do.
    • Things your Data Access Layer shouldn't know about: It shouldn't know about HTML, and it shouldn't know about ASP.NET.  It should avoid knowing about business rules that don't related directly to how the data is stored (like cardinality.)
    • Things your Data Access Layer should know about: It should know about accessing data in whatever form it's stored.  It might have functions like "InsertBook(string name, string isbn)" or "InsertBook(Book b)" if you don't mind it knowing about your Business Objects (I usually don't).  It should act as an Adapter between your Data Access Layer and your Data Store.
  • The Data Store: This might be a SQL Server; then you'll need CRUD Stored Procedures to ReadBooks, UpdateBooks, etc.
    • Things your Data Store shouldn't know about: Your Data Store shouldn't be generating messages in language.  That means don't have your Stored Procs generate English messages.  Sounds silly, but I've seen it before in the wild, so it bears repeating.  It's your Data Store's job to get data to the DAL, and little else. 
    • Things your Data Store should know about: Storing stuff.  'Nuff said.

This may seem overkill, but believe me, once you've done it a few times, you'll appreciate it when you come back to mess with the code in the future.  Remember also that much of this CRUD stuff can be auto-generated by CodeSmith or by Deklarit.  Please, do resist the urge to open up a SqlConnection from your next ASP.NET page.

Why should you do this?  Because of the 'ilities and because the simplest even-slightly layered design hides complexity. 

  • Flexibility: "The ease with which a system or component can be modified for use in applications or environments other than those for which it was specifically designed."
  • Maintainability: "The ease with which a software system or component can be modified to correct faults, improve performance, or other attributes, or adapt to a changed environment."
  • Reusability: "The degree to which a software module or other work product can be used in more than one computing program or software system."
  • Scalability: "The ease with which a system or component can adjust to changing load."
    [All these definitions are from the IEEE Standard Computer Dictionary.]

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. I am a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Tuesday, June 01, 2004 12:10:42 PM UTC
Dear Scott,

Thanks for your vision on web application architecture. I agree with all your points, but i don´t undestand exactly the reasons for not using datasets in your business layer.

Does it really make sense to use objects in web apps, if I create a customer object and use it in asp, this object wont persist through the requests. Why not directly use the dataset. Instead of objects wouldn´t it be better to be more serviced oriented?

Manuel
Manuel Lopez
Tuesday, June 01, 2004 5:40:29 PM UTC
Great post Scott. Thanks for saying what needs to be said.

I constantly spend more and more time on this same topic when doing developer training. If I even see the use of System.Data.SqlClient, or even System.Data in the presentation layer I make them go back and redesign. There's a place for that stuff and it sure isn't there!

Manuel, you don't want to use DataSets in the business & presentation layers because that requires that code to "know something" about the data. For example, when building the business layer I would have to know that the DataSet contains a field named "fieldX" ie: mydataset.Tables[0].Rows[0]["fieldX"] instead of the simpler myobject.ValueX.

-Ryan
Tuesday, June 01, 2004 7:53:48 PM UTC
Hi Scott, great entry. You point out what is lost on many coders. A great followup to this one (which is the "how") would be the "why" -- why seperate out layers, why not have the data store performing logic, etc...

Andrew Lance
http://www.livejournal.com/~andrewlance
Tuesday, June 01, 2004 9:24:35 PM UTC
Wonderful post Scott! A quick reminder of what goes where.

you say you dont like datasets, and while i agree, i dont care for them as i like the OO approach, you mention deklarit. Deklarit uses datasets :)

I actually am considering purchasing either Deklarit or LLBLGen Pro, i was wondering if you could comment on Deklarit?

Manuel Lopez:
Datasets are not all that great for web apps becuase they are very "heavy" and most of the time you dont need 90% the functionality provided by them. In a thick client (winforms) datasets are more useful for databinding, but this isnt really true for asp.net.
Ryan Hurdon
Tuesday, June 01, 2004 10:17:26 PM UTC
Nice post Scott. I'm hopping to get our dev group and dev efforts following those directives. Our mgmt is focused on quick-n-dirty code and believes that asp/asp.net is just to make the page look pretty, and that all business logic sould be in pl/sql. SOA is waisted breath. I'll keep nudging and hope for the best :)
Dwayne Nance
Tuesday, June 01, 2004 10:33:56 PM UTC
It can be perfectly reasonable to put the Business Layer on the DB side. For example, if your app is not going to be the only app directly accessing the DB (you're writing the .NET cleint and someone else is writing a GUI Java client), then it makes sense to have the Business Layer be either directly on the DB in T-SQL or PL/SQL or Web Services.

That said, C#/VB.Net/Java tend to be much better languages for writing business logic, IME.
Richard P
Tuesday, June 01, 2004 10:36:47 PM UTC
A very nice little intro piece to good application architecture. One of the reasons you see so many MegaTier applications is that there aren’t enough good examples for people to get into. It’s either presented at a high theory level, with a scattering of UML diagrams and pretty colored boxes (yours are very nice), or at such a detailed, it took us 9 months to just design this baby, level that it is overwhelming. What people need are *small* real-world style projects using many of these ideas that someone can take apart to understand with complete error handling and dealing with the issues you encounter when going from theory to implementation.

There are far too many 1 or 2 page articles on this is what you should do and this is generally how it should work and very few putting your money where your mouth is examples. Then of course you ask for examples from these authors and you get “oh well, it’s all proprietary” or “it’s not 100% done” or “it’s very specific to a single solution, and it’s massive”. All of which are completely valid but now you’re asking someone that needs to get a working project out the door in 3 months to reinvent the wheel based on a pretty image of the various tiers.

It's also surprising how little a CS degree relates to quality code and architecture on a consistent basis. Having worked with a ton of developers over my career I've really stopped caring or using that as any basis for good programming practices. Sad but true. Their lexicon of programming terminology is usually greater but ask to see a solid, working example of the Observer pattern (even after you explain what it is) and you have a 50/50 chance of getting something that works.

So… great article but where’s the meat for those that want to see that diagram in action? Would make my life a lot easier when we get junior programmers. Right now I get a ton of "but how do we really do this?". Something like Test-Driven Adventures in C#, but for 3-Tier apps.
Shawn Oster
Tuesday, June 01, 2004 11:56:58 PM UTC
Scott -- I love your work -- but I really wish your menus were on the right.

Your articles would become *much* more printer friendly.

and how cool are those XP-style icons in the image? "pure sex".

cheers
Leon
Wednesday, June 02, 2004 5:10:13 AM UTC
No worries, I just added a Print Specific Style Sheet. These pages should print normally now. Check out the results in your Print Preview screen.
Scott Hanselman
Wednesday, June 02, 2004 10:32:34 PM UTC
I agree... too many people have no clue what a multi-tiered software architecture is. At the end of my Senior Project, groups had to do presentations on their design, testing methods, risks, etc... so many of the groups went up their and said that since they have a client (web browser), a web server, and a database server, that they had a 3-tiered software architecture. I wrote "hardware architecture does not determine software architecture, code does" on so many evaluations.
Friday, June 04, 2004 1:59:32 PM UTC
You wrote:
It might present public methods like "GetBookByISBN" or "CheckOutBook(Book b)" or "ReturnBook(Book b)."

One might say these methods really belong to the DAL, not the Business Logic Layer.
Monday, June 14, 2004 7:58:48 PM UTC
I think I understand why the Book-specific methods are in the BizObject Layer, rather than the DAL. The DAL really just knows CRUD. Those Book-specific methods need to have some kind of business process knowledge to be implemented.

Having said that, there needs to be a relationship between the BizObjects and the DAL. In the example of GetBookByISBN, the BizObject layer eventually has to be able to ask the DAL for the results. This is where I am getting stuck.

My DAL has an interface that provides Retrieve, Insert, Update and Retrieve. Then, I can have whatever kind of data backend I want. I have a factory to create my DAL object for the Book. How do I then add the custom methods to Book, without having Book talk directly to the data layer?

I know this isn't the place for questions like this, but if you could point me to a good place for design-feedback questions, I'd appreciate it.
Ken Scott
Tuesday, June 15, 2004 9:48:46 PM UTC
Amen, brotha.

This practice is a little like test driven development, once you go there, you'll never look back. The nice thing about this type of app architecture is that you leave behind something 100% maintainable, and possibly extensible. Great examples of this type of architecture are found throughout Microsoft's newest .NET based technologies (SPS, Reporting Services, Microsoft CRM, Etc...).

Thanks for laying it out so plainly, Scott.
Saturday, June 26, 2004 4:31:46 PM UTC
I am joining the people questioning why not datasets?
They are perfectly suitable IMO - the only problem is transporting the dataset over the net, however even for this problem there is a cure.
And people, go with CodeSmith as this is the best you can get - full control over everything (this also mean you might have to create a template or two :-) ) and there is a free version avaialable!
Monday, June 28, 2004 6:32:13 PM UTC
Great post.
One question, if BLL should not, ideally, know the data access stuff - and perhaps, how or where the data is coming from - then does it make sense for the DAL to cover calling other webserives? Or perhaps there should be another layer between the BLL and DAL - in the traditional sense - that retrieves the data for the BLL whether be it from a webservice or a database?
Jiho Han
Monday, August 29, 2005 9:30:07 PM UTC
Hello! I was interested in your article. It is rather instructive.
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.