N
Nigel Norris
Stuart,
One thing you haven't given any indication of is the scale or requirements
for the project. In practice I think that the appropriate answer to tackling
this sort of problem depends on answers to questions such as:
- How big a project is this?
- How important is flexibility in future?
- Do you need ot have the DAL as a full blown tier (distributable) or is it
simply an internal software layer?
- What is your testing approach - does the DAL need to be replaceable for
testing?
I'd probably come up with very different answers for a 100 user one-off
project than for something that was going to be the key business application
for the next decade. I think all projects should have some sort of
'complexity budget' - where complexity in this case is measured as the ratio
of 'infrastructure' code to useful application logic. As you add structure
(to reduce complexity in your application logic) you add complexity in extra
code. So it's a tradeoff of whether the benefit outweighs the cost.
So for a really simple project where the DAL was an internal layer I might
just break the layering rule and have the DAL create my busness objects. I'd
keep some separation between the database logic and the 'mapping' component,
per laimis's ideas, but I wouldn't worry too much about making it perfect.
Personally I'd prefer this 'impure' layering to having to have all my
business logic in static methods - that's too high a price to pay. I want to
have my business objects enapsulate data and behaviour, not separate them
out for artificial reasons.
If you want to stick to strict layering, there are two basic approaches:
- pass the data between layers in some simple shared structure, and copy in
the BL to the business objects
- use some form of inversion of control or factory class to pass the
necessary logic into the DAL to allow it to create business objects without
knowing about them
In the first case, use DataSets or custom-defined Data Transfer Objects.
This works well for remoting, as well.
The inversion of control solutions generally seem too complex for me - if
it's getting that complex then I'd be thinking of a full blown O/R mapper
instead of a DAL. However one simple variation that I've considered but not
used in practice is to use strongly typed datasets as the basis for the
business objects in the BL and pass in datasets to the DAL. In the style
'here's a dataset - please fill it for me'. The DAL works against simple
untyped dataset interfaces, but the dataset insfrastructure creates the
approriate strongly typed objects.
Good luck..
Nigel
One thing you haven't given any indication of is the scale or requirements
for the project. In practice I think that the appropriate answer to tackling
this sort of problem depends on answers to questions such as:
- How big a project is this?
- How important is flexibility in future?
- Do you need ot have the DAL as a full blown tier (distributable) or is it
simply an internal software layer?
- What is your testing approach - does the DAL need to be replaceable for
testing?
I'd probably come up with very different answers for a 100 user one-off
project than for something that was going to be the key business application
for the next decade. I think all projects should have some sort of
'complexity budget' - where complexity in this case is measured as the ratio
of 'infrastructure' code to useful application logic. As you add structure
(to reduce complexity in your application logic) you add complexity in extra
code. So it's a tradeoff of whether the benefit outweighs the cost.
So for a really simple project where the DAL was an internal layer I might
just break the layering rule and have the DAL create my busness objects. I'd
keep some separation between the database logic and the 'mapping' component,
per laimis's ideas, but I wouldn't worry too much about making it perfect.
Personally I'd prefer this 'impure' layering to having to have all my
business logic in static methods - that's too high a price to pay. I want to
have my business objects enapsulate data and behaviour, not separate them
out for artificial reasons.
If you want to stick to strict layering, there are two basic approaches:
- pass the data between layers in some simple shared structure, and copy in
the BL to the business objects
- use some form of inversion of control or factory class to pass the
necessary logic into the DAL to allow it to create business objects without
knowing about them
In the first case, use DataSets or custom-defined Data Transfer Objects.
This works well for remoting, as well.
The inversion of control solutions generally seem too complex for me - if
it's getting that complex then I'd be thinking of a full blown O/R mapper
instead of a DAL. However one simple variation that I've considered but not
used in practice is to use strongly typed datasets as the basis for the
business objects in the BL and pass in datasets to the DAL. In the style
'here's a dataset - please fill it for me'. The DAL works against simple
untyped dataset interfaces, but the dataset insfrastructure creates the
approriate strongly typed objects.
Good luck..
Nigel
Stuart Hilditch said:I did originally use interfaces in the DAL, but it resulted in so much
messy code (some of my object have 25+ properties) I decided that it was
far cleaner to simply reference the object from the ORL.
- Stu
John B said:Google Dependency Inversion Principle and Interface SegregationStuart said:Hi all,
I am hoping that someone with some experience developing nTier apps can
give me some advice here.
I am writing an nTier web app that began with a Data Access Layer (DAL),
Business Logic Layer (BLL) and User Interface Layer (UIL).
The problem I found with this was circular referencing...
My objects would be defined in the BLL, so let's say for example that I
want to instantiate a new BLL.Customer object in the UIL, and then run
Customer.AddCustomer() which would in turn pass the object into the DAL,
let's call this method DAL.AddCustomer(BLL.Customer myCustomer) which
would insert into the DB.
The problem is that the BLL needs to reference the DAL and the DAL needs
to reference the BLL (to receive the custom business object), hence a
circular referencing error. I understand that I could turn this custom
object into some sort of generic object[] or collection and pass it
then, or alternatively pass the method field values one by one (not
practical with 10+ values)
What I did was to create a 4th 'vertical' layer which I called the ORL
(Object Reference Layer), the purpose of which is to allow all other
layers to reference the same objects so they can be passed between
themselves without issues. The drawback is that for this to work
properly you need to have the objects themselves defined in the ORL, but
the methods defined statically in the BLL.
My question is this...
Is this good programming?
Obviously it would be ideal to have the object constructor and instance
methods declared in the same class, but I can't seem to get this to work
effectively any other way.
I would appreciate any advice.
- Stu
Principle.
I am by no means an expert but..
In the past I have created another assembly containing an interface that
both the DAL and BLL know about.
This interface pretty much only contains properties for all the db table
columns.
Thus, the DAL classes know about the interface and can interact with that
and the BLL classes implement this interface.
HTH
JB