08 March 2008

Anger for Free

Our internet provider is free.fr and our freebox died recently. I called free, a human replied quickly, and after I explained the situation, they assured me

We want to fix this as quickly as possible so we'll send you a new (upgraded) freebox by courier tomorrow morning and also give you a month's credit on your account to compensate for the inconvenience. The new box will work out-of-the-box (if you'll pardon the pun), but in case you have any trouble getting it going we'll send a technician to you within a day to fix anything that might have gone wrong. Thank you for bringing this issue to our attention and we hope you will continue to enjoy surfing with us!

*** Only Joking !!!

In fact, it took about twenty calls before reaching a human, and the indignity of it, each time it took about two minutes on their 34c/min line to reach the point where their computer voice told me there was no human available at the moment.

When Sabrina finally got through (I had given up), they needed the password to our client area on their own site so they could order a freebox upgrade on our behalf - which would take about two weeks to "configure" and deliver.

At the same time, I got a suggestion from their email support that I borrow a power adapter from a neighbour and see if that fixes the problem - and please provide the name and telephone number of said neighbour when you're done.

Three weeks later, I called again, and politely inquired whether I would be seeing any freeboxes coming my way in the foreseeable future - it was supposed to take two weeks, after all. "Oh, no, sir, we don't give timelines for delivering the freebox. The person who told you two weeks was in error".

I have to say, we've been using freetelecom for about three years now, and their service worked flawlessly for the whole of that time. As far as I can tell from articles and forums on the topic, they are one of the best providers in France. But this is the end for me. Their goodwill has a half-life of about one day, and it's so miniscule now it's not even homeopathic.

If anyone has an ISP recommendation, I would love to hear it. Especially if it comes with uptime guarantees, even if it has to cost more ...

07 March 2008

Fundamentals of OO (aka FOO)

Whenever I happen upon a beginner's introduction to OOP (why this happens to me is another story altogether), there's usually a long-winded account of how a Cat is a kind of Mammal, and so is a Dog, and a Mammal is an Animal, blah blah blah.

OO is basically about types, and types came from ... guess where ... Typing!! Ladies and Gentlemen, this is not a joke!! Gutenberg (the person, not the free online book project), credited with the invention of Movable Type (the printing system, not the blogging software, we're talking 15th century here), used Types for creating printed representations - instances, one might say - of letters.

So there you have it, OO in a nutshell, you have a Type, and from it you create as many instances as you desire. Object Oriented Programming is the direct descendant of the humble TypeWriter. The Type is not the instance, and vice-versa, although the characteristics of the Type evidently determine the characteristics of the instance.

Please unlearn everything you might have read about Cats and Dogs and Mammals, it's BS.

(picture under GFDL, borrowed from Wikipedia, thanks to Daniel Ullrich)

06 March 2008

Tomcat Deploys My Application Twice !

I drop my foo.war under webapps, and from the logs I see objects from my Spring application context getting loaded two times. What's causing this double deployment?

After much head-scratching I realised that my foo app was getting deployed as the root context (under "/"), as well as under "/foo". And in our Tomcat's server.xml we had a little

  <Context path=""
              docBase="/path_to_tomcat/webapps/foo"
              reloadable="true" 
              crossContext="true"> 
  </Context>

We dumped this Context entry, renamed foo.war to ROOT.war (caps necessary), and our double application startup disappeared.

Tomcat was dutifully doing its auto-deploy magic with its webapps directory, and then dutifully deploying any Contexts it found in its server.xml. If you really need a Context in your server.xml, make sure its docBase isn't under your Tomcat's webapps directory.

A simple solution, but it took us a while to fix, and according to my friend google lots of other people have had similar symptoms and worse trouble fixing them.

HTH :))

24 February 2008

Readable Specifications : Hpricot and RSpec

I use FIT and HTMLUnit during the day for really, truly testing my web application. At night, when I transform myself into a Ruby monster, it's RSpec and Hpricot (the "enjoyable" HTML parser). I had tried before with assert_select, but I ended up with a zillion nested with_tag statements that didn't help my digestion.

At work, we have written a little bit of transformation so that the tables we see in our FIT tests look pretty similar to the tables we are testing in our application. I wanted to do the same with RSpec so it would look like this:

table = doc.search("//table[@id='invitations']").first

table.should_match([
  [ "email",            "sent",        "accepted",    "login"   ],
  [ "foo@bar",          "2008-02-10",  "2008-02-16",  "foobar"  ],
  [ "yoyo@toto",        "2008-02-15",  "2008-02-17",  "yoyo"    ],
  [ "will@not.accept",  "2008-02-15",  "",            ""        ],
])

The following little bit of code does the job (I dropped it into my spec_helper)

module Hpricot
  class Elem
    def should_match(array)
      array.each_with_index { |row_data, row_index|
        if (row_index == 0)
          cell_tag = "th"
          row = 1
        else
          cell_tag = "td"
          row = row_index
        end
        row_data.each_with_index { |cell_text, column_index|
          q = "//tr[#{row}]/#{cell_tag}[#{column_index + 1}]"
          self.search(q).inner_html.strip.should == cell_text
        }
      }
    end
  end
end

This is a really basic solution ... there's lots of work before I can use it to test attributes and nested markup in an equally readable way. And it assumes the first row is in a <thead> and contains <th> elements; and that the remainder is under a <tbody> element (this is how Markaby generates markup (it also happens to be correct, if you have a header row)).

I'm a total Hpricot n00b, so there's probably a better way to implement this, but I'm enjoying it for now ... please let me know if you have a better way :)

14 February 2008

Markaby vs templating, with a remark on DSLs

