Re: Long Life Objects



Responding to Timeisfire8...

I am getting hung up on the terminology here (e.g., "Dictionary"). It
sounds very much like you are trying to emulate an RDB and the
Dictionaries are just surrogates for table indices.


So I am. One of your other posts taught me the valuable lesson of
solving the problem without considering RDB persistence, which should
be handled in isolation. Before this I would drive the design from the
database and I now see how this is a poor approach. I suppose that the
reason I have unwittingly created an application RDB is because my
thought process for the implementation of the Use Case above, for
example, is:

1) I will need the Customer, Contact and Service(next day delivery)
objects for this problem.
2) All entities are persisted in my RDB using a surrogate key of type
int which is also used as the materialised entity's ID, i.e.
CustomerID = 87.
3) These entities are rarely updated but frequently read so I will
place them all into a Domain layer Dictionary at application start-up
using the ID for the key, i.e Dictionary<87, customer>.
4) I can now contain these Dictionaries in the application's start-up
object (Company) without hitting the RDB until a change is notified in
some way at which point I can refresh.

If I understand this correctly, your Dictionaries exist only in the DB Access subsystem. They support requests in the problem solution for particular Customer information and Contact information. The implication is that in the actual warehousing problem solution one deals with only one Customer and Contact at a time. So the Dictionaries are effectively a cache for the RDB.

Why do you want to use the Dictionaries as buffers in the DB Access layer? Is this a performance issue (i.e., read the DB once at startup and emulate it in memory to avoid individual seeks)? Is the application up 24x7 or heavily multi-user so that the same customers keep getting re-accessed and you wish to avoid redundant DB accesses?

The reason I ask is that an RDB is ideally suited to ad hoc queries and you could probably do individual accesses in terms of joins from the <encapsulated> DB access layer instead of providing your own dictionaries as a buffer in that layer. (More below on the possibility of this being CRUD/USER processing.)

Almost. Each Customer has many Contacts which are physical people.
Each Customer has many Addresses. A contact belongs to one Address.
ServiceCatalogue is spot on.

1
[Company] ----------------------+
| 1 |
| |
| R1 | R4
| |
| has | references
| * | 1
[Customer] [ServiceCatalogue]
+ customerID | 1
| 1 |
| |
| R2 | R5
| |
| has | organizes
| * | *
[Contact] [Service]
+ phoneNumber + serviceID
+ eMailAddress

So the only "address" is an eMail address string? (I assumed it was a classic mailing address composed of {street, city, etc.}.)

I'll make the assumption that you want to build this structure in memory once with all the customers and their contact into available for the session. The first thing I would point out is that if the RDB exists to service only this application, it will probably map 1:1::tables:classes. The structure is pretty simple and the identity is pretty explicit in the problem space so there isn't a lot of wiggle room for ensuring referential integrity.

Having said that, the relationships will be implemented quite differently. The RDB can provide indices that are essentially your Dictionaries. But they will use the explicit identity and that implies full table searches. In your application you have a lot more flexibility. For example, you can eliminate searches by using a secondary key of consecutive integers, as you suggest above, so that you have a simple array lookup to access a specific Customer via R1.

[Another advantage is that since OO relationships are instantiated at the object level, the scope of any searches is greatly reduced. For R1 that is not relevant because all Customers are in the set for a single Company object. But for R2 it can make a big difference because, given a customer, the number of members of the R2 collection will be much smaller than the RDB table entries that must be searched for a matching customerID.]

If you construct the structure in memory for the model above, you will already have the same structure to navigate that the Dictionaries provide in your DB access layer. The collection objects for R1, R2, and R5 will provide exactly the same services as the Dictionaries. The only difference between this structure and the RDB schema will be the way the relationships are implemented, instantiated, and navigated.

My point here is that if the problem solution naturally only accesses one Customer and Contact at a time AND their information is accessed on an as-needed basis from the DB Access subsystem AND for performance reasons you want to buffer all Customer and Contact information in memory, then you may as well just build the structure directly in the problem solution memory rather than in the DB Access subsystem. The access of individual Customers and Contact information will still Just Work in pretty much the same way it will in your Dictionaries.

