passing objects through multiple layers

F

Frank Munsberg

Hey,

I guess you all agree that layering software is a good idea but I'm at
a point where I'm not entirely sure which route to go (read: stay wtf
free).

Imagine something like a three layered application with a database,
business logic and ui layer for simplicity.
Now if I got the principle of dependency injection and inversion of
control correct then each layer exposes some interfaces which the
layer below it has to implement. That way you can just stack them on
top of each other and also replace some lower layer with mocked stuff
for testing and whatnot.

Some data object from the database layer implements the
"ibusinessobject" interface from the business logic layer. The object
can enter the business logic layer and is treated like it is of type
"ibusinessobject" but what about passing that one up to the ui layer
so it can be displayed to the user?
The ui layer should not know details of the layers below it so it
can't just handle objects of type "ibusinessobject" since it doesn't
know the interface. Now if one sticks to the plan the ui layer exposes
some interface to the business logic layer and the "ibusinessobject"
interface needs to implement lets say an interface named
"idisplayobject" from the ui layer.

now the actual implementation from the database layer directly
implements "ibusinessobject" and indirectly "idisplayobject" from the
ui layer which sounds creepy to me.

Is it a good idea to put a layer next to the whole layered cake and
name it something like data object layer, put the interfaces for the
data objects in it and have every layer that needs to know use the
interfaces from there?
Then you don't stack a chain of interfaces on top of each other and
the whole thing stays a bit cleaner.
I'm not sure if this leads to future problems of some sort but right
now the idea looks appealing to me as it would even work for more
layers so the cake can get bigger. :)

Maybe you can give me your thoughts about that.

Greetings
Frank
 
J

Jon Skeet [C# MVP]

Is it a good idea to put a layer next to the whole layered cake and
name it something like data object layer, put the interfaces for the
data objects in it and have every layer that needs to know use the
interfaces from there?

This is *exactly* what I've done in the past - and it's worked well
then. That doesn't mean it will work well everywhere, of course!

I've written up a bit more on it in a blog post about a project I
started with a friend (which unfortunately hasn't gone anywhere,
mostly due to me taking on the book):

http://perfectprojectquest.blogspot.com/2007/03/of-layers-and-designs.html

Jon
 
P

Peter Morris

Hi Frank, I did this....


Object persistence framework
Business classes
Task flow (read: application layer)
GUI

Each being in its own DLL.


The user is never presented with a business object, they are presented with
a data object which may or may not be similar to one or more business
objects. For example I might ask the GUI layer to present the user with an
instance of GenericYesNo which looks like this

public class GenericYesNo
{
public string Message { get; set; }
public YesNo Answer { get; set; }
}

and the GUI will display it how it feels it should. In my case I have a
factory assembly for generating GUI based on the type, this prevents any GUI
controls being in the TaskFlow level which contains GenericYesNo in addition
to logical tasks.


So I might do something like this

JobSummary jobSummary = JobSummary.FromJob(currentJob);

the JobSummary class populates some header info + how many lines on the job
etc.


The GUI knows how to display a JobSummary, not a Job + Lines.



Pete
 
P

Peter Morris

PS: If you look at Ruby on Rails, MonoRail, Web Extensions they encourage
this approach by giving you named data in the form of IDictionary<string,
object> (ViewData).

Some people put business objects in there, but I disagree with that approach
:)



Pete
 
F

Frank Munsberg

Hi Jon, Hi Pete,

I messed the term "business object" up a bit maybe. In fact I meant
something like this GenericYesNo object, so something that just
contains some data and almost no logic.
The objects that contain business logic are somewhere inside the
business logic layer and the only thing that's passed through are the
objects containing plain data. No shopping cart that knows how to
commit its own order and things like that.

I'm not sure about the IDictionary approach. It sounds good in itself
but I guess it would give me headaches with NHibernate and its
Session.
If I just hide the data objects behind an interface then Nhibernate
works fine. I thought about using only simple types in the upper
layers but as soon as you get a data object with like 30 Properties
things would start to get really ugly.

I started to use the general concept in the thing I'm working on just
now as it took only a tiny bit of refactoring.
So far it has a good feel to it, and I'm pretty positive that it won't
blow up on me anytime soon. ;-)

Frank
 
P

Peter Morris

In my opinion the business classes shouldn't have access to these data
objects (I call them task parameters).

Instead the application layer should create the "task parameters" from
whichever business objects it sees fit, and when the updating in the GUI is
done the updated tasks parameters data should be used to manipulate the
business objects.


Pete
 
F

Frank Munsberg

I agree because the layering would certainly be stricter if upper
layers wouldn't know about the classes that are persisted by the DAL.
For the sake of avoiding problems I think having the same data object
type used in all of the layers is acceptable though. Of course the GUI
shouldn't mess with Id's and things like that.

Actually I thought about introducing some "task parameter" objects
that are used by the application layer to modify the persisted data
objects a while ago. Since I'm using NHibernate to persist things,
this would require me to write something like a little session
mechanism inside the application layer to match the task parameter
objects to their appropriate data counterparts used in the DAL since
the DAL is not really state-free due to the NHibernate Session.
If I relied on ADO.Net and things like DataSets I probably would have
ended up doing it like you suggest but it sounded just like too much
complexity back then.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top