Ultimate enterprise design pattern for 3 tiered apps

T

timasmith

So, I feel I am close here is what I have so far.

Goal: Database driven selection of controls on forms
Goal: Business rules only aware of interfaces
Goal: Presentation layer only aware of interfaces


Database Table Person: Name, BirthDate, Gender, CreateDate, CreatedBy


Value Object:

public class Person {
private String name;
private DateTime birthDate;
private int gender;
private DateTime createDate;
private int createdBy;
}


Business Layer Object:

public interface IPersonModel {
public boolean isTeenager();
public boolean isMale();
public boolean isFemale();
}


Presentation layer Multi Column List control

public interface ITableList {
public int rowCount();
public Object getItemAtRow(int row);
public Object getValueAtRowColumn(int row, int column);
}
public interface ITableItem {
public Object getValueAtColumn(int column);
}


The most complex part is storing in a database table which fields on
the value object will be presented in the multi column list control.
It needs to be user friendly and maintainable.

One time I tried having each value object with a switch statement for a
unique number for each field. So the database contents and source code
are kept in synch e.g. 266 in the database means 'Person CreateDate'
and the value object returns that when implementing ITableItem.
It worked but relies on a code generator to make it all work.

This time around I thought I could keep a script in the database so the
user would pick the first column to be person.getCreateDate(), the
second to be person.getName() etc.
Using reflection I could generate on the fly which attribute will be
displayed in which column.

Anyone think of other options?

The other thing I need to change is it seems an unecessary dependency
for the value object to implement ITableItem - there probably needs to
be another class which does it and depending on the database values
pulls the data from the value object.

The same goes for the value object implementing the business rules.
While probably not too bad if it does, perhaps mapping the values to
something that does might work better.

Apart from the value object I am trying to anything else in all the
code knowing about fields which are only used for CRUD e.g. createDate.
CreateDate may never be used for logic - in my app - ever - so why
pass it around as business objects - better to only have things
implementing interfaces where needed.

What do you think so far?
 
F

Frans Bouma

So, I feel I am close here is what I have so far.

Goal: Database driven selection of controls on forms
Goal: Business rules only aware of interfaces
Goal: Presentation layer only aware of interfaces

Unless motivation is given for these goals, they're pretty useless,
IMHO. Don't over-engineer just because some book told you to apply
pattern ABC because it's soooooo great. A simple app should be a simple
app, not a complex framework build upon framework build upon... just
because you can.
Database Table Person: Name, BirthDate, Gender, CreateDate, CreatedBy


Value Object:

public class Person {
private String name;
private DateTime birthDate;
private int gender;
private DateTime createDate;
private int createdBy;
}


Business Layer Object:

public interface IPersonModel {
public boolean isTeenager();
public boolean isMale();
public boolean isFemale();
}

Interfaces are meant to define multiple-TYPE inheritance. If you're
never going to use an interface for more than one implementation, you
can as well use the class doing the implementation, and get rid of the
interface.
Presentation layer Multi Column List control

public interface ITableList {
public int rowCount();
public Object getItemAtRow(int row);
public Object getValueAtRowColumn(int row, int column);
}
public interface ITableItem {
public Object getValueAtColumn(int column);
}

Why re-invent the wheel? GUI controls should be grabbed from the
shelve, not programmed yourself, that's just a waste of time.
The most complex part is storing in a database table which fields on
the value object will be presented in the multi column list control.
It needs to be user friendly and maintainable.

why do you want to store in the DB which fields to show? After all, if
you want logic in those forms as well, that logic has to know what's on
the form to do something.

FB


--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
T

timasmith

So I guess I could have qualified the project but I dont see the
relationship to the design

a) This is a large project - tens of thousands of requirements
b) This is an extremely complex domain - not a store front or banking
app...
c) This is regulated and must be executed under design control,
traceability etc.

So I hardly would say Presentation being unaware of business objects is
useless... and I considering the complexity of the domain it is
*impossible* to determine all the data elements required to capture on
forms.

Forms which capture custom content only for a single site should not
(can not) be aware of the content. Events and data entry rules can be
executed by custom scripting specific to the site implementation.

