views:

302

answers:

3

Hi everyone i'm pretty new to the tiered development process. I'm currently developing an app and i have some basic questions regarding the best practices / architectural questions with todays technology. I'm going to be using WCF as the service layer. Note i'm trying to decouple things as much as possible. I don't want anything in the upper tiers to have to know about anything in the lower tiers which is one of the reasons i don't like LINQ TO SQL or the entity framework.

1) What is the best way to pass data between the tiers? I know either a dataset or a datatable would be easy but i wouldn't think passing this bloated data structure between tiers would be the best solution. Also debugging would be harder if the datatables / datasets were large. Would maybe an array of POCO objects be the best solution or is there a better way?

2) The next question is a little trickier. A lot of applications will have a bunch of different views of the data. You might have multiple reports, a variety of datagrids, and maybe a chart or two. How do you go about designing your data tier for this? Do you just design a a "Get" type function for each table and then try to combine them into useful views for say a grid or a report in your buisness layer or do you have a specialized function for each view you need in the buisness layer.

To be honest i don't like either solution. If you decide on specialized logic per view then you would need to create a POCO object (assuming your going to be returning an array of POCO objects) per view. If you decide later you need to add more columns to one of the view then you would be breaking the existing code (because your changing the interface on the POCO). If you decide to return a view of each table and try to combine it in the buisness layer than that could get REALLY messy. TSQL has joins for a reason :). Also you could possibly be returning a lot more data then you need depending on your design which would be inefficient.

I have some more questions but i will save that to later. I don't want this post to become to large :)

Ncage

A: 

I think you're missing a bit with the idea of not wanting the data tier to know anything about the business or UI tier. In an ORM tool (LINQ to SQL, for example), the properties of your entities are determined by the data. There's really no reason not to do this. Having strongly-typed entities is not the same as having business/UI logic in the data tier, and is generally a good thing; how you get there is up to you.

I ALWAYS advocate using a strongly typed component to pass data around as opposed to a general purpose repository like a DataSet/Table/Row/View/etc.

Perhaps you could expand a little on what has drawn you away from this approach?

Adam Robinson
Think about it this way...if your designing your system like that then you will have to reference your data tier in both your buisness tier, and client tier. Is this a good design? What if your break the interface on your data tier because you added a column to the database. You just broke every single client and also the changes will have to deployed to N Clients this is unless you don't return an anonymous type. Also you can not pass the datacontext object across tiers (WCF).
But what was mentioned was the UPPER not knowing about the LOWER, not the LOWER not knowing about the UPPER, which is what you're describing here.What, exactly, are you referring to as a "tier" here? Are these just different projects in a solution? Different processes on the same machine? Different machines altogether?
Adam Robinson
And, as an aside, you cannot return an anonymous type outside of the scope of its creation (in other words, you can't return an anonymous type (other than as an "object") outside of a function.
Adam Robinson
+2  A: 

These are very good questions. There are a lot of possible answers and a lot of possible architectures. I recommend you read a primer on the subject. Patterns & Practices has a very good one. It's free, comprehensive and discusses in depth the questions you are asking. No one architecture guide is perfect, but as a starting point, I don't think you can go wrong studying up on the basics.

JP Alioto
thanks JP I will check out the patterns and practices guidelines and see if they help me at all
+4  A: 

Good questions. Important stuff, this. In general, one of the best ways to approach tiered solutions is to look at Interfaces. Interfaces are a way of providing "chokepoints", which can serve several useful purposes.

Within tiered solutions, Interfaces serve to enforce the behaviours of the tiers; effectively by defining the set of behaviours that you expect, you decouple the implementation of the tiers. That is, so long as my tier implements the interface properly, the implementation is something that I don't need to care about at all.

I bring this up (and it IS relevant) because when defining your Interfaces, you will also need to define your data that is passed between the tiers. So when defining what needs to happen between the tiers, you end up defining what data gets passed; and at the same time, defining a strict set of data that is passed.

A relevant point here about the segregation is that no information about the implementation of a tier should be passed between the tiers. That is, by defining your Interface and being strict about the implementation, you should be able to make it such that the implementation of the tier can be reimplemented from scratch, knowing only about the interface, and can replace the other implementation with no problems.

Knowing this makes things simple; using Plain Old Objects will generally keep your Interfaces clean and proper; and it keeps your data structures from becoming bloated. It also serves the purpose of preventing the temptation of using some information about the implementation of one tier in another tier.

Of course, to do this properly, it's useful to take a long view at the problem to be solved; what are the set of operations that the user will want to do? Those operations generally resolve themselves into "verbs" which map well to Interface definitions which define the contract that the business objects will implement. The datasets your business objects will operate upon will define the set of views that you need to have on your database. In this way, you can cleanly maintain your separation.

McWafflestix
thanks for the reply. Yes i will definitely use interfaces because of WCF. In general i always use interfaces anyway. I hardly ever program directly against the objects i create. Interfaces are always the way to go. Do you think you should take the view per need approach or view per table. You also have to consider you have to send these POCOs back for insert/updates so your probably going to always at least need a poco for each table.
View per need. Absolutely. A View consists (or should) of the data taken from multiple tables anyway. I strongly disagree with the idea of binding objects to table definitions. Think of it this way; I don't need to know all of the vegetables that my supermarket carries to cook a meal; I only need to know the ingredients for the recipe I'm looking at. And where I get the ingredients is irrelevant anyway! :-) Does that make sense?
McWafflestix