Hi guys,
First, let me say that I was really hoping that the User Guide has a chapter for what I will ask in this thread. Ok, I understood basic concepts of GemStone. I understood it's basic classes and libraries. I understood the basic transactions concepts. I could even run my webapp from inside GemStone. Cool. But now... how do I persist for real in GemStone? How do I design my app API for storing, retrieving, editing, removing objects?
As far as I understand (please correct me if I am wrong), the first thing to know is that we should put our persistent objects somehow reachable from the user smalltalk dictionaries. Ok, as most OO DBs, GemStone works by reachability.
Second. Since the classes of my app are in those smalltalk dictionaries, and class variables are reachable from my classes, then whatever I store in class variables are persistent, right? (of course, unless I store there some objects that cannot be persisted).
Third...I would try not to enter too much in the transactions problem right now. I would like to keep using the GLASS as it comes for the moment... So...Ideas: 1) I keep a collection in a class side for each of my classes whose instances I want to persist. And I implement a protocol add: remove: etc that I put in Behavior. Them from my code I do: "Client addObject: anInstance"
2) I have one "MyAppRepository" class which is a singleton. The unique instance has a dictionary. From my code I do "MyAppRepository current addObject: anInstance". And MyAppRepository instance has a dict and operates for that dict (asking #class to the receiver and put that as keys...).
3) others... So, what do you do? My idea was to use 2) but reuse the repository class of Voyage and reuse also its protocol. Thanks!
Mariano http://marianopeck.wordpress.com _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
Administrator
|
Hi Mariano,
>> ... hoping that the User Guide has a chapter for what I will ask in this thread. I suggest you approach this question from a different perspective. If you were to build an application in Pharo or almost any other Smalltalk, how would you manage the objects? I doubt that either of those choices would appeal. The fundamental issue in any Smalltalk is how to hold references to the objects you want to keep in your image and how to let go those you no longer want. You can hold the root object in one of your classes, but that isn't necessarily an appropriate responsibility for the class. More likely, you would have a suitably named global to hold things, and possibly more than one. For example, you might have "customers", where each customer holds references to one or more accounts, and accounts hold references to transactions. That makes it difficult to find accounts or transactions without traversing the owning objects. So you might have additional collections holding references to these, as well. Of course, these additional collections have the consequence of blocking garbage collection, but they also create the possibility of indexed queries (in GemStone) for even faster searching. A single "database root" object makes sense. Multiple globals for different collections probably doesn't. (Refer to P. J. Plauger's article from c. 1989 on 0, 1, and infinity for some great modelling advice.) Having a single database root with a number of named collections is probably a better design. You can combine these approaches with some of your alternatives, such as having the global database root hold an instance of some class which manages the "database" aspects of your storage model (e.g., schema operations rather than application functionality). |
In reply to this post by Mariano Martinez Peck
Ciao,
In my GLASS system i create a ApplicationSystem class with some instance variables to manage the data i need for one specific application problem name Name of the environment rfrDb Dictionary for specific DataBase instance ( Costumer - Items ...... any with a specific dictionary of the relative keys) rfr..... rfrGlobal for global data relative to the specific Application After i define UserGlobals instances with the name of the specific environment. EnvironmentA -> anApplicationSystem EnvironmentB -> anApplicationSystem I create a WASession subclass DTRWASession with a 'applicationSystem' instance variable. When i open a new web session i understand from the pathString request the relative environment name ( EnvironmentA or Environment...... ) and then i set the aDTRWASession applicationSystem instance to the specific anApplicationSystem. A this time my superclass DTRDataBase ( superclass of all my database definitions ) in the methods intercept the session with the code: | session | session := WACurrentRequestContext value session. and return the specific dictionary ^ session applicationSystem rfrDbFor: className ( Costumer - Items ...... ) Or a specific other request for example : ^ session applicationSystem rfrGlobalFor: anSymbol. Can you understand the explanation of my solution? Dario
_______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
In reply to this post by Mariano Martinez Peck
From: "Mariano Martinez Peck" <[hidden email]>yes... yes... Yes, I'm assuming that your application is a web app and the best/simplest way to manage transactions is to abort before the request is handled and commit before the response is returned ... This disadvantage of this approach (and the GemStone model in general) is that "long running operations" may span multiple http requests and you may end up needing to "rollback data that was previously commited". Johah has a Database Abstraction Layer project[1] that includes some support for these types of applications ... Johan has also presented at ESUG about this project, so slides are available as well ... With that said, it is prudent to keep things simple at the outset... [1] http://ss3.gemstone.com/ss/DALi.html Yes ... the only caveat is that you should consider whether the add objects messages may be sent from multiple concurrent requests .. if so, you should use one of the Rc* collection classes that are designed to minimize the likelihood of transaction conflicts ... Here are a couple of useful references[2][3] [2] http://gemstonesoup.wordpress.com/2007/12/16/gemstone-101-transaction-conflicts/ [3] http://gemstonesoup.wordpress.com/2010/02/11/gemstone-101-short-features/ In GemStone I would avoid direct references to classes as much as possible (use names and a lookup instead). Classes in GemStone are versioned so it is very possible (and likely) that you will have multiple instances of a class floating around so it is not a good idea to hang onto them ... I don't think that you have to be fancy when dealing with persisting objects in GemStone ... I would recommend that you treat GemStone the same way you would treat the application in Pharo ... if it is natural to have a dictionary lookup by userid then store the dictionary along with the user class or in a a named global if that makes sense ... you don't have to have a central point of access as the entire Smalltalk object graph is persisted just like in Pharo ... if it is referenced it stays alive ... you can have a collection of users in one class variable and a collection of orders in another class variable and the orders can directly reference users without any need of worrying about identity or access paths or duplicate copies the object graph works just like smalltalk ... The one thing that you don't want to rely on is allInstances ... there is a tendency to rely on allInstances in client smalltalks to manage your objects and that is not a good practice in GemStone ... for large repositories, the allinstances operations can be very slow because of all of the disk i/o that will be involved ... so it makes sense to manage explicit collections of objects instead ... Dale _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
On 15 Nov 2013, at 18:51, Dale K. Henrichs <[hidden email]> wrote: > 2) I have one "MyAppRepository" class which is a singleton. The unique instance has a dictionary. From my code I do "MyAppRepository current addObject: anInstance". > And MyAppRepository instance has a dict and operates for that dict (asking #class to the receiver and put that as keys...). > In GemStone I would avoid direct references to classes as much as possible (use names and a lookup instead). Classes in GemStone are versioned so it is very possible (and likely) that you will have multiple instances of a class floating around so it is not a good idea to hang onto them ... +1 (read: got bitten by this in the past :-) This is a rule we apply: never hold on to classes as values in persistent objects. Instead, as Dale says, store the name and do a lookup when you need the class. If you hold on to a class, you must change the reference to the new class version manually when you upgrade the code. > 3) others... > > So, what do you do? My idea was to use 2) but reuse the repository class of Voyage and reuse also its protocol. We store a dictionary that is our 'persistent root' in UserGlobals: UserGlobals at: #MyDatabaseRoot put: (self createDatabaseDictionary) Johan _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
Free forum by Nabble | Edit this page |