views:

91

answers:

5

I understand the benefits of three tier architecture ( for example, changing code in one layer doesn’t usually affect code in other two layers ), but I don’t understand why it would be bad idea for UI layer to ( in certain circumstances ) directly access the `data layer.

a) I can think of few reasons why UI should only talk to BLL layer:

  • this way UI developer doesn’t need to know details of DB schema, since BLL layer abstracts DB tables using custom objects.

  • also, often times BLL layer processes/validates the incoming data before passing it through to another layer

Are there any other reasons?

b) But if same developer is writing all three tiers, then are there really any reasons why UI layer shouldn’t directly access data layer (in cases where it doesn’t need the BLL layer to process/validate data)?

thank you

+4  A: 

As a database and server developer, I have a simple answer: you can no longer look in one place to see all of the database access, and database changes will now affect more than one module.

orbfish
Also, your BLL layer serves as a gatekeeper for the data layer. Even if it's the same programmer, people change their minds or forget their own design: the BLL layer can't enforce validation if there is code which bypasses it.
orbfish
Exactly, it's a dependency problem. And to expand a little, you really want to minimize the amount of code touching your database because bugs in this code can lead to very big problems: data loss and persistent invalid database state. These can be much worse than crash bugs in traditional programs. So you need to minimize the amount of code that is directly touching your database and really make that bulletproof.
bshields
"database changes will now affect more than one module." But isn't one of major benefits of using 3 tier layer arhitecture that changing layer L1 doesn't affect the other two layers, as long as L1's interface remains the same? Thus, even if we access DAL from UI layer, changing DAL layer shouldn't affect UI layer, as long as DAL's interface remains the same?
flockofcode
In my experience, whenever a change needs to be implemented, it will very often affect all 3 tiers: for instance, a new field requires changes in UI, BLL and DAL. In my opinion, "agility" (or "how hard it is to implement changes") should always play a major role in choosing a layer pattern.
tijmenvdk
+2  A: 

Security. The BLL should be accessible from the client, and only exposes the methods you want people on the client to use. How do you securely store the database connection string in the Client code?

Depending on the language and framework you use you can make the BLL methods only accept pre-authenticated calls.

I am assuming the UI is Client Application and not a website.

DaveShaw
»How do you securely store the database connection string in the Client code?«By client code are you reffering to the UI layer? But UI layer is also located on the server side, so how could database connection be compromised if specified in UI layer?
flockofcode
+3  A: 

If you leave the layers uncoupled you can switch out components like the database engine without recoding your UI layer. Likewise even if the middle layer doesn't have to process / validate data it can be used to retrieve additional data from other sources (other databases, network resources etc) without recoding your UI layer.

It's just a good practice to keep with. It allows you to alter your system to scale or adjust with minimal impact on the other pieces.

wlashell
"If you leave the layers uncoupled you can switch out components like the database engine without recoding your UI layer."But even if you access DAL directly from UI, you're still able to change the DAL layer (say switching to a new DB) without changing the UI layer?!
flockofcode
+2  A: 

Some applications are small enough that a n-tiered architecture is overkill. When you start working with larger applications (remember small application tend to grow into big applications) then it becomes important to:

  • Minimize the impact of change
  • Test your code

Most important is the ability to test your code without requiring a connection to a database thereby allowing you to truly isolate the object under test.

As for minimizing the impact of change, as your requirements change, your design will likely change. If logic and data access is scattered across your application, then small changes introduce significant risk (and additional testing effort).

Now if you're a one man shop and don't expect your software to grow in any significant way, then there's little need to prepare for it with a more complex design.

On the other hand, they're called "best practices" for a reason.

Ryan Emerle
+1  A: 

In the end this type of decision comes down to preference (obviously), but it is also a reminder that every architectural decision needs to be traceable to a certain purpose. Those purposes or requirements can have a multitude of backgrounds, ranging from business to technical, but the important point is that they should be there, for the simple reason that whenever you find yourself questioning specific details (decisions) in the architecture at hand, you can trace the motivation behind the decisions.

In doing architectural reviews, I often find a 3-tier UI/BLL/DAL architecture as you described, and very often for no other reason than "everybody else is doing it", "it is the Microsoft way", et cetera ad nauseam. It is a fine architecture (or layer pattern), but it is not the one-size-fits-all (since that doesn't appear to exist in IT anywhere).

A few questions that come to mind: where do the custom objects live that "abstract the DB tables" (quote), and to what level do you expose these? Are these DTOs, or objects from the BLL that are populated by the DAL? Does the UI know these objects (direct reference), or are they hidden by the BLL? Are objects in the BLL persistence-aware? What do your references between tiers look like? Drawing a high-level picture can help here.

Some reasons not to do what you propose have already been posted; while these are all valid, each objection can potentially be mitigated by a workaround (or 10). Given a greenfield situation, I actually prefer doing something along these lines, making the data access as (architecturally) lean as possible. I find that this keeps the solution agile and well suited to change when requirements shift (as they always do).

A few suggestions: if you are going to go forward with this, try to explicitly separate reads from writes (queries from commands, questions from transactions, choose your lingo). An alternative to linking the UI to the DAL would be to create a very thing Service layer (how's that for an ambiguous term? Actually, this is why I sometimes name this the "Operations" layer, for no other reason than to disambiguate) that can either grab the required objects directly from your data access layer, or invoke the business layer whenever the operation requires it. This way, you still define all your interaction between the UI and the underlying infrastructure in one way, but you can optimize each operation individually.

tijmenvdk