<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2317206127860697037</id><updated>2011-07-28T20:40:36.581+02:00</updated><category term='Pharo'/><category term='refactoring'/><category term='Smalltalk'/><category term='Toplink'/><category term='functional programming'/><category term='Squeak'/><category term='GLORP'/><category term='HASingleton'/><category term='Qi4j'/><category term='SqueakSource'/><category term='Snarl'/><category term='polymorphism'/><category term='DDD'/><category term='Traits'/><category term='JBOSS'/><category term='Magritte'/><category term='Newspeak'/><category term='immutability'/><category term='Java'/><category term='OO'/><category term='OODB'/><title type='text'>point of view is worth 80 IQ points...</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://80points.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2317206127860697037.post-5455544610758024970</id><published>2009-10-20T21:13:00.002+02:00</published><updated>2009-10-20T21:39:10.039+02:00</updated><title type='text'>Keeping Seaside session alive</title><content type='html'>I've created a simple Seaside app to monitor the state of our servers. It does this by screen-scraping multiple service status webpages hosted on our servers. The monitoring was coded as a sUnit set of tests which can run standalone or as part of the Seaside application. Any service breaches are sent via Growl or Snarl. All status responses are persisted using Magma and so far it's been working well.&lt;br /&gt;&lt;br /&gt;There have been a few minor issues though.&lt;br /&gt;&lt;br /&gt;Memory consumption was a little high and I pinpointed it to Magma + Squeak. It seemed the MaTransaction's and the oid's were not being garbage collected even though they were in a WeakDictionary. I fixed this by registering the WeakDictionary with the WeakArray finalization process in MaTransaction. Memory problem fixed :)&lt;br /&gt;&lt;br /&gt;Another issue was that sessions were expiring after 10 minutes and since we typically look at the results every 2 hours or so. Reconnecting to the Magma store and re-establishing the session was slightly slowing down the responsiveness of the app, so I decided to add a Javascript session keep-alive hack. I created a little Seaside component that I render in my main Seaside component. It's renderContentOn: method reads&lt;br /&gt;&lt;blockquote&gt;&gt;&gt;renderContentOn: html&lt;br /&gt;  (html periodicalEvaluator frequency: 5 minutes asSeconds) callback: [:renderer | "do nothing"].&lt;/blockquote&gt;All this does is call back into the app every 5 minutes and now the responsiveness has improved and we still have session management (when the browser is closed).&lt;br /&gt;&lt;br /&gt;The other issue was really to a poor design decision on my part. The status responses received from the servers are persisted using Magma and I had created a few indexes and used a MagmaCollection. One of the monitoring pages show the total number of tests and the total number of failures. This query was progressively getting more expensive as the status response objects were being materialised to see if the response was successful or not. The answer to this was to create another index for this boolean. So I created a BooleanIndex added it to the MagmaCollection and bam, much better performance. Queries are now coming back in under 1.5 seconds whereas before it was taking about 90 seconds. Magma DB has about 20000 entries at the moment, so I'm pretty pleased with the response times.&lt;br /&gt;&lt;br /&gt;Overall I am pleased with the use of Seaside, Magma and Pharo. What I want to do now is make the site look better and maybe add some ajax calls to make the site more usable. But then again this is a hack, maybe I'll live with it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2317206127860697037-5455544610758024970?l=80points.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://80points.blogspot.com/feeds/5455544610758024970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2317206127860697037&amp;postID=5455544610758024970' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/5455544610758024970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/5455544610758024970'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/2009/10/keeping-seaside-session-alive.html' title='Keeping Seaside session alive'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2317206127860697037.post-1460699996897533302</id><published>2009-09-22T19:45:00.005+02:00</published><updated>2009-09-22T20:07:08.401+02:00</updated><title type='text'>Snarl Smalltalk client</title><content type='html'>After basically hacking a simple &lt;a href="http://www.pharo-project.org"&gt;Smalltalk&lt;/a&gt; &lt;a href="http://www.fullphat.net"&gt;Snarl&lt;/a&gt; client I decided to put it to use.&lt;br /&gt;&lt;br /&gt;First of all a quick status on the client: &lt;ul&gt;&lt;li&gt;it covers the bare minimum functionality,&lt;br /&gt;&lt;/li&gt;&lt;li&gt; uses the network protocol because it was easy to do,&lt;br /&gt;&lt;/li&gt;&lt;li&gt;has no error handling because most of the time it just works.&lt;/li&gt;&lt;/ul&gt;To monitor our systems (we have about 9 servers) we use simple web interfaces to query their status. Normally we would log in to each app via HTTP and use the web interface, so I decided it would be easier to use Snarl to notify us as soon as something goes wrong (we have monitoring software but there are some issues ... anyway). I created a simple Seaside app to register/de-register a Snarl service running on our client PC's, and also start a background process to interrogate the HTTP interfaces of the PC's we were monitoring.&lt;br /&gt;&lt;br /&gt;So far it has been working really well without any issues. As this was an interim measure I didn't want to spend too much time creating a monitoring tool but so far am impressed with how simple it was to hook everything up.&lt;br /&gt;&lt;br /&gt;Some technical details on the solution: use SUnit to test the REST-ful services, announce the results (using Announcements) so that either the TestCase runs standalone if there isn't an announcer registered or it notifies all subscribers. Set up &lt;a href="http://www.squeaksource.com/UpsideDownSnarl.html"&gt;UpsideDownSnarl &lt;/a&gt;client to process the announcements. Used Seaside to create a management interface.&lt;br /&gt;&lt;br /&gt;The sweetest section of code in all of this: Using Process&gt;&gt;allSubInstances and then using the enumeration protocol to find and terminate any processes that were registered on the clients behalf.&lt;br /&gt;&lt;br /&gt;Smalltalk makes it so easy to do something like this :) you gotta love the quick feedback cycles&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2317206127860697037-1460699996897533302?l=80points.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://80points.blogspot.com/feeds/1460699996897533302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2317206127860697037&amp;postID=1460699996897533302' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/1460699996897533302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/1460699996897533302'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/2009/09/snarl-smalltalk-client.html' title='Snarl Smalltalk client'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2317206127860697037.post-4897898407806993919</id><published>2009-09-22T00:33:00.004+02:00</published><updated>2009-09-22T00:38:15.164+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pharo'/><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='Snarl'/><category scheme='http://www.blogger.com/atom/ns#' term='SqueakSource'/><category scheme='http://www.blogger.com/atom/ns#' term='Squeak'/><title type='text'>UpsideDownSnarl - Smalltalk Snarl client</title><content type='html'>I need to monitor some services at work and they've been misbehaving for a while now. So I saw James Robertson blogging on Snarl/Growl and decided to hack my own Snarl client for Pharo/Squeak.&lt;br /&gt;&lt;br /&gt;I uploaded the first version to SqueakSource and I must say Snarl is a nifty little tool. I now can run my Snarl client + service tests and get notified if something goes down.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2317206127860697037-4897898407806993919?l=80points.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://80points.blogspot.com/feeds/4897898407806993919/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2317206127860697037&amp;postID=4897898407806993919' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/4897898407806993919'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/4897898407806993919'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/2009/09/upsidedownsnarl-smalltalk-snarl-client.html' title='UpsideDownSnarl - Smalltalk Snarl client'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2317206127860697037.post-3399346574355618141</id><published>2009-03-15T22:50:00.006+02:00</published><updated>2009-03-16T00:11:04.772+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Magritte'/><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='Traits'/><category scheme='http://www.blogger.com/atom/ns#' term='Newspeak'/><category scheme='http://www.blogger.com/atom/ns#' term='GLORP'/><category scheme='http://www.blogger.com/atom/ns#' term='Qi4j'/><category scheme='http://www.blogger.com/atom/ns#' term='OODB'/><title type='text'>Qi4j == Magritte + Traits + OODB  + Newspeak</title><content type='html'>I recently came across the opensource &lt;a href="http://www.qi4j.org/"&gt;Qi4j&lt;/a&gt; project which has  &lt;a href="http://www.jroller.com/rickard/"&gt;Rickard Öberg&lt;/a&gt; &lt;a href="http://thejbossissue.blogspot.com/"&gt;co-founder of JBoss&lt;/a&gt; as one of its core developers. Now I haven't gone into a large amount of detail, but I have read the tutorial and some examples and although I see the benefit, I feel Java as the implementation language was definitely the wrong choice.&lt;br /&gt;&lt;br /&gt;If you are going to try predict the future &lt;a href="http://www.smalltalk.org/alankay.html"&gt;and the best way is to invent it&lt;/a&gt; then why cripple it with Java? Ok so thats a little harsh but look at the examples and tell me if you can see the domain code easily, Java is just not expressive/malleable enough to make it read well and Qi4j's meta-descriptions (as annotations) are not extensible or dynamic. In my opinion this limits its power.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Qi4j == Magritte + Traits + OODB  + Newspeak&lt;span style="font-style:italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.lukas-renggli.ch/smalltalk/magritte"&gt;Magritte&lt;/a&gt; &lt;blockquote&gt;...is a meta-description framework, describing domain classes and their respective attributes, relationships and constraints.&lt;/blockquote&gt; With Magritte you can describe your domain model similar to what Qi4j is doing. A major difference is that Magritte is self-describing and the meta-model is modifiable at runtime. So since you can describe your domain you can do things like object persistency, indexing, reports and views etc. and having this meta-model would allow one to create an optimised &lt;a href="http://en.wikipedia.org/wiki/Object_database"&gt;OODB &lt;/a&gt;(&lt;a href="http://www.cincomsmalltalk.com/userblogs/avi/blogView?showComments=true&amp;entry=3246121322"&gt;ROE&lt;/a&gt;?, &lt;a href="http://www.gemstone.com/products/smalltalk/"&gt;Gemstone&lt;/a&gt;) persistence facility or a relational database mapping scheme (&lt;a href="http://www.glorp.org/"&gt;GLORP&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://en.wikipedia.org/wiki/Mixin"&gt;mixin &lt;/a&gt;and behaviour separation constructs in Qi4j remind me of &lt;a href="http://www.iam.unibe.ch/~scg/Research/Traits/"&gt;traits&lt;/a&gt; which arguably is a better form of behaviour composition.&lt;br /&gt;&lt;br /&gt;The Qi4j application 'assembly' steps remind me of &lt;a href="http://newspeaklanguage.org/"&gt;Newspeak&lt;/a&gt;'s nested classes and module system.&lt;br /&gt;&lt;br /&gt;I appreciate the ideas that Qi4j is trying to achieve but believe they are most likely wasting lots of developer 'cycles' trying to wrangle Java rather than coming up with some innovative ideas. A dynamic, fully reflective OO lanaguage (like Smalltalk :)) would be better suited to their needs as it would allow them to focus on their 'domain' which is building a &lt;a href="http://en.wikipedia.org/wiki/Domain-driven_design"&gt;DDD&lt;/a&gt; enabling framework.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2317206127860697037-3399346574355618141?l=80points.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://80points.blogspot.com/feeds/3399346574355618141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2317206127860697037&amp;postID=3399346574355618141' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/3399346574355618141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/3399346574355618141'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/2009/03/qi4j-magritte-traits-oodb-newspeak.html' title='Qi4j == Magritte + Traits + OODB  + Newspeak'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2317206127860697037.post-6818244491195125366</id><published>2009-03-13T00:44:00.014+02:00</published><updated>2009-03-15T22:29:17.181+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Are you an OO Bigot? Time for a different modeling technique maybe...</title><content type='html'>After reading through a blog entry which basically centered on &lt;a href="http://www.markhneedham.com/blog/2009/03/12/oo-reducing-the-cost-oflots-of-stuff/"&gt;'Reducing cost by using OO principles'&lt;/a&gt;&lt;br /&gt;it made me realise that there is the danger where we stick to our ways and preclude lots of other valid design and modeling choices. The author describes how he has been described as 'over object orienting' solutions. I feel it happens to many of us, and when people are telling us this it may be a valid flag that we are over-generalising and therefore over-complicating our design&lt;br /&gt;i.e. typically the more generalised the solution the more 'mental hoops' the readers of the code will have to go through to understand it. It might be time to use another modeling technique, function oriented, rule based etc.&lt;br /&gt;&lt;br /&gt;BTW I'm not implying that the referenced blog entry is wrong in saying that OO design can reduce cost but what I do think is that cost can be measured in many ways.&lt;br /&gt;Yes there are cost 'reductions' in being able to localise code change as to me one of OO designs strength's lies in the ability to package behaviour and state.&lt;br /&gt;&lt;br /&gt;This 'hopefully' reduces the cost of change as the state changing behaviour should be localised in a few key areas (depending on how deep the change 'cuts across the grain').&lt;br /&gt;&lt;br /&gt;But here lies the rub; OO works well when the object model lies close to the actual real world 'object' or metaphor that it is modeling. &lt;br /&gt;&lt;br /&gt;What I mean is that OO designs favour mental models where we can safely imply what the expected behaviour is of an object and not have to dive into the details.&lt;br /&gt;In this way users of our code can safely modify the code (tests help to verify that the known behaviours still work after the change but they don't verify all possibilities, just the ones the tester deemed important).&lt;br /&gt;&lt;br /&gt;OO design does not lend itself to composing of behaviours because it has to typically deal with state. Users of the object need to understand the messages that the object can react to and what the intended result of the message is. They don't need to know how it is done just that it will be done, but this limits how you can compose behaviour because the timing of calls is important. &lt;br /&gt;&lt;br /&gt;Functional languages and designs would (and by no means am I an expert) favour applying functions to a data structure (and to other functions ala higher order functions) that transform the data safely and typically are side effect free.&lt;br /&gt;This is crucial to being able to compose behaviour as you can apply the function to data over and over again knowing the result will be the same. Nothing changes that behaviour, there is no concern of state to add to the stack of your 'conceptual model'.&lt;br /&gt;&lt;br /&gt;I believe (and not from first hand experience) that it falls down somewhat because it lacks powerful logic structuring mechanisms. i.e. it's hard to keep track of the transforms and group/package them, the function may be too coarse and have to be broken down into 2 or more functions; or it may be too fine grained and therefore be more difficult to understand how the transforms fit together i.e. to get a desired result which set of transformations should I use.&lt;br /&gt;&lt;br /&gt;Ok example time, I'll use working with collections of objects in Smalltalk and Java&lt;br /&gt;Say we have a business requirement to contact patients who are in arrears at a medical practice.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;kindReminder := [:account | account dueDate &gt; (Date today + 30 days)].&lt;br /&gt;slightlyOverdue := [:account | account dueDate &gt; (Date today + 60 days)].&lt;br /&gt;veryOverdue := [:account | account dueDate &gt; (Date today + 90 days)].&lt;br /&gt;&lt;br /&gt;'this is a function that emails a contact with a message'&lt;br /&gt;email := [:contact :message | Email mail: contact with: message].&lt;br /&gt;'email the patient'&lt;br /&gt;emailPatient := [:account | email value: account contact value: 'overdue'].&lt;br /&gt;'leave a voice mail on their phone'&lt;br /&gt;leaveVoiceMail := [:account | PhoneService leaveVoiceMailFor: account contact saying: 'overdue please call us'].&lt;br /&gt;'apply the normal email function to the patient and then make the lawyers aware by sending the same email sent to the patient'&lt;br /&gt;emailLawyers := emailPatient ensure: [email value: lawyer contact value: emailPatient value asMessage].&lt;br /&gt;&lt;br /&gt;'apply the functions to the data'&lt;br /&gt;Accounts findAll select: kindReminder thenDo: emailPatient.&lt;br /&gt;Accounts findAll select: slightlyOverdue thenDo: leaveVoiceMail.&lt;br /&gt;Accounts findAll select: veryOverdue thenDo: emailLawyers&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;OO would be cleaner to the eye, we could do something like:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;List inArrears=Accounts.findAllInArrearsByAtLeast(Days.from(30));  // 30 days&lt;br /&gt;for (Account account : inArrears) {&lt;br /&gt;    account.notifyInArrears();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void notifyInArrears() {&lt;br /&gt;    ContactStrategy.createArrearsStrategyFor(this).contact();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// ContactStrategy factory method would create the relevant strategy based on the account dueDate etc&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The 'functional style' (kind of, it still is Smalltalk) is more amenable to composition of behaviour safely by using higher order functions.&lt;br /&gt;The OO style is separated cleaner so change is easier to localise but extension points are harder to 'mould' in unless hooks were provided already.&lt;br /&gt;&lt;br /&gt;Now to get back to some kind of takeaway from this rambling post :). &lt;br /&gt;&lt;br /&gt;OO is great to factor behaviour; &lt;blockquote&gt;...In Smalltalk, nothing ever happens here...&lt;/blockquote&gt;'nothing ever happens here behaviour' (I think &lt;a href="http://en.wikipedia.org/wiki/Adele_Goldberg_(computer_scientist)"&gt;Adele Goldberg&lt;/a&gt; &lt;a href="http://www.lordzealon.com/2008/04/02/smalltalk-oop-quotes/"&gt;said that&lt;/a&gt; about Smalltalk/OO design) though means that typically understanding the model is more complex. There are just more moving parts with state and everything seems to happen elsewhere.&lt;br /&gt;&lt;br /&gt;Functional design favours transformations where we know what the input and output are meant to be, so we can compose behaviour more easily which is a very powerful tool.&lt;br /&gt;&lt;br /&gt;I feel a blend of styles would be best, something akin to the Smalltalk example but putting most of the logic behind intention revealing methods, and using the powers of functions (&lt;a href="http://en.wikipedia.org/wiki/Closure_(computer_science)"&gt;closures&lt;/a&gt;) or even &lt;a href="http://www.iam.unibe.ch/~scg/Research/Traits/"&gt;Traits — Composable Units of Behavior&lt;/a&gt; to compose certain behaviours.&lt;br /&gt;&lt;br /&gt;The ultimate goal for me when designing a solution is that it must be readable, understandable and therefore easy to change.&lt;br /&gt;&lt;br /&gt;Sorry about the long rambling post...if you made it here...well...wow&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2317206127860697037-6818244491195125366?l=80points.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://80points.blogspot.com/feeds/6818244491195125366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2317206127860697037&amp;postID=6818244491195125366' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/6818244491195125366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/6818244491195125366'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/2009/03/are-you-oo-bigot-time-for-different.html' title='Are you an OO Bigot? Time for a different modeling technique maybe...'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2317206127860697037.post-6307332483669208865</id><published>2009-03-03T10:54:00.006+02:00</published><updated>2009-03-15T22:29:44.701+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><title type='text'>Smalltalk: power of simplicity and personal mastery</title><content type='html'>One of the principles stated in &lt;span style="font-style:italic;"&gt;Design Principles Behind Smalltalk by Daniel H. H. Ingalls&lt;/span&gt; which appeared in the BYTE Magazine, August 1981 was that the &lt;a href="http://en.wikipedia.org/wiki/Smalltalk"&gt;Smalltalk&lt;/a&gt; project had a bias towards: &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Personal Mastery: &lt;span style="font-style:italic;"&gt;If a system is to serve the creative spirit, it must be entirely comprehensible to a single individual.&lt;/span&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Well my Smalltalk is not great, I have read some of the free books on &lt;a href="http://stephane.ducasse.free.fr/FreeBooks.html"&gt;Stephane Ducasse's website&lt;/a&gt;, and yet I still find Smalltalk to be intuitive and easy to do things with. I'm not sure if it was the way the language was designed, the class design (libraries) or a combination of the 2.&lt;br /&gt;&lt;br /&gt;Let me give a simple example, but first a disclaimer; I could have used excel or some other mechanism to do this but it was more of a learning experience. &lt;br /&gt;Ok so basically I had 2 CSV reports that i had run on 2 environments that I wanted to compare to make sure that there were no differences. Thats really simple and I didn't explore many options, I just fired up &lt;a href="http://pharo-project.org/home"&gt;Pharo&lt;/a&gt; and started typing into a workspace:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;firstReportList:= (CSVParser parse: (FileDirectory default readOnlyFileNamed: 'resources\first.csv')).&lt;br /&gt;firstReportList := firstReportList asOrderedCollection.&lt;br /&gt;firstReportList allButFirstDo: [:entry | entry at: 5 put: nil.].&lt;br /&gt;&lt;br /&gt;secondReportList := (CSVParser parse: (FileDirectory default readOnlyFileNamed: 'resources\second.csv')).&lt;br /&gt;secondReportList :=secondReportList asOrderedCollection.&lt;br /&gt;secondReportList allButFirstDo: [:entry | entry at: 5 put: nil.].&lt;br /&gt;&lt;br /&gt;Transcript clear.&lt;br /&gt;Transcript nextPutAll: (liveList = wareList) asString; cr; flush.&lt;br /&gt;Transcript nextPutAll: firstReportList size asString; cr; flush.&lt;br /&gt;Transcript nextPutAll: secondReportList size asString; cr; flush.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.squeaksource.com/CSV.html"&gt;CSVParser&lt;/a&gt; was a small nifty library by &lt;a href="http://www.avibryant.com/"&gt;Avi Bryant&lt;/a&gt; that I had previously loaded in my image. The line &lt;span style="font-style:italic;"&gt;firstReportList allButFirstDo: [:entry | entry at: 5 put: nil.].&lt;/span&gt; was put in to ignore the heading on the first line and then for all the other rows blank out (by making it nil) a column that was deliberately different in the 2 files with which I did not want to compare.&lt;br /&gt;&lt;br /&gt;Now firstly how sweet is that! &lt;br /&gt;Secondly I didn't get any differences so I was happy with the code i.e. I didn't have to write code to spit out the differences although I feel that would have been trivial. &lt;br /&gt;Thirdly try doing that in my staple language Java...umm no thanks...I know its possible but not as succintly as Smalltalk. I'm sure Lisp or Perl would have a nifty way of doing this, and probably Smalltalks distant cousins offspring Ruby.&lt;br /&gt;&lt;br /&gt;I can't wait for what Daniel Ingalls ended the article with (I think many people want to be part of this too :) and its not Ruby )&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-weight:bold;"&gt;Natural Selection: Languages and systems that are of sound design will persist, to be supplanted only by better ones.&lt;span style="font-style:italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;On another language note I see the &lt;a href="http://liftweb.net/"&gt;Lift &lt;/a&gt;web framework written in &lt;a href="http://www.scala-lang.org/node/25"&gt;Scala &lt;/a&gt;was released, I took a very brief look at some of their examples and I was not impressed with the mental hoops it took to make it do something simple. &lt;a href="http://seaside.st"&gt;Seaside&lt;/a&gt; seems simpler to grasp and as expressive if not more....but I'd still need to look at it in more detail.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2317206127860697037-6307332483669208865?l=80points.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://80points.blogspot.com/feeds/6307332483669208865/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2317206127860697037&amp;postID=6307332483669208865' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/6307332483669208865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/6307332483669208865'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/2009/03/smalltalk-power-of-simplicity-and.html' title='Smalltalk: power of simplicity and personal mastery'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2317206127860697037.post-391795456141264752</id><published>2008-06-12T14:05:00.000+02:00</published><updated>2008-06-12T14:05:23.714+02:00</updated><title type='text'>point of view is worth 80 IQ points...: JBoss HA Singleton using a service interface</title><content type='html'>&lt;a href="http://80points.blogspot.com/2008/06/jboss-ha-singleton-using-service.html#links"&gt;point of view is worth 80 IQ points...: JBoss HA Singleton using a service interface&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2317206127860697037-391795456141264752?l=80points.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://80points.blogspot.com/2008/06/jboss-ha-singleton-using-service.html#links' title='point of view is worth 80 IQ points...: JBoss HA Singleton using a service interface'/><link rel='replies' type='application/atom+xml' href='http://80points.blogspot.com/feeds/391795456141264752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2317206127860697037&amp;postID=391795456141264752' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/391795456141264752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/391795456141264752'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/2008/06/point-of-view-is-worth-80-iq-points.html' title='point of view is worth 80 IQ points...: JBoss HA Singleton using a service interface'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2317206127860697037.post-2446135782562609894</id><published>2008-06-11T16:49:00.012+02:00</published><updated>2008-06-11T17:10:28.769+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JBOSS'/><category scheme='http://www.blogger.com/atom/ns#' term='HASingleton'/><title type='text'>JBoss HA Singleton using a service interface</title><content type='html'>I wrote this post on a previous blog that was lost but resurrected it here:&lt;br /&gt;&lt;br /&gt;Some related links are:&lt;br /&gt;&lt;a href="http://wiki.jboss.org/wiki/JBossHASingletonRemoteAccess"&gt;http://wiki.jboss.org/wiki/JBossHASingletonRemoteAccess&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.jboss.com/index.html?module=bb&amp;amp;op=viewtopic&amp;amp;t=55794"&gt;http://www.jboss.com/index.html?module=bb&amp;amp;op=viewtopic&amp;amp;t=55794&lt;/a&gt;&lt;br /&gt;&lt;a href="http://lists.jboss.org/pipermail/jboss-user/2006-October/014954.html"&gt;http://lists.jboss.org/pipermail/jboss-user/2006-October/014954.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;server&amp;gt;&lt;br /&gt;&amp;lt;mbean code="org.jboss.invocation.jrmp.server.JRMPProxyFactory"&lt;br /&gt;name="jboss.jmx:type=adaptor,name=SingletonInvoker,protocol=jrmp,service=proxyFactory"&amp;gt;&lt;br /&gt;&amp;lt;depends optional-attribute-name="InvokerName"&amp;gt;jboss:service=invoker,type=pooled&amp;lt;/depends&amp;gt;&lt;br /&gt;&amp;lt;depends optional-attribute-name="TargetName"&amp;gt;&lt;br /&gt;my.domain:service=HaRemoteLoggingService&amp;lt;/depends&amp;gt;&lt;br /&gt;&amp;lt;attribute name="JndiName"&amp;gt;jmx/invoker/SingletonRMIAdaptor3&amp;lt; /attribute&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;attribute name="InvokeTargetMethod"&amp;gt;true&amp;lt;/attribute&amp;gt;&lt;br /&gt;&amp;lt;attribute name="ExportedInterfaces"&amp;gt;&lt;br /&gt;  com.platform.management.logging.distributed.RemoteServerLoggerMBean&lt;br /&gt;&amp;lt;/attribute&amp;gt;&lt;br /&gt;&amp;lt;attribute name="ClientInterceptors"&amp;gt;&lt;br /&gt;  &amp;lt;interceptors&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;interceptor&amp;gt;org.jboss.proxy.ClientMethodInterceptor&amp;lt; /interceptor&amp;gt;&lt;br /&gt;    &amp;lt;interceptor&amp;gt;org.jboss.invocation.InvokerInterceptor&amp;lt; /interceptor&amp;gt;&lt;br /&gt;  &amp;lt;/interceptors&amp;gt;&lt;br /&gt;&amp;lt;/attribute&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/mbean&amp;gt;&lt;br /&gt;&amp;lt;/server&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2317206127860697037-2446135782562609894?l=80points.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://80points.blogspot.com/feeds/2446135782562609894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2317206127860697037&amp;postID=2446135782562609894' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/2446135782562609894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/2446135782562609894'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/2008/06/jboss-ha-singleton-using-service.html' title='JBoss HA Singleton using a service interface'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2317206127860697037.post-5320105597231429364</id><published>2008-06-11T13:49:00.002+02:00</published><updated>2008-06-11T15:55:34.333+02:00</updated><title type='text'>UI and domain code</title><content type='html'>Although I am more of a back-end programmer I have worked with some, albeit, rudimentary webpages, recently in &lt;a href="http://www.seaside.st/"&gt;seaside&lt;/a&gt;. I've often thought of the mismatch between domain code (the model) and the view that we create around it to manipulate the domain.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;What is this mismatch? &lt;/span&gt;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 &lt;a href="http://martinfowler.com/eaaCatalog/"&gt;Transfer Objects with domain Commands&lt;/a&gt; to perform the business functionality.&lt;br /&gt;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 &lt;a href="http://martinfowler.com/eaaCatalog/"&gt;Transaction Script&lt;/a&gt;). 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.&lt;br /&gt;&lt;br /&gt;Trying to follow a design with a &lt;a href="http://www.domaindrivendesign.org/"&gt;rich domain model&lt;/a&gt; I would say that an application should have it's own application-domain-model (idealy with its own well defined &lt;a href="http://www.domaindrivendesign.org/"&gt;bounded context and a mapping layer&lt;/a&gt; to the actual business-domain-model below), and this application-domain-model would drive the business-domain-model code.&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Funny enough what I wanted to talk about was &lt;a href="http://www.lukas-renggli.ch/smalltalk/magritte"&gt;Magritte&lt;/a&gt; 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.&lt;br /&gt;&lt;br /&gt;Well I'll leave that for another post and maybe think more of the application-domain-model vs business-domain-model issue...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2317206127860697037-5320105597231429364?l=80points.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://80points.blogspot.com/feeds/5320105597231429364/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2317206127860697037&amp;postID=5320105597231429364' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/5320105597231429364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/5320105597231429364'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/2008/06/ui-and-domain-code.html' title='UI and domain code'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2317206127860697037.post-8694747628622479279</id><published>2008-06-10T11:07:00.003+02:00</published><updated>2008-06-10T11:44:57.667+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DDD'/><category scheme='http://www.blogger.com/atom/ns#' term='immutability'/><category scheme='http://www.blogger.com/atom/ns#' term='Toplink'/><title type='text'>Immutability mutiny</title><content type='html'>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 '&lt;a href="http://www.martinfowler.com/bliki/HumaneInterface.html"&gt;humane&lt;/a&gt;' interface.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://www.domaindrivendesign.org/books/PatternSummariesUnderCreativeCommons.doc"&gt;DDD by Eric Evans&lt;/a&gt;) 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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;You could say where are all the unit tests; the unit tests should catch this; after 6 years you never came across this?&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2317206127860697037-8694747628622479279?l=80points.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://80points.blogspot.com/feeds/8694747628622479279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2317206127860697037&amp;postID=8694747628622479279' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/8694747628622479279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/8694747628622479279'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/2008/06/immutability-mutiny.html' title='Immutability mutiny'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2317206127860697037.post-8698720809030679718</id><published>2008-06-09T16:35:00.004+02:00</published><updated>2008-06-10T09:33:39.639+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='polymorphism'/><category scheme='http://www.blogger.com/atom/ns#' term='refactoring'/><title type='text'>Refactoring to show the rules</title><content type='html'>&lt;span style="font-size:100%;"&gt;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!).&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;I'm naming this method/variable this as it better reflects the intent...&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Restructuring the code like this will have this advantage but may have these disadvantages...&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;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? ...&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:100%;"&gt;and so the discussions went on.&lt;br /&gt;&lt;br /&gt;We both feel that the structure may feel more foreign to juniour programmers or to 'procedural OO programmers' for instance 1 comment was:&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-size:85%;" &gt; &lt;blockquote&gt;when debugging it is more difficult to see what is actually executing this code because of all the indirection/polymorphism&lt;/blockquote&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;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).&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;The end result was that we refactored the code into &lt;/span&gt;&lt;span style="font-size:100%;"&gt;1 high level interface, &lt;/span&gt;&lt;span style="font-size:100%;"&gt;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).&lt;br /&gt;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).&lt;br /&gt;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  (&lt;a href="http://blogten.blogspot.com/2006/11/polymorphism-at-its-best-nyc-sug-1129.html"&gt;polymorphism-at-its-best&lt;/a&gt;)&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2317206127860697037-8698720809030679718?l=80points.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://80points.blogspot.com/feeds/8698720809030679718/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2317206127860697037&amp;postID=8698720809030679718' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/8698720809030679718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/8698720809030679718'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/2008/06/refactoring-to-show-rules.html' title='Refactoring to show the rules'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2317206127860697037.post-8649218424894384406</id><published>2008-06-05T16:51:00.000+02:00</published><updated>2008-06-05T16:53:59.660+02:00</updated><title type='text'>First post</title><content type='html'>Hi&lt;br /&gt;&lt;br /&gt;Planning on blogging about IT and software engineering. The blog title is 'stolen' from Alan Kay, he said something to that affect.&lt;br /&gt;&lt;br /&gt;Anyway my interests revolve around programming languages (Smalltalk, Java) and all the technology alphabet out there.&lt;br /&gt;&lt;br /&gt;Cheers&lt;br /&gt;Carlo&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2317206127860697037-8649218424894384406?l=80points.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://80points.blogspot.com/feeds/8649218424894384406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2317206127860697037&amp;postID=8649218424894384406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/8649218424894384406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2317206127860697037/posts/default/8649218424894384406'/><link rel='alternate' type='text/html' href='http://80points.blogspot.com/2008/06/first-post.html' title='First post'/><author><name>greedycat</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