The interfaces I refer to would be used for > 100 objects.

The controls need to be stored in the db so the users can choose which
to configure on the forms.
 
N

Nick Malik [Microsoft]

Hi Tina,

I read your other response, so I saw that you are building an enterprise
system. However, I have to agree with Frans on some points.


So, I feel I am close here is what I have so far.

Goal: Database driven selection of controls on forms

Interesting. I would say that you need to have metadata (form display
control data) in the database to accomplish this. Not unreachable. The
site that Microsoft presents to some supply chain partners has this feature.
There are pros and cons to this design.

First, about the concept:
Page request comes in from. Authenticate the user.
Download a base page with controls and LOTS of javascript
The page asks for it's metadata.
Ajax Service sends metadata that reflects the user's authorization. Some
controls appear. Others do not.
The page asks for it's initial data based on the original request.
Ajax Service requests data for the page of the business objects
Business objects tailor the request with authorization information.
Database sends back only the rows and columns that the user has the right
to see
Business objects convert to an appropriate format for sending to the page
(*Don't assume XML*)
Ajax Service sends formatted data
Page script gets data and fills in the page
User performs manipulations and submits data
Ajax Service receives the data and decides if a data manipulation has
occurred. Calls appropriate business layer object to save changes.


Pros: You get a highly flexible interface. The site that I spoke of has
features that are available based on a large number of very narrowly defined
classes of partners. For example, very large partners in China may need
some things that very small partners in Argentina do not. Microsoft has
literally thousands of partners using these tools, and they are not a simply
heirarchy. In other words, some partners work with other partners. We
offer tools to multiple points in the supply and distribution chains.
Therefore, it is sometimes appropriate for a company to see a small amount
of the data of another company. Auth/Auth is very important on a row-by-row
and column-by-column basis. This also gives us a LOT of flexibility in
building many different types of apps, all using this same pattern. By
developing common tools that can be used by each of the web-part
applications, we reduce the need for overhead on each application, and
reduce the cost and error rates of small changes. We have apps that assist
with order management, inventory management, supply chain controls,
invoicing, and financial adjustments under this design. That's a pretty
wide set.

Cons: This is a lot of engineering. Most of the existing controls require
some extensions to use this pattern (we extended existing controls rather
than wrote new ones). This may be appropriate if you have 50 engineer-years
that you expect to expend on your sites. We do. I don't know if that
applies to you. This mechanism also has difficulty being performant. The
MSN Live site experienced some difficulties early on with performance, and
one of the biggest factor turned out to be the XML (the 'X' in Ajax). For
some systems, switching the data transfer format to JSON has had some
success in speeding up the site. My suggestion: create a working prototype
with a grid that runs end-to-end through your proposed stack and put in on a
database and run it for the users to see. Our prototypes were end-to-end on
the process parts, but were shell apps when it came to working the stack, so
we didn't see the performance impacts until later than I would have liked.
Goal: Business rules only aware of interfaces

Not sure if I agree. If you mean: business rules are applied consistently,
in a carefully constrained way, and defined in a way that allows them to
change with a minimum of recoding effort, then I agree. If you are
implementing that goal by applying the business rules only to data that is
represented by a messaging contract, then I may agree, depending on the
rules. If you are saying that this particular implementation is 'ultimate'
or should be used by all apps, then I disagree. It is OK to have multiple
tools in the toolbelt. Just because a hammer works, that doesn't mean I
discard my screwdriver.
Goal: Presentation layer only aware of interfaces

If you change the word 'interfaces' to 'messaging contract' then I'd
understand and agree. As it is, I worry a little. If you mean 'interface'
in the OO sense, then you are sharing class, not contract, and that is the
opposite of SOA-based patterns. Perhaps you meant 'contract' and not
'class'?
Database Table Person: Name, BirthDate, Gender, CreateDate, CreatedBy


Value Object:

public class Person {
private String name;
private DateTime birthDate;
private int gender;
private DateTime createDate;
private int createdBy;
}

This is going to be hard to do if the ability for a particular column to
appear, based on metadata, is database driven. I'd suggest a more generic
DTO (Data Transfer Object integration pattern), like a .Net DataSet.
Business Layer Object:

public interface IPersonModel {
public boolean isTeenager();
public boolean isMale();
public boolean isFemale();
}
OK, as long as you are handling the situation where some method's values are
undefined since the underlying data may not always be available. Not sure I
can see how these particular methods would be useful though. Perhaps you
were just be illustrative?
Presentation layer Multi Column List control

public interface ITableList {
public int rowCount();
public Object getItemAtRow(int row);
public Object getValueAtRowColumn(int row, int column);
}
public interface ITableItem {
public Object getValueAtColumn(int column);
}

If you are on the Microsoft platform, these capabilities are built in to the
ASP.Net controls out of the box, with support for a broad array of browsers.
Please avoid writing 'yet another set of controls' if you can. MS released
a set of Ajax controls this year that are pretty good. There are competing
sets of Ajax controls, as well as more traditional server-side controls, in
abundance. Please don't reinvent this wheel.
The most complex part is storing in a database table which fields on
the value object will be presented in the multi column list control.
It needs to be user friendly and maintainable.

Yes, this is a problem. In the portal I described above, we have created a
'metadata editor' to allow us to maintain the complex rules.
One time I tried having each value object with a switch statement for a
unique number for each field. So the database contents and source code
are kept in synch e.g. 266 in the database means 'Person CreateDate'
and the value object returns that when implementing ITableItem.
It worked but relies on a code generator to make it all work.

Yuck. This also has the problem of driving complexity into the display
controls.
This time around I thought I could keep a script in the database so the
user would pick the first column to be person.getCreateDate(), the
second to be person.getName() etc.
Using reflection I could generate on the fly which attribute will be
displayed in which column.

A generic DTO will take care of the column selection for you by returning,
in the data structure, the column names that are coming back and their
relative position. A control designed to work with the same generic DTO
will be able to consume that data with minimal modifications. This is a
better route from a standpoint of testability and Time To Value (TTV).
The other thing I need to change is it seems an unecessary dependency
for the value object to implement ITableItem - there probably needs to
be another class which does it and depending on the database values
pulls the data from the value object.

A generic DTO (Data Transfer Object) removes this need. Even if I assume
your design, I would definitely want to avoid passing the ITableItem
implementation all the way down the stack to the value object.
The same goes for the value object implementing the business rules.
While probably not too bad if it does, perhaps mapping the values to
something that does might work better.

IMO, value objects do not implement business rules... business objects do
and, for the sake of efficiency for set-based operations and network data
load, you can and should move some of those rules into the database layer.
Not in the value objects.
Apart from the value object I am trying to anything else in all the
code knowing about fields which are only used for CRUD e.g. createDate.
CreateDate may never be used for logic - in my app - ever - so why
pass it around as business objects - better to only have things
implementing interfaces where needed.

No reason to pass them around normally. I have occasionally seen fields
passed to the U/I and back that were not used by the presentation layer, but
were used instead for data synchronization and concurrency control. Those
are valid purposes. Passing the last date changed and the id of the person
who changed it could be factored out if you think it is better. I guess it
depends on whether you want to use the same objects for the audit system as
you use for the transactional components. That's a tradeoff. Your call.

I hope this helps,

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
--
 
R

Robert Martin

Goal: Database driven selection of controls on forms
Goal: Business rules only aware of interfaces
Goal: Presentation layer only aware of interfaces

It seems to me that you are looking for a meta-data approach. The
database, or some kind of configuration file[set] could describe the
fields to be maintained, and the controls that access them. Once you
have that worked out, these three goals become pretty simple to achieve.

In essense you will be creating a domain specific language for your
application. At first (according to goal #1 above) this DSL will
simply specify the controls on the forms, but I guarantee you that you
will find ways to start encoding business rules into that metadata.
This is not necessarily a bad thing, especially if the business rules
are volatile.
 

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

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,527
Members
44,998
Latest member
MarissaEub

Latest Threads

Top