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.]