Pages

13 January 2006

Roman code kata: MCMLXXIV => 1974

I want to share a small code kata I did tonight.

The kata

Transform a roman number "MCMLXXIV" into a decimal number: 1974. This kata is extracted from the XP french website (here).


What! Ruby is not perfect ?!

Another example of DiD,... In my implementation, I wanted to get access to all the characters of a string: "CIV" to ["C", "I", "V"].

So I grab the ruby doc and after a few searches on the web, I realize that no nice method such as String#chars or String#each allows to get the characters in an array (here's a ticket for that issue).

I had to resolve to my_string.split(//) which is not quite natural and expressive.

TDD of course

I used TDD to progress with my development:

assert_equal(1, r_to_i("I"))
then
assert_equal(2, r_to_i("II"))
...

and I was quite glad to get the right code fast enough. Ok, agreed, it is not rocket science. But small successes make a happy day.

Lessons learned

The interesting thing about code kata is the time to consider what has been done and how it has been done. Specifically I wondered about the possible use of an injecter to reduce the code (which was a question on the web site):

def r_to_i r
result = last = 0
r.reverse!.split(//).each{|n|
T[n] >= last ? result += T[n] : result -= T[n]
last = T[n]
}
result
end


[funny thing : copying-and-pasting the code on the blog, I found several ways to reduce the code size. However, I feel a comment is necessary on the algorithm. I may not be understandable at first sight,...]

But I don't how it is possible since injectors are repeatedly cumulating the same operation on elements of a collection. Anyway, it was a good pretext to re-read the paragraph on the subject in ProgrammingRuby.

Ok, back to hiraganas now (I am currently learning japanese,...)

11 January 2006

DiD : Devil in the Details,...

A new acronym, that can be encountered in so many workplaces, even literally speaking sometimes ! (Bwah, ah, ah, ah,...)

Time for a follow-up. I was pretty satisfied with my idea of implementing associations as first-class objects in our object-model. It truly serves its purpose : a fine management of relationships between objects: deletion, updating, adding,...

However, I would like to summarize also all the difficulties we had along the way, that's not always paved with flowers:

Transient/Persistent objects

We have some objects that are build only for the purpose of the application session. Those objects are displayed to the user but not meant to be persisted. Yeah, right. But hey, anytime you are associated with a business object, an underlying Observer-Observable relationship is build. It's fine until the business object is persisted and JDO kindly does "persistence by reachability" to persist anything connected. Bang! A transient object is persisted,...

Modification impacts outside the aggregate

With our framework, each time the marketing adds a new ProductRelease to the Product, the Catalog can be notified. All this stays in the same hierarchy of objects. But what if a corresponding new ManufacturedItem should be created in the Factory ?

Loosing my memory

Objects are cool, objects are fine and RAM is cheap,... but not infinite! Adding new objects to manage the relationships also adds more data and we had surprises with our memory consumption.

Redundant associations

Every relationship is managed as an association, even for redundant associations, that are only there for design reasons. As we also use our framework, in a very generic way, to create configuration files, we had never-ending instability each time a new association was added even if the business did not evolve.

Caches

A variant of the previous one. How should a cache of objects be managed? As a composition between the object owning the cache and the cached objects? Can the cached objects appear in compositions even if they are indeed shared?


Tackling the issues one by one

Ah the details,... They can truly turn any "brilliant idea" into "useless crap". Our current answers to those issues are:
  • Transient/persistent: no obvious solution. Delete the objects when not used. Persist them temporarily if necessary. We are waiting for our supplier to implement JDO2.0 to implement an elegant solution.
  • Modifications outside the aggregate: use the ubiquitous EventBus
  • Loosing my memory: some attributes were unecessary on the associations. This had a nice impact. However since we don't have any way in Java to know who's using a specific object, we need to add extra-pointers
  • Redundant associations / caches: this is a real case of "don't mess the business model with the design model". We redesigned our associations with more meaningful data. Is it a design association? Is the component object cached? And so on.
So far, so good, we didn't find a vicious little problem that could bring our framework down,... yet!

One more word: I wish we did all that in Ruby! Take a look at the ActiveRecords framework:
class Firm < ActiveRecord::Base
has_many :clients
has_one :account
belongs_to :conglomorate
end
or
class Account < ActiveRecord::Base
composed_of :balance, :class_name => "Money",
:mapping => %w(balance amount)
composed_of :address,
:mapping => [%w(address_street street), %w(address_city city)]
end
It seems so clean :-O