Board index » delphi » Re: Are your persitable objects crudy?
Joanna Carter (TeamB)
![]() Delphi Developer |
Joanna Carter (TeamB)
![]() Delphi Developer |
Re: Are your persitable objects crudy?2004-06-02 11:11:29 PM delphi170 "Bob Dawson" <XXXX@XXXXX.COM>a écrit dans le message de news: 40bdd947$XXXX@XXXXX.COM... QuoteI'd say rather than opinion is mixed (but feeling lonesome at the moment). Joanna Consultant Software Engineer TeamBUG support for UK-BUG TeamMM support for ModelMaker |
Shawn Oster
![]() Delphi Developer |
2004-06-03 02:30:37 AM
Re: Are your persitable objects crudy?
"Bob Dawson" wrote
Quote
Broker.StoreObject(SomeObject) then they are going to have to think about what that Broker object is and more importantly, have they initialized it yet with the proper Connection object (username, password, connect string) and is it connected? I feel even the app developer needs to be aware of the different levels going on in their application. Perhaps my need to create an OPF for legacy tiers has corrupted my wee nut but it is been nice being able to Load from one persistance mechanism to Save to another, without having to swap out Connection objects. I simply have two PersistanceBrokers to work with. Slainte mhath, Shawn Oster |
Shawn Oster
![]() Delphi Developer |
2004-06-03 02:37:24 AM
Re: Are your persitable objects crudy?
"Joanna Carter (TeamB)" writes:
Quote2. Write one persister or adapter class per BO class, where you are QuoteThe only other concession has to be some means of including the concept of working rather well for this project. I came across something you mentioned in one of your old articles about the lack of a friend qualifier in Delphi. I can really see how that would be useful for the ID. I dislike that the ID is read/write but then again without a friend qualifier there really is no other way to handle setting the ID of a new object. Shawn Oster |
Shawn Oster
![]() Delphi Developer |
2004-06-03 02:42:37 AM
Re: Are your persitable objects crudy?
"Hechicero" writes:
Quote
are very important. Right now I am handling those at just the database level. Each SaveObject method I have starts and commits a transaction on my Connection object. Any contained objects simply bump up the Transaction count and when it reaches 0 I do the actual physical commit on the database. Rough but it works. Shawn Oster |
Shawn Oster
![]() Delphi Developer |
2004-06-03 02:54:31 AM
Re: Are your persitable objects crudy?
"Bob Dawson" writes:
Quote
persistence layer (PL) with no BO concept, and the mapping layer is owned by the PL you must be mapping it directly to the meta-data? It'd be interesting to see all those pieces working together in a small example. I like the concept. Quote2. it is possible, once passage to the persistence layer has taken place, what private data people are needing to get at via RTTI/reflection. Of course I am just dealing with client information, addresses, phone numbers, status codes, etc. Sorry for the double response on this, I am the type of bloke that reads magazines backwards and I tend to reply that way as well. Got over eager and hit sent *grin*. Shawn Oster |
Bob Dawson
![]() Delphi Developer |
2004-06-03 05:37:08 AM
Re: Are your persitable objects crudy?
"Shawn Oster" wrote
Quotealmost too easy in my eyes. If they have to write You can make a choice available without losing default behavior. IOW, your case of QuoteLoad from one persistance mechanism to Save will route to the normal data provider for that class, but myObj.Save('Alt_Named_dbRole'); or myObj.SaveTo('Alt_Named_dbRole'); allows redirection under programmer control. You can build the persistence layer to accomodate an array of persistence handlers without forcing the user to juggle them manually. IMO app programmer intervention in persistence routing should be an exceptional need, not a standing requirement. bobD |
Bob Dawson
![]() Delphi Developer |
2004-06-03 06:15:04 AM
Re: Are your persitable objects crudy?
"Shawn Oster">
QuoteAt which point I assume you do all your mapping on the information, and IPLPersistable, which acts somewhat like Joanna's attribute collection in being able to support a run-time discoverable array of properties/values. the broker object in the line broker.SaveObject(Identifier, Persistable) is really a broker, not a persistence handler--it evaluates the Identifier package and routes the call to the appropriate connection. QuoteSo far I haven't had to worry about getting at any information that isn't into property getters/setters that you don't want a db load to hit. For example, --in order to assume mfg state 6, a product must be in state 5 --on any processing state change, an object must spawn a 'process complete' record for the previous state. --additionally on entry to state 6, an object will spawn a process 6 queuing item --process change events are accumulated by the object and saved whenever the item saves How does the db load a process 6 item if it has to go through this logic? Quotecourse I am just dealing with client information, addresses, phone bobD |
Marc Rohloff
![]() Delphi Developer |
2004-06-03 06:51:03 AM
Re: Are your persitable objects crudy?
On Wed, 2 Jun 2004 08:38:23 -0500, Bob Dawson writes:
Quote<Aside> Quote
mechanism. It also means that your BO objects have to implement non-business code and are more tightly coupled to the business layer. After Save and Load would you add Refresh, Delete. Where do you stop. BO.Edit, BO.SendByMail, BO.Print? Marc Rohloff marc rohloff at myrealbox dot com |
Phil Shrimpton
![]() Delphi Developer |
2004-06-03 07:39:04 AM
Re: Are your persitable objects crudy?
In article <40bd68fb$XXXX@XXXXX.COM>, monocularjack@change-
haute-to-hot.hautemail.c0m says... Hi, QuoteACustomer.Save -- Discover a lost art - play Marbles May 2004 www.marillion.com |
Bob Dawson
![]() Delphi Developer |
2004-06-03 08:12:01 AM
Re: Are your persitable objects crudy?
"Joanna Carter (TeamB)" wrote
Quote
bobD |
Bjørge Sæther
![]() Delphi Developer |
2004-06-03 04:01:32 PM
Re: Are your persitable objects crudy?
Bob Dawson writes:
Quote"Bob Dawson" wrote ...is a convenient one, no doubt. But - it introduces a coupling that one doesn't need. Coupling is the enemy of reuse, IMHO. Do we need "Business Object" as a term in the OPF ? No, not really. The BO is a BO because it may a) be stored and retrieved, and b) Be used with controls, reports, etc.. The fact that it represents something related to the user's business rather than some internal technical mumbo-jumbo isn't really important. What *is* important is that the object is part of a data structure that is the *User data*, distinguished from various kinds of system data, user settings, etc.. It may also be convenient to distinguish between "Register data" and "User data", where ZIP codes & Customer tables may be an example of the first, while Invoice data belongs to the latter. It doesn't *need* to be organized that way, but it may be convenient to some applications. And typically, if there is differences between the handling of "Zip codes" and "Invoice lines", it is about their place in the implementation model more than whether they classify as "Business Objects" or not. The exception to this is possibly the validation part. This has to do with the object being editable or notrather than having anything to do with "business". At application level (hence, controlled by user actions) one decides the storage parameters; selecting a database, choosing a filename, etc.. To make the BO.Save; work, one must set the properties of the persistence layer so that the 'Save' method gives the desired result. This is of course possible, but the model isn't all that obvious. One may want to do a whole lot of different things with modified data, and a lot of rules and options may exist. It leads to an extremely stateful application, with a lot of "indirect" logic. IMHO, what you *do* need to "bury in a black box" is the following: - Coupling between editors/controls and edited object. - Storage of object into desired media. That is, there may be special cases where you need to write the entire storage stuff for just one application's sake. ...even a plain thing like the 'New Object' functionality may involve a lot of specialized stuff, and one doesn't necessarily want to bury this down in the OPF. The control question could be: "When do you write a call to BO.Save; ?" - it will IMHO lead to the answer: "Hardly ever." This is more typically an indirectly invoked operation. E.g. when a grid line looses focus, or a modal editor window is closed. Rather, it is some kind of available event - "Object editing finished" - that the OPF needs to route somewhere. I don't want to pepper my code with 'BO.Save;', I want another kind of coupling between controls/BO/storage. And - I have seen that it is as important to leave flexible the things that typically change between applications, as important as having implemented all that is general. -- Regards, Bjørge Sæther XXXX@XXXXX.COM ------------------------------------- I'll not spend any money on American Software products until armed forces are out of Iraq. |
Bob Dawson
![]() Delphi Developer |
2004-06-03 08:41:44 PM
Re: Are your persitable objects crudy?
"Marc Rohloff" wrote
QuoteI think that this would warrant a UI Manager just as we have of what they called it) considered both requesting BO type and security context in choosing the appropriate editor to return. bobD |
Bob Dawson
![]() Delphi Developer |
2004-06-03 09:07:39 PM
Re: Are your persitable objects crudy?
"Bjørge Sæther" wrote
Quote...is a convenient one, no doubt. But - it introduces a coupling that interface--not a class level coupling. And can anyone claim that their OPF makes no demands whatsoever on what it understands? My OPF requires that objects to be saved be able to produce a specific IPLPersistable interface--but they needn't implement it personally. Since taking any arbitrary object and inroducing it to the system would at minimum mean introducing an adapter that could accomodate this, it seems a small addition to make that adapter into a wrapper class that supports a Save call. I'm not arguing that one _has_ to provide direct persistence methods on persistable objects, just that it is convenient, preserves OO class containment, appears 'natural' for a user, and with a bit of work can be just as flexible as forcing the app programmer to submit the object the framework manually. QuoteThe control question could be: "When do you write a call to application logic, usually if not always in response to direct user gesture." Unless the application programmer writes .Save, it doesn't happen. The only qualification to this is that objects may own collections of objects, so for example the line Order.Save will save the Order object, any dirty LineItem objects owned by the order, etc. Put another way, saves are atomic over object sub-hierarchies. bobD |
Joanna Carter (TeamB)
![]() Delphi Developer |
2004-06-04 05:48:13 PM
Re: Are your persitable objects crudy?
"Bob Dawson" <XXXX@XXXXX.COM>a écrit dans le message de news:
XXXX@XXXXX.COM... QuoteSince taking any QuoteActually this is a substantial philosophical difference. My answer is "The but surely the BO should not know that it can be saved either? Therefore the only way of invoking a 'save' is for the application code to link the two together and perform the required action. Since developing my MVP framework further, I now use the Model to look after the CRUD of objects : ///////////////////// TOrderModel = class(...) class procedure Store(order: IOrder); ... end; class procedure TOrderModel.Store(order: IOrder); var tx: ITransaction; cust: ICustomer; lineIter: IOrderLineIterator product: IProduct; begin tx := TTransaction.Create; try tx.AddStoreObject(order); // this also adds internal lines to tx cust := order.Customer; cust.TotalOnOrder := cust.TotalOnOrder + order.Total; tx.AddStoreObject(cust); lineIter := order.Lines.GetIterator; while lineIter.Next do if lineIter.CurrentItem.IsDirty then begin product := lineIter.CurrentItem.Product; product.QtyReserved := product.QtyReserved + lineIter.CurrentItem.Qty; tx.AddStoreObject(product); end; tx.Commit; except tx.Rollback; end; end; ...this then gets called by a Command in an instance of the Model : procedure TStoreOrderCommand.Execute; var iter: ISelectionIterator; begin iter := GetCurrentSelection.GetIterator; while iter.Next do TOrderModel.Store(iter.CurrentItem as IOrder); end; ////////////////////////// This ensures that not only is each Order stored inside a transaction, but the related Customer and Products are also included in the same atomic transaction. QuoteThe only qualification to this is that objects may own collections of Consultant Software Engineer TeamBUG support for UK-BUG TeamMM support for ModelMaker |
Joanna Carter (TeamB)
![]() Delphi Developer |
2004-06-04 06:08:17 PM
Re: Are your persitable objects crudy?
"Bjørge Sæther" <XXXX@XXXXX.COM>a écrit dans le message de news:
40beff49$XXXX@XXXXX.COM... I could not divide your message to reply easily to a section, so here are some thoughts related to your message (vaguely) :-)) In this group we seem to do a lot of discussing about whether the BO should know about persistence and vice-versa. I have just started to look at porting my OPF to C#, which has caused me to think very carefully at how much of the Delphi baggege I need to take with me. C# supports the concepts of reflection and serialization. Therefore, if all classes can be inspected for their field values, we do not strictly need the Value (Attribute) framework we had in Delphi to give us this introspection, either for persistence or display. What is becoming clear though is that we still have to mark all fields that are persistable in some manner to stop us persisting fields that are only used for temporary working storage. Now we could dream up our own PersistableAttribute class that would allow us to mark fields as persistable, but if we use the SerializableAttribute already provide, then by marking temporary storage fields as NonSerializable, we have a ready made mechanism for serializing objects. Could we, in theory, write a custom .NET formatter that knows how to create SQL scripts and get the application code to simply serialize the object to the OPF or remote machine/process etc?? Because reflection/serialization is an expected part of any object, especially if we are using remoting, is this implementation hiding still such a big issue? What is more, we could also add attributes that define things like string length or decimal precision on each field. String length has always felt like a DB imposed limit and I still need convincing as to the best place to impose this limit as it also affects imput and validation. Decimal precision, IMO, is an important metadata item that rightly belongs in the BO class. Joanna Consultant Software Engineer TeamBUG support for UK-BUG TeamMM support for ModelMaker |