This post originated from an RSS feed registered with .NET Buzz
by Scott Hanselman.
Original Post: A reminder on "Three/Multi Tier/Layer Architecture/Design" brought to you by my late night...
Feed Title: Scott Hanselman's ComputerZen.com
Feed URL: http://radio-weblogs.com/0106747/rss.xml
Feed Description: Scott Hanselman's ComputerZen.com is a .NET/WebServices/XML Weblog. I offer details of obscurities (internals of ASP.NET, WebServices, XML, etc) and best practices from real world scenarios.
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.]