That suggests that one can go directly from an RDB query to the model structure. All one needs is a factory object that knows how to "walk" the returned dataset from the RDB query to create the in-memory structure. IOW, it is quite possible that the DB access subsystem may be quite trivial and you might get away with a single object to construct the <one time, startup> query, submit it to the RDB engine, and hand the returned dataset back to a factory object.

[Note that a dataset is just a pile of data in a known format. So there is no substantive difference between it and a message data packet. So it is fair to hand the raw dataset into the problem solution as a message data packet. The fact that its format is defined by the RDB mechanisms is not relevant to the problem solution. So there is no implementation exposure. Even if the DB's dataset format changes for some reason, you can isolate that in the DB access by converting the new dataset format to the old dataset format so that the change is transparent to the problem solution. Then the old dataset format really is just a message data packet format. But I digress...]

So how does one get a Customer in hand? I'm betting that is supplied through the UI. (You can ignore everything below here if you get the customer in hand from some other object while doing other warehouse things.) If so, that user is probably not going to know the index of the customer even if it is in the RDB. (It would probably not be a very friendly UI if the user has to go to a separate listing to find the index for a Customer the user naturally knows by name.) That means you are going to have to search R1 by name anyway, just as you would search the DB Access Dictionary, or a Customer table in the RDB.

That brings me full circle to my questions about performance above. This warehouse application may be doing lots of other fascinating things, but accessing contact information seems like it is pure CRUD/USER processing. It also seems like ad hoc processing in that the user is going to provide an arbitrary name and you give back the Contact information that is in the DB. That is exactly what RDBs do best and you are emulating it in memory. If that is the case, I would be inclined to forget about [Contact] completely. I would just invoke a DB Access interface method like getContact(customerName, contactSelector) and let the RDB do its thing.

OTOH, if there is a reason why the whole structure must be in memory, one has to make sure the implementation of the R1 collection object is efficient for searches. [Or one has to deal with sparse arrays if an integer secondary key is in the DB. That's a separate problem and there are ways to ensure the secondary keys are always consecutive if one wants to go to the trouble.]

Normally anticipatory caching is an issue for the DB Access subsystem. That's because there are usually special decisions to be made about what gets cached. In your case, though, the entire structure is being cached. Since there is nothing terribly tricky about the mapping (in effect R1 and R2 just go from 1:1 relationships to 1:* relationships in the solution space), it seems more natural to just use the problem space model structure in the solution memory space directly.


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@xxxxxxxxxxxxxxxxx
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info@xxxxxxxxxxxxxxxxx for your copy.
Pathfinder is hiring: http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH



.



Relevant Pages

  • Re: Long Life Objects
    ... I enjoy reading your posts and understand at ... Dictionaries are just surrogates for table indices. ... solving the problem without considering RDB persistence, ... I will need the Customer, ...
    (comp.object)
  • Re: Relational database & OO
    ... It really doesn't matter to the time management problem solution whether the data is persisted in an RDB, an OODB, flat files, or clay tablets. ... So one could regard the DB Access subsystem I proposed as being a PSE from the perspective of the problem solution. ... I argue that the DB Access subsystem needs to deal with the particular persistence mechanisms that are at hand. ... Here is a basic example that you may find in a customer care & ...
    (comp.object)
  • Re: in need of a pattern
    ... over to a relational database. ... To deal with RDB access one just needs to raise the level of abstraction. ... That's how GUI builder tools exist; they provide identity mapping and external configuration data that allows the GUI screens to be initialized properly using data from the problem solution. ... If the interface is designed around the problem solution's needs for data, then changing the persistence mechanisms will not affect the problem solution because the interface will stay the same. ...
    (comp.object)
  • Re: Help! Difficulty understanding DB -> Object mapping
    ... Solve the customer's problem first and then worry about how objects in that solution will map into tables in the RDB. ... If addresses are stored in a separate table, then the Customer_Address_ID should be in the Customer table, not the Order table. ... Product, not the OrderLineItem. ... access subsystem to properly access the RDB to obtain the information, ...
    (comp.object)
  • Re: Help! Difficulty understanding DB -> Object mapping
    ... > The first thing to do is forget about what the RDB looks like. ... > depends on the Customer identity, ... > Product, not the OrderLineItem. ... > To do that the persistence access subsystem needs to know more about ...
    (comp.object)