Wednesday, June 11, 2008

JBoss HA Singleton using a service interface

I wrote this post on a previous blog that was lost but resurrected it here:

Some related links are:
http://wiki.jboss.org/wiki/JBossHASingletonRemoteAccess
http://www.jboss.com/index.html?module=bb&op=viewtopic&t=55794
http://lists.jboss.org/pipermail/jboss-user/2006-October/014954.html

You can also access the HA Singleton via the actual services interface instead of org.jboss.jmx.adaptor.rmi.RMIAdaptorExt. So for example if we wanted to access a service with the following interface com.platform.management.logging.distributed.RemoteServerLoggerMBean, then we would use something like the following:

<server>
<mbean code="org.jboss.invocation.jrmp.server.JRMPProxyFactory"
name="jboss.jmx:type=adaptor,name=SingletonInvoker,protocol=jrmp,service=proxyFactory">
<depends optional-attribute-name="InvokerName">jboss:service=invoker,type=pooled</depends>
<depends optional-attribute-name="TargetName">
my.domain:service=HaRemoteLoggingService</depends>
<attribute name="JndiName">jmx/invoker/SingletonRMIAdaptor3< /attribute>

<attribute name="InvokeTargetMethod">true</attribute>
<attribute name="ExportedInterfaces">
com.platform.management.logging.distributed.RemoteServerLoggerMBean
</attribute>
<attribute name="ClientInterceptors">
<interceptors>

<interceptor>org.jboss.proxy.ClientMethodInterceptor< /interceptor>
<interceptor>org.jboss.invocation.InvokerInterceptor< /interceptor>
</interceptors>
</attribute>

</mbean>
</server>

UI and domain code

Although I am more of a back-end programmer I have worked with some, albeit, rudimentary webpages, recently in seaside. I've often thought of the mismatch between domain code (the model) and the view that we create around it to manipulate the domain.

What is this mismatch? It seems that there are a couple of camps on how to create an application layer around a model where either you create fine grained Transaction Script code or more coarse grained Transfer Objects with domain Commands to perform the business functionality.
The problem I feel is that business-domain-model code then moves into the application layer (most people create Commands that are nothing more than a glorified Transaction Script). The problem is your business-domain logic is in the wrong layer and therefore business rule consistency and re-use is diminished or hard to separate due to the coupling.

Trying to follow a design with a rich domain model I would say that an application should have it's own application-domain-model (idealy with its own well defined bounded context and a mapping layer to the actual business-domain-model below), and this application-domain-model would drive the business-domain-model code.
It feels like most people see MVC very explicitly and would like to have 'business objects' (objects persisted to a DB) with a view/presentation aspect and then a thin and very direct user gesture interpreter to manipulate the objects and satisfy the business rules. Now in simple CRUD applications this is fine, but when we have rich business-domain-models I can't see how this solution would scale. Abstractions would start to leak out, coupling would occur between application code and business code, and generally the 'application' logic cannot be reused/reappropriated on a different UI. What I'm trying to say is that a web app cannot be changed to a J2ME app as the app code is very specific.

Why aren't we creating an application-domain-model that abstracts what the app is trying to achieve and then we may be able to cater for different UI/interaction models over it. Also we would be encapsulating the application state/process-logic from the business-domain-model.

Some disclaimers: this is a rambling post because I'm not sure what the right answer is, all business problems are very different in complexity and so these arguments won't hold in all situations.

Funny enough what I wanted to talk about was Magritte which is dynamic meta-description framework for domain objects which helps developers to build different views, editors, and reports; and handle querying, validation and storing domain objects in an extensible and easy way.

Well I'll leave that for another post and maybe think more of the application-domain-model vs business-domain-model issue...

Tuesday, June 10, 2008

Immutability mutiny

As part of some legacy code we designed a Date wrapper for our persistent objects, that referenced dates, so that we could hide the fact of if we were using 'varchars' to store a date or using an actual 'timestamp' in our Oracle DB. All our code would use our wrapper class and be oblivious to the underlying implementation and also provide a more 'humane' interface.

