This post originated from an RSS feed registered with Agile Buzz
by James Robertson.
Original Post: Restore O/R Framework
Feed Title: Cincom Smalltalk Blog - Smalltalk with Rants
Feed URL: http://www.cincomsmalltalk.com/rssBlog/rssBlogView.xml
Feed Description: James Robertson comments on Cincom Smalltalk, the Smalltalk development community, and IT trends and issues in general.
John Aspinell, longtime (1992) Smalltalker. Started this project in 2000, turned commercial in 2001, released by fall 2001.
O/R Frameworks he's known - TopLink, developed others on own. Considers TopLink is great, but heavyweight for his needs.
Persitency is not free, even with an OODBMS
Issues - deepCopy. Copying an object model requires thought. You don't need everything, but what do you need?
Relational DB's do have some advantages
Define the DB yourself? It's a luxury and a responsibility. Duplicates a lot of effort. You end up maintaining not just the Object Model, but also the db schema.
How did he get to ReStore? Went from large clients and large systems to smaller clients and smaller systems. Changed from working with VW, VSE, VA to mostly Dolphin. Why Dolphin? Mostly low cost, along with the tight Windows integration. In short, Dolphin = VB for Smalltalkers. In other words, it's fully replaced the slot Smalltalk/V was in before Digitalk got stupid.
What other possibilities?
Binary Storage (BOSS equivalent)
OmniBase
OmniBase got the "where's my data?" question - so relational db's gave them a warm fuzzy. Also leverages customer's existing investment in tools like access, Oracle, SQL Server (etc). Also makes data visible to stock reporting tools. Made things flexible (Just add ODBC!). Got transactions and security and querying "for free".
OODBMS
Transparency
Object Identity
RDBMS
Querying support
Visibility
Wanted minimal impact on ST work - support agile development, reduce duplication of effort, did not want to make refactor/redesign a feared activity because of the db. Wanted Collection support (transparent). Wanted to not require SQL knowledge by developer. Wanted to be generic (not tied to a specific db).
What about existing databases? Was not aware of GLORP when he started.
Technical side of ReStore - pretty standard
Classes map to tables
Inst vars map to fields
Proxies wrap persistent objects
Identity maintained by
Single, Unique ID per object (row)
System Generated
Invisible to client objects
used by all foreign references
Not required to subclass from a specific class
SSWRestore - main broker
handles all db interaction
caches persistent objects
manages transactions
Transactions
Handle all db updates
Work with proxies to track changes
single level (not nested) - something of a limitation
Strong support for update clash detection and conflict resolution
Proxies knows the class and id it wraps. Asks ReStore for its object on demand. When referenced it adds self to current transaction. Uses #become to become the wrapped object. Pro - very fast. Con - needs tidying up (Dolphin become is two way).
Using ReStore in an application
Define the classes you want to persist. Avoids relational terminology. Specify the class of object held in each inst var to be persisted. Can be a base class or a collection.
Many to many in relational terms. Collection stored in an intermediate table. Will be created and then automatically given a name (like PERSON_FRIENDS). Inheritance - simple support. All classes in a hiearchy share a single table. Controllable bu subclass or superclass. System column specifies the class. Pro: Single query searches all subclass. Con: Redundant fields. Some wasted space in the db. On the other hand, disk space is cheap.
Create the DB. Add classes to ReStore. Synchronize with the db.
This creates the table schema, without adding any actual data. It's now ready for use. Tables created from class specifications (a method). Tables created if they don't exist, if it does exist, it will compare and possibly update the structure.
reStore evaluateAsTransaction:
[johnsmith := Person new
firstName: 'John;
lastName; 'Smith';
pets: (OrderedCollection with: (Dog named: 'Rover'));
storeIn: reStore].
That does the transaction to update the object in the db. When the transaction commits, all the relevant SQL generated and fired.
At this point there was a lively discussion of the proxies, and the collection interfaces being used. Pointed out that collections need to be homogenous - heterogeneous collections are a problem. It's a limitation based on the static typing in the db. This may be addressed in future.
Querying the database - What is a database? A collection of tables. What is a Table? A collection of Rows. What's querying? Searching db for objects matching a certain criteria. Querying in ST uses #select: and friends.
allPersons := aRestore instancesOf: Person.
Answers a virtual collection of all persistent objects. Understand #select:, #reject: (etc). Only brings objects into memory upin query at ST level
End up being able to use mostly normal looking Smalltalk queries. Blocks are parsed in a special parsing object to create SQL (there are some limitations). Traverses messages sent in the block via #doesNotUnderstand: Builds up a map of tables, columns, joins, and conditions. Translates to SQL. Some of this gets ugly in code (system, not app)
and so on. Also an #addAll: that can merge results of a collection query. Also virtual. Other virtual collection methods: #asOrderedCollection, #asSortedCollection: [] - answers a real collection. #size, #isEmpty - issues a COUNT query.
Future Plans
Convert to other Smalltalks (VW in particular)
Integrate with the RB (catch class renames, etc)
Nested and Parallel Transactions
Relational integrity
Questions What about reverse engineering a db? - not now, maybe in future. What about storing partial classes into db? - does that now - based on the specification Cursors and Paging? - has a readstream that keeps track, likely needs a bit more transparency Any support for weak caching? - everything coming back is dictionary cached. The cache is all weak, not string Two way become on proxies - what if I have multiple proxy refs? - not a problem Collection faulting? - done differently, as one would expect Update/class resolution? - can be turned off. Each object has a version field. gets updated on write to db. Update looks for that in order to resolve, if fails, will rollback transaction - can provide a block to handle that (similar, sounds like, to BOSS schema migrations). Do you ask user, or the code what to do? - can be handled in code, with or without user interaction multiple db sessions? - multiple instances of the reStore object. This can support multiple transactions, through independent reStore objects. When rollback, object state is restored - yes. People note that the class resolution across multiple reStore objects could be an issue in web apps with multiple users in an image