Collaboration: At the Extremities of Extreme
Jason Ayers share the observations he made watching a team of developers collaborating in real time on the same code base, pushing XP, pair programming and continuous integration to their extremes.
The content has been bookmarked!
There was an error bookmarking this content! Please retry.
Posted by Werner Schuster on Aug 06, 2007
GemStone has two object database products: one built for Java (Facets) and one for Smalltalk (GemStone/S). We are looking at applying Facets to JRuby and GemStone/S to Rubinius. Since the JRuby project is already in a 1.0 release, we are doing our first proof-of-concept on that platform. So far, it looks good. It requires downloading our JVM (the JVM is licensed from Sun and we have tweaked the byte codes to allow for transparent persistence of Java objects). The JVM is slightly slower (about 5% in my tests) than the current Sun JVM because of the additional work going on with the persistence.
There has been one problem to solve in the JRuby implementation and I have submitted a fix to the JRuby team. JRuby currently does not support serialization (or our style of persistence) because every Ruby object has direct references to the JRuby runtime (threads, dynamic methods, and other internal objects). When the objects are serialized (or persisted) they drag along the entire runtime system. So I found a way to detach the objects from this runtime system and enable both serialization and transparent persistence. Once that was done, our persistence engine just worked.
# to persist an object in one VM declare a
# persistent 'root' that allows access to objects with the
# 'name' of the object
persistent :people => :name
# begin a transaction, put a Ruby object and all objects that are
# connected to it into the persistent root, and commit it
p = Person.new('Alan')
p.children << Person.new('Jimmy')
p.children << Person.new('Janie')
transaction
people << p
commit
# in another VM
persistent :people => :name
p = people['Alan']
puts p.name
p.children.each do { |child| puts child.name }
We are in the process of designing an API for this transparent persistence. In Rails, you won't use 'transact' and 'commit'. You will just declare the persistent roots and put objects into them. The transaction boundaries will be created when the request comes in and the commit will happen just before the response goes out.
Since much of ActiveRecord is there because of the impedance mismatch between objects and relational databases, a lot of ActiveRecord will be unnecessary. For example, belongs_to, has_many, etc. are there to support associations (foreign keys in the db, etc) and they are unnecessary. Likewise with acts_as_list, etc. I find it interesting that ActiveRecord requires so many duplicate constructs in violation of the DRY Principle. Declaring associations in your Ruby classes and setting up the foreign keys in the schema. It would all go away.Continuing with technical details, Alan explains how Gemstone's custom JVM makes persistence possible:
But we do want to support filters, validations, etc. Whether it will look exactly like ActiveRecord is doubtful because, unlike ActiveRecord, the Ruby objects do not have to be subclassed off of a particular class. The other problem with ActiveRecord that transparent persistence solves is subclassing. There is no good solution to representing a hierarchy of classes in a relational database (sparse tables or table joins). With our persistence, it is automatically supported. Subclass to you heart's content, mixin any modules into your domain classes. It just works.
We persist the Java representations of the Ruby objects. The JRuby objects are simple Java objects with a Map of instance variables. It is not image-based. Although the fix I sent to the JRuby team does allow serialization, we don't use serialization. Our persistence is based on page caching. Small (8K) pages of memory are flushed to the database on a commit and pages are faulted in from the persistent store as the application uses the object references. Since objects tend to aggregate onto the same page, there is little paging going on once a page is brought in.
Ruby objects don't have a well-defined structure. One instance of a Ruby class might have a different structure than another instance of the same class. This is because instance variables are dynamically added by the methods that are invoked upon the instances. So the structure (and the ivars) that an instance has depends on what messages it has been sent during its lifetime. This is very different from both Java and Smalltalk where the are places in the classes where all of the instance variables are declared statically. So migration of Ruby objects is not as large an issue. There are some requirements that would make sense to support (e.g.e, removing an instance variable and its associated value when the method that caused it to exist has been removed from the class definition, but we see that as an administrative task that is supported by tools.
By the way, stay tuned for progress on the Rubinius VM. That will not run in JRuby and will not require using our JVM. We are working with Evan Phoenix to ensure that the VM will support our requirements out of the box. Then it will probably just be a gem that you install to use our persistence. Our intention is to provide a product for free (limited ot a 4G data repository on one server) as we are doing with Seaside. Once you need more than 4G of data or you want to scale to multiple servers, it requires purchase and licensing.Gemstone has been busy supporting new web frameworks and tools. Next to the new Ruby support, Seaside will be supported as well.
We are applying our persistence to the Smalltalk Seaside framework. It will be released this Fall. The approach in Seaside will be very similar to what we are looking at doing for Ruby and Rails.Initial announcements call this GLASS, which stands for Gemstone/Linux/Apache/Smalltalk/Seaside.
Fair Trade Software Licensing - A Guide to Neo4j Licensing Options
Getting Started with Stratos - an Open Source Cloud Platform
18 agile and lean practices for effective software development governance
Jason Ayers share the observations he made watching a team of developers collaborating in real time on the same code base, pushing XP, pair programming and continuous integration to their extremes.
Michael Snoyman presents Yesod, a web framework written in Haskell and containing a web server, templating, ORM, libraries (templating, gravatar, etc.).
Richard Kreuter and Kyle Banker on how to avoid classical RDBMS transactional systems by using compensation mechanisms, transactional messaging or transactional procedures.
Attila Szegedi talks about performance tuning Java and Scala programs at Twitter: how to approach GC problems, the importance of asynchronous I/O, when to use MySQL/Cassandra/Redis, and much more.
One category of risk that project teams need to ensure they address is business value failure – delivering a product that fails to provide value for the business investor.
InfoQ spoke to the authors of Software Systems Architecture on a couple of new topics, the System Context viewpoint and Agile, which have been added to the second edition.
Alex Papadimoulis discusses ugly code, where it comes from, how to avoid it, and how to get rid of it.
John Davies examines Visa’s architecture and shows how enterprises have architected complex integrations incorporating Hadoop, memcached, Ruby on Rails, and others to deliver innovative solutions.
1 comment
Watch Thread Reply