As part of this initial design back in 2002 the developers decided to make the class a value object that was immutable, exhibited side-effect free functions, closure of operations and was a stand-alone class (see DDD by Eric Evans) which made developers life easier as they could safely perform operations on this Date object without needing to know the internals or combine these objects in a safe manner. Now I am not saying that the developers designed it knowing all of this but rather that it grew from a very simple interface into something that exhibited most of these behaviours.

Now to get to the point of this post: All of us thought that our Date wrapper was immutable and we relied on this fact heavily even caching all Date's ever created for garbage collection purposes, but it turns out after 6 years of use we just found out that it in fact is not.
The problem is that our ORM (Toplink) was mapped so that it could use protected method accessors to determine the value to write and read (which supplied our polymorphic behaviour to the clients). Now if we create an object and set an instance variable to a Date and then regsiter this with a unit of work, modify the object's date, and then try persist; Toplink will check the changeset and merge the result into the original object which bypasses our immutable side-affect free functions, and directly changes the object through the protected methods.

You could say where are all the unit tests; the unit tests should catch this; after 6 years you never came across this?

But we have nearly 2500 unit tests, run regression tests using our staging code vs our live code for about 400 000 (medical aid insurance) policies we have on our systems and yet we never came across this.

The problem boils down to: for some reason all the developers followed a way of coding that never included a default constructor that set a date on an object and then registered this new object with the unit of work. What we typically did was register the object at the end as we typically had control/awareness of what was being modified created. New developers that had joined the team had not been 'tainted' with the way that things had been done and bingo things began to break horribly.

I'm not sure how we can avoid immutability issues like this when using Toplink in this manner but anyway we have an idiom now on how to use dates and some code that checks if an existing date is being modified by Toplink or a client.

Monday, June 9, 2008

Refactoring to show the rules

A team mate and myself had a good time refactoring some non-OO spaghetti code into a more robust OO version. We didn't set out to do pair programming or refactor the code to the extent we did (partly because we were approaching a test freeze and did not have the time and partly because the code had been in this state for over 4 years!).

The nice end effect of this was that pair programming helped us share knowledge, not only business knowledge but also design knowledge. We constantly discussed micro-design decisions like:
  • I'm naming this method/variable this as it better reflects the intent...
  • Restructuring the code like this will have this advantage but may have these disadvantages...
  • If we create more classes and distribute the desired behaviour across them we will factor the code better and get rid of all these conditionals, but now this complex method has become a system of objects messaging each other. Which is more simple? ...
and so the discussions went on.

We both feel that the structure may feel more foreign to juniour programmers or to 'procedural OO programmers' for instance 1 comment was:
when debugging it is more difficult to see what is actually executing this code because of all the indirection/polymorphism
But the end product clearly factored the monolithic conditional-laden method into objects that had well defined responsiblities and that encapsulated the high-level policy (heuristic/algorithm/rules).

To give an example the code has 4 variations of calculating a value based ultimately on what is in the DB and the state of a policy (medical insurance policy). The code originally used many conditionals to determine what the DB says the rules are for a given state. These different strategies were interwoven in one method so the high level policy/heuristic/rule whatever you want to call it could not be easily understood.

The end result was that we refactored the code into
1 high level interface, 4 strategies, with 1 strategy being unique and the other 3 having a inheritance relationship (not only for sharing of behaviour but also sharing of implementation).
The sharing of implementation was a by-product of the refactoring exercise and although not ideal the main concern was that we had a well typed polymorphic hierarchy and as a by-product an implementation sharing hierarchy (ala some implementations of Smalltalk collection libraries where the main concern is subclassing for implementation).
The one complex method became 3 lines of code, and the rules were spread over 3 objects. Almost all the conditionals were removed in favour of polymorphic calls and for me this became the crux of the refactoring: Everything seemed more simple and easy to change and maybe even faster (polymorphism-at-its-best)

Thursday, June 5, 2008

First post

Hi

Planning on blogging about IT and software engineering. The blog title is 'stolen' from Alan Kay, he said something to that affect.

Anyway my interests revolve around programming languages (Smalltalk, Java) and all the technology alphabet out there.

Cheers
Carlo