I tried out Markaby ("MARKup As ruBY") the other day because I was getting completely tangled in my rhtml. It's a DSL for generating HTML from Ruby. I like it: it's much less verbose than templating, and it's a lot easier to read. Template enthusiasts might argue that Markaby does not enforce proper separation between markup and content - so a UI designer will be unable to work properly. Sorry. I only know of projects where the developers are also the HTML/CSS designers. This seems to be standard practice for in-house projects at large organisations, as well as a necessity for tiny organisations who can't afford more people. The mythical UI designers - so real in the Freemarker manual I start to worry they'll grab my keyboard - haven't turned up for work yet ...

Unfortunately, it's not so easy to write. At the risk of being scorned by the rails community I will dare to mention that I use Intellij for all my ruby coding (yes, ruby coding. I know it's the "intelligent java editor"), and it has great support for HTML - it autocompletes html tags, attributes, a little bit of javascript, and a heap of CSS. Even colours. It's, like, awesome.

But I'm not talking about Intellij today, I'm talking about Markaby. The problem is, Intellij doesn't know (yet) how to autocomplete Markaby. When I write


div.selected(:id => "foo_#{foo.id}", :style => "position:abs___

and try to complete from here, Intellij doesn't realise this is the position property of a HTML style attribute, and it can't tell me that the valid completion is absolute. What's more, I can't control-click selected to navigate to the definition for this CSS class.

I'm sure the smart guys at Intellij will have this one figured out pretty quickly if Markaby gains market share. As Martin Fowler discusses in detail at Language Workbenches, tool support for DSLs is a general problem. But this absence of support doesn't mean we should reject either Markaby or DSLs generally.

One of the reasons we choose one programming language over another is because of how it helps us think. Lisp/Smalltalk/Ruby are powerful because they get completely out of the way. Well-designed DSLs are useful because they focus our attention on the problem at hand. The languages that win are those that allow us focus while staying out of our way. The value of the language is independent of the availability of tools for it. Java was around for a long time before Intellij, and indeed Spring and Hibernate were around for quite a while before Intellij provided specific tool support for those frameworks.

Tool support for a DSL is often more expensive than the DSL itself - so it will be unsurprising to continue seeing new unsupported DSLs for the foreseeable future. That way the industry invests in tool support only for those DSLs that actually take off.

Which I hope Markaby does.

Database Connection pooling with Oracle and Hibernate

We were getting a lot of ORA-00020: maximum number of processes (%s) exceeded, and we were also using apache commons dbcp for connection pooling. I can't say that the oracle error message is at all related to dbcp, but after a little hunting I found that the Oracle jdbc driver natively supports pooling - you don't need a 3rd-party pooling provider. This is how we have our Hibernate datasource set up now (in our Spring application context) -


<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
   <property name="dataSource">
        <bean class="oracle.jdbc.pool.OracleDataSource">
            <property name="URL" value="${datasource.url}"/>
            <property name="user" value="${datasource.user}"/>
            <property name="password" value="${datasource.password}"/>
            <property name="connectionCachingEnabled" value="true" />
            <property name="connectionCacheName" value="my_connection_pool" />
            <property name="connectionCacheProperties">
                <value>
                    MinLimit: 5
                    MaxLimit: 25
                    InitialLimit: 5
                </value>
            </property>
        </bean>
    </property>

  ... other stuff ...

</bean>

"oracle.jdbc.pool.OracleDataSource" is shipped with the Oracle driver (ojdbc14.jar). Our friend ORA-00020 hasn't appeared again in the last couple of days, so we might be in luck.

You might argue that the project now has a hard-coded dependency on Oracle - but, honestly, the Universe will die its heat death long before this project switches database.

On a completely separate note, the ${substitutions} are replaced by a Spring PropertyPlaceholderConfigurer at runtime, and we are using a jasypt implementation so we can even encrypt the database password. Nice stuff ...

04 February 2008

CVs and CVS, part II (the other side of the coin)

As étienne commented, (and I paraphrase) CV authors include a lot of keywords in order to game CV indexing engines. In a sense, the CV authors and the JD (Job Description) authors are in a kind of arms race. Of the pointless, self-defeating kind.

Dear JD authors:

There are a million CVs out there that match your JD. How about writing something with a little more focus? You would need to know what you really want ... not just what are the technologies on your project.

It's true that if you have a project that's all java, struts, oracle and whatnot, it's quicker to integrate someone who's all java, struts, oracle and whatnot. But that still leaves a million CVs. What can you do to bring that down to, say, 50?

First of all, how can you tell whether the java, struts, etc mentioned on the CV are real skills rather than just technologies used on the project your candidate has been "involved in"? What would you expect to find in the CV of someone really, truly, deeply skilled with java, compared to someone who has poked around with the language for a year?

Secondly, how can you tell this person really wants to deliver value on your project, and isn't just looking for another job to keep going for the next few months? How do you feel when you read the CV of someone who is obsessed with delivering great software, compared to someone who would be bored without a job and wouldn't know what to do outside a cubicle?

Thirdly, if you will forgive me for smashing the stereotype of the antisocial nerd, the geek that can't speak (I imagine this is why Dilbert is rarely drawn with a mouth) - the primary job of a software developer is communication with other human beings. We spend ages just trying to find the right name for things. The best software speaks first of all to the team that develops it; and only secondarily to the machine that runs it. What picture forms in your mind as you read the CV of a great communicator, compared to the picture that develops (if at all) as you read the CV of a ... um, you know, those people who, sort of, can't really express themselves really well, like.

Fourthly, why are you reading CVs? Haven't you heard of Google? It's your CV :)