Tuesday, May 8, 2007

RailsBrain

If you need to refer to the Rails API documentation frequently, as I do, then you'll really appreciate RailsBrain.

Monday, May 7, 2007

Design Patterns - last reminder

A final reminder that if we receive enough bids we'll be closing the Design Patterns workshop to attendees midnight this Friday. Post your bids by email.

Template Methods in Java and Ruby

Template method is a pattern commonly used in Java frameworks to allow application specific configuration of a generic framework. Most of the behaviour is contained in a generic Base class (usually abstract), and the consumer provides their specific implementation in a concrete subclass that overrides methods invoked from the superclass template. Some form of dependency injection (often Spring) is used to let the application know what concrete class needs to be instantiated. Testing the concrete extension usually means testing that it invoked the responsibilities of the superclass as expected. Let's look at an example.

class Extension extends Base
{
void extensionMethod()
{
this.abstractBehaviour(someParameter);
}
}

I want to test interactions, so normally I'd use a mock, but I can't mock out the superclass. A brute force approach is to roll my own mocking by creating a new subclass for testing.

class TestExtension extends Extension
{
boolean wasInvoked = false;
void abstractBehaviour(Object parameter)
{
wasInvoked = true; // could be more complicated
}
}

public void testExtension()
{
TestExtension extension = new TestExtension();
extension.invokeFrameworkMethod();
assertTrue(extension.wasInvoked);
}

An alternative is to inject an object that encapsulates the behaviour as a strategy, like this:

class Extension extends Base
{
Extension(Implementation implementation)
{
this.implementation = implementation;
}

void extensionMethod()
{
this.implementation(this);
}
}

Then I can inject a mock or stub implementation and verify that it is invoked, and separately verify that the implementation does what I expect by injecting a mock/stub Base into the implementation. That certainly separates the two concerns, and each concern is neatly unit tested. It's also quite a bit of code. It also points us in a new direction for the framework - injection of strategy objects for the customisable pieces of code instead of using template method and inheritance.

Ruby can handle the problem using both these approaches, but there's a third alternative that isn't available in Java. In Ruby, I can directly change the behavious of the framework class.

class Base
def extensionMethod
abstractBehaviour(parameters)
end
end

All done. No new classes, no injection, and the entire application is aware of the change once the code is loaded. But how do you test it? We go one step further, and override the behaviour of just the Base instance that we are testing, like this:

specify "Should invoke abstract behaviour" do
base = Base.new
class << base
attr_reader :was_invoked
def abstractBehaviour(parameter)
was_invoked = true # could be more complicated
end
end
base.invokeFrameworkMethod
base.was_invoked.should == true
end

Of course, in Ruby you might still benefit from the flexibility of using injected strategy objects rather than a template method, but you might also be able to get away with something that is even easier than either of the Java alternatives.

Saturday, April 28, 2007

From Java to Ruby, Rails for Java Developers, and Everyday Scripting with Ruby


Things Every Manager Should Know (Pragmatic Programmers)

Bruce Tate is a popular Java author (Better, Faster, Lighter Java, Bitter Java and Bitter EJB) and blogger, so it's significant when he shifts his focus from Java. In the earlier Beyond Java (which I haven't read), Tate looked at what lead to Java's dominance, and the limitations that were creating opportunities for other programming languages. In From Java to Ruby: Things Every Manager Should Know (Pragmatic Programmers) Tate focuses entirely on Ruby, which he sees as a strong (but not certain) contender for the 'next' programming language (though it's unlikely that anything will be as ubiquitous as Java has been). As the title indicates, the book is targeted at managers. If you're a manager or team leader who needs an overview, perhaps because your developers are advocating Java, or you're a programmer who needs to think about about how to advocate for Ruby without your organisation this is a good book. If you're a programmer looking for details on programming in Ruby, you're better off with one of the books I talk about next.




Rails for Java Developers



If you're already familiar with web application development in Java Rails for Java Developers by Stuart Halloway and Justin Gehtland is an excellent introduction to Rails. It runs through a point by point comparison of web application development in Java (using Spring, Hibernate and JSPs) and in Ruby on Rails. It's a short, accessible book (292 pages), but it's not a replacement for Agile Web Development with Rails (Pragmatic Programmers) - if you're doing serious Rails development you'll still want that on your shelf as well. But developers who only need a comparison and an introduction, perhaps before they decide whether to jump into the deeper water, will definitely appreciate "Rails for Java Developers".



For Teams, Testers, and You

Finally, I'm reading (but haven't quite finished, because it's sitting on my desk at work as a reference)
Everyday Scripting with Ruby: For Teams, Testers, and You by Brian Marick. Although ostensibly targeted at non-programmers who need to 'get something done' with Ruby, I'm finding this to be an excellent Ruby introduction for anyone. It has the clearest explanation of regular expressions that I've come across - I'm weak on regular expressions, but after reading this book I was confident enough to apply them both willingly and successfully on my current project. Once again, this book isn't as deep as the Pickaxe book (Programming Ruby: The Pragmatic Programmers' Guide, Second Edition), but I think it's much more accessible. Definitely recommended.






Hard Facts, Dangerous Half Truths & Total Nonsense


Hard Facts, Dangerous Half-Truths And Total Nonsense: Profiting From Evidence-Based Management



Hard Facts, Dangerous Half-Truths And Total Nonsense: Profiting From Evidence-Based Management by Jeffrey Pfeffer takes aim at many of the management fads of the last 20 years - not individually, but as a group. It critiques the anecdotal approach used by many management gurus and finds it lacking. It points out that in many cases a management technique might be present in a successful company, but also present in a large number of failing companies, and many (most?) management authors only present one half of the equation.



"Hard Facts" doesn't give any easy solutions to this problem. It suggests that every company is unique, and that it's always a good idea to run some sort of internal pilot to validate a new management approach.



This isn't a great book, but you might find it very useful if you're trying to critique the management fad du jour at your company.





Wednesday, April 18, 2007

Programming is important - really important

I wrote this in response to a comment on my post about Dreaming in code, but I wanted to expose it to people who view this via RSS, so here's the comment and my response.


Finally, something I can talk about.

I disagree totally.

Programming is not about code.

For me, a program or application doesn't live in the computer. It is not the bits and bytes. It extends much, much further.

For me, an application extends across everything the code affects. Not only is it the code, but it is also the users’ and the stakeholders’ mental models, processes and understanding of what the code does, what their organisation is and how to use the code to enhance their organisation.

Applications extend beyond computers into the people.

Example - a content management system is more that just the DotNetNuke code. It is also assigning the roles of writers and editors, it is understanding the people who will read the content and shaping the navigation and tone of the articles appropriately, it is teaching everyone in the organisation that they can request changes, and communicate their important stories with the world through the web.

When I am writing an application, I am not writing code. I am talking to people, I am trying to understand their issues, ideas and viewpoints. I am trying to work my way to the root of the problem. I am working out what questions to ask, talking to end users and training people to see things in different ways.

The application exists both in the computer and in the minds of people. As application building is not about code, it's not creative writing.

You don't look at the source code for great pieces of software. Or look at the architecture of great pieces of software. You don't look at their design.

What are patterns if not examples of great pieces of software and design?

What is MSDN - the magazine? Yes it is a Microsoft advertising vehicle, but it still has great code to read, understand and appreciate.

What are all the sites, forums and blogs on coding (including this one) but a sharing of knowledge on building applications and computing?


I use some of these words differently to you. I don't think a 'program' is that same as an 'application', and I don't think that 'software/application development' is the same as 'programming' at all. So I agree with all the things you say, up to the quote, about applications and application development, but at some point in application development we need to do some programming and to me that is absolutely, positively, by definition, about code. Programming isn't the only thing that we do in application development, but it's an important thing and I think there is a tendency to devalue it; to treat it as a typing exercise in which all programs that perform the same function are treated as equally worthy (you didn't say this, but I hear it a lot). I think application development would benefit from improvements to many disciplines, but I feel that programming is one of the most neglected disciplines at all.

When we write a program we write for two very different audiences - the program needs to be understood by the computer, which is apparent when it does (or doesn't) perform the expected functions, but it also needs to be understood by human beings. Most of our effort currently goes into pleasing the computer, but in some sense this is the easier of the two audiences. Gabrielle is saying (and I agree strongly) that we need to put more of our effort into satisfying the human audience for code. I'll assert as a corollary that finding ways to make code more expressive to people will also make it easier to write code that satisfies the computer as well, but I can't offer a proof in a mathematical sense.

As to what are patterns, and the code in places like MSDN and most web sites (including this one), they bear the same relationship to great programming that a power tool catalogue has to great building. They're focussed predominantly on efficiency, and on satisfying the computer, not on the aesthetics of programming as it's experienced by a human being. Christopher Alexander presented a keynote at OOPSLA many years ago, which I had the honour of attending, at which he said that he was ashamed of the way that the software community had applied patterns; that the heart of his idea was creating environments that appealed to our humanity but that software patterns has been sterilised - stripped of aesthetics and reduced to the equivalent of screwdrivers (my words, not his, but I think I'm faithful to the intent). Show me an article, or rather not one exceptional article but a body of work, that addresses different ways to name variables within the same programming idiom to improve expressiveness, or how to write code that brings a smile to your face, and we'll be heading down the path that Gabrielle is talking about, and we'll have taken one tiny programmatic step towards Alexander's goals.

You once asked me in email why I went back to uni to study psychology - my reply should have been because I think it would make me a better application developer. If I wanted to become a better programmer I wouldn't choose psych, I'd choose creative writing and literature, and that I haven't speaks to lack of time and dedication to my craft, not to a lack of need.

Tuesday, April 17, 2007

Dreaming in Code

I've always been interested in books that tell the story if creation from the inside, and particularly when they related to software. I remember being very impressed by Tracy Kidder's The Soul Of A New Machine when I read it way back at university, and another of Kidder's works, House. This week I finished another book in the same tradition, Dreaming in Code: Two Dozen Programmers, Three Years, 4,732 Bugs, and One Quest for Transcendent Software by Scott Rosenberg.

"Dreaming in Code" recounts the development of Chandler, an open source personal information manager (PIM) that's now been in development for four years. I have to admit that when I saw the project start date, I assumed that the book documented a rise and fall, and I was really surprised to find out that the project was still in development, but without a widely used release, after all this time. It's not really important though. "Dreaming In Code" is a journey, not a destination, and it was revealing to see that developers with great pedigrees have the same problems that I do on my projects.

There were a few quotes along the way that should have been worth saving, but in the end I'm left with these:
"People write programs. That statement is worth pausing over. People write programs. Despite the field's infatuation with metaphors like architecture and bridge-building and its dabbling in alternative models from biology or physics, the act of programming today remains an act of writing - of typing character after character, word after word, line after line. Tools that let programmers create software by manipulating icons and graphics shapes on screen have a long and sometimes successful history... But these have generally served as layers of shortcuts on top of the same old text0based code, and sooner or later, to fix any really hard problems, the programmer would end up elbow-deep in that code anyway.

People write programs

...Is programming a kind of creative writing? The notion seems outlandish at first blush. Any discipline that involves complex mathematics and symbolic logic does not seem to share the same cubbyhole with poetry and self-expression. Yet the programming field could learn much from the writing world, argues Richard Gabriel, a veteran of Lisp and object-oriented programming who is now a Distinguished Engineer at Sun. 'My view is that we should train developers the way we train creative people like poets and artists. People may say, "Wall, that sounds really nuts." But what do people do when they're being trained, for example, to get a master of fine arts in poetry? They study great works of poetry. Do we do that in out software engineering disciplines? No. You don't look at the source code for great pieces of software. Or look at the architecture of great pieces of software. You don't look at their design. You don't study the lives of great software designers. So you don't study the literature of the thing you're trying to build.'"

And Rosenberg's Law:
"Software is easy to make, except when you want it to do something new"

with it's corollary,
"The only software that's worth making is software that does something new."

Friday, April 13, 2007

RCov measurements

I'm busy setting up a Rails development project at a client site, and we've chosen to use rSpec for specification/testing, and rCov to report coverage. They work quite well together, but there's one caveat - classes that aren't loaded don't appear in the coverage report at all, so for a single class there's effectively no difference between 0% coverage (no tests at all) and 100% coverage. Of course this is an oversimplification, since Ruby loads files, not classes, but it's a good enough approximation on most projects, and there's clearly some sort of problem regardless of the details.

Our solution has been to force rSpec to load everything in app/models and app/controllers before the specs are run. We do this in the rspec_helper, and since this is loaded multiple times (on different paths) it's also useful to restrict this code so it only runs once.

First, here's the code that loads the models and controllers:


class ForceLoader
def self.run
["models", "controllers"].each do | app_component |
directory = File.join(RAILS_ROOT, "app/") + app_component
Dir[directory + "/**/*.rb"].each { |file| require_dependency file }
end
end
end


There are two things to note about this code:

  1. we use require_dependency for consistency with other Rails loading, rather than require or load;

  2. we need to ensure that the path of the file passed to require_dependency is the same as the path used by default by Rails. Ruby loading is path passed, and if you refer to the same file with two different path representations you may load it twice.


Next, let's look at the code that we put in rspec_helper.


begin
ForceLoader
rescue
require File.dirname(__FILE__) + '/force_loader'
ForceLoader.run
end


If we can't reference ForceLoader we load it and run it. Once the class is loaded the rescue code won't be invoked, so this ensures once only execution.

Hopefully this approach will give you more accurate coverage reports with minimal overhead - it's certainly uncovered at least one problem on our project so far. It can also be extended to cover other parts of your app in a fairly straightforward way.

Friday, April 6, 2007

Amazon links in Ruby

As I mentioned in an earlier post, I read a lot, and I want to be able to comment on the books I like, with links to a page about the book on my preferred book seller, Amazon. I also have an associates account with Amazon and I'd like to include that in the link, even though the last time I made any money from that was about 2001! Making the links has, frankly, been a pain the butt, but I finally dusted off my Ruby and used Amazon Web Services (AWS) to make this easier.

First I tried Ruby/Amazon, but this seemed to be using an old version of the AWS and I couldn't figure out how to do an ISBN based lookup, and I eventually abandoned it. In hindsight I should have done this earlier - the functionality I need was pretty easy to write directly in Ruby, and only the latest version of AWS seems to handle both 10 and 13 digit ISBNs correctly.

So here's my code:

require 'rubygems'
require 'hpricot'
require 'open-uri'

isbn = ARGV[0]

ACCESS_KEY = '01WXX7HHK8GBB3BFYX02'
ASSOCIATES_TAG = 'cogentconsult-20'

site = 'http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService' +
'&AWSAccessKeyId=' + ACCESS_KEY +
'&AssociateTag=' + ASSOCIATES_TAG +
'&Operation=ItemLookup' +
'&ResponseGroup=ItemAttributes,Images' +
'&IdType=ISBN' +
'&SearchIndex=Books' +
'&ItemId=' + isbn

doc = Hpricot(open(site))

author = doc.at("author").inner_html
title = doc.at("title").inner_html
detail_page = doc.at("detailpageurl").inner_html
image = doc.at("smallimage/url").inner_html

puts ''

html = "<a href='#{detail_page}'><img src='#{image}' alt='#{title}'></a><a href='#{detail_page}'>#{title}</a> by #{author}"

puts html
puts

Open-uri made the http access a piece of cake - definitely use this instead of Net::HTTP - and Hpricot was equally adept at giving me just the parts of the returned XML that I needed.

I can run this at the command line using "ruby booklink.rb someISBN" and I get the html for both an image link and a text link, that I can then paste into my web pages and edit ass appropriate. Hopefully I'll now be less reluctant to write about the books I've read.

Saturday, March 31, 2007

Code Retrospectives

I bet that most of the people who read this blog have been through a code review at some point - a session where a bunch of people get together, look at a piece of code, identify all the things they consider problems and document them. Then the developer goes away and fixes all the problems.
Usually these reviews are relatively infrequent, time consuming, and exhausting. The focus is on finding errors and correcting them, and I know that when I was having my code reviewed this way I found the process quite stressful as well.

I think this model of reviews is pretty much broken. These days I want to get "code reviews" done at least a few times each hour, whether there's anyone else around or not, and the only way to get that is to use automation. In the Java world, tools like Checkstyle, Simian and Complexian provide a wealth of checks - far more than a human team could check in any reasonable amount of time. And despite the names these checks aren't just "style" checks - they help you enforce metrics thresholds as well (which is a separate discussion). Plus there's much less emotion associated with feedback from an automated tool, and the tool has infinite patience.

Once significant chunks of what's covered by traditional code reviews have been handed off to automated tools, the humans are free to use code reviews in a different way. Instead of looking for mistakes, the team can look for opportunities to learn. Accept that the code is the way it is, that everyone was doing the best they could at the time, and review the process that created the code rather than the code itself, all the way back to the root cause. Certainly you'll find some things in the code that must be fixed before you move forwards, but lots of things will be tolerable if you can fix the process so that they don't recur.

In this context, "process" is a broad term - it includes the way you hire people, the training you give them, the tools, the incentives, the requirements; anything that might impact the final code. The Toyota "Five Whys" can be a good way to get to the root cause. (make some note in here)

At this point we've transcended code reviews - what we're doing is far more like a retrospective, focussed tightly on our code. Although retrospectives are usually associated with ends of iterations and releases, we can use code retrospectives much more often.

So instead of treating your code reviews as opportunities to find the mistakes that your colleagues have made, switch to code retrospectives and improve the process that created the code.

Thursday, March 29, 2007

Design Improvement to Design Patterns

Marty ran the Design Improvement workshop last weekend - another full house and another good day. There are some pics on the wiki, and also some blog posts from attendees.

The next workshop is Design Patterns on May 19, and we're really lucky to have secured Andy Bulka as the workshop leader. We've already got four people bidding, so if you're interested you might want to get in now.

Saturday, March 24, 2007

Commenting on ideas

I had this email exchange with a friend, and since it's related to change I thought I'd share it (plus it means I don't have to write a separate blog entry!).



Steve,


We have discussed giving feedback before and that when you start to
give it your automatically
at odds with the person receiving it.


For example, they present a shape that is a triangle and you
believe a square is better, so
suggesting a different shape automatically suggests that they are
incorrect and those that
also have supported the triangle or have not suggested another
shape are also somehow
incorrect. At least this is how I remember you explaining it to me.


Given that your at odds with the person receiving the feedback, is
there any way to give it
in such a way as to lessen the possibility of it being taken
negatively?


I could try the feedback sandwich approach but do you have any
others that you use with
success ?


If you think the feedback will not make a difference do you suggest
keeping quiet, even if
you think your expected to speak up ?




My reply:


Feedback is incredibly difficult, and success or failure can depend
as much on tone and body language as the words used.


First, you need to accept that they may be right and you may be
wrong. I guarantee that whether you accept this or not will come
across somehow. I've used to ask leading questions, until someone
pulled me up on it, and I now I try to make sure that words and
thoughts are a bit better aligned - questions when I'm in doubt,
statements when I'm not.


Maybe the first thing you need to do is better understand why they
used a triangle - "I thought of something different - can you tell
me why you used a triangle?". When you can echo back to the other
person why they used a triangle, and they nod or agree throughout,
then you're on a good track. Then rather than just say "a square is
better", maybe you can say "ok, I understand why you used a triangle,
but I'm concerned about these things as well, and I think that a
square addresses those concerns".


It's quite possible that neither the square or the triangle address
all the concerns - that you've each uncovered some overlapping issues
and some unique issues. Or you've uncovered the same issues, but have
given them different priorities. There may not be right and wrong
solutions, or even outright better or worse.


Although I don't always speak up myself, I don't think it's healthy
to stay quiet when you're asked for feedback, if you have feedback
related to the matter on hand, not general feedback like "I think
you're an idiot"! The times I stay quiet are when I don't think I can
present the feedback appropriately, perhaps because I don't have the
verbal skills, or perhaps because I'm agitated by something at the
time. I certainly need to get better at this myself (this is a case
of do as I say, not do as I do). Try not to offend people, but the
decision about whether the feedback will make a difference doesn't
really belong to you.

Thursday, March 22, 2007

Drawing the reader in

I read a lot of material - some short, some long. A lot of it is mandatory work-related reading, so I can get quite selective about the remaining pieces - if you want me to read something, you need to convince me. I'm willing to give you some of my time upfront, but that may be less than 5 seconds (I kid you not). If what I read in that period seems interesting then I'll give you some more of my time, but even then my commitment isn't open ended; you need to continually convince me to keep going (at least until I can see the end in sight). So how do you do this?

You should be able to see the solution in a typical newspaper article. The article probably has this structure:

  • the impact of the story is captured in the headline;

  • the first paragraph gives a summary of the whole story;

  • the next few paragraphs expand on the first paragraph, but still omit details;

  • the details are contained in the main body of the article


Each reader should be able to read until they've got the level of detail they need - they shouldn't be forced to read from beginning to end just to get an overview.

We have the same problems whenever we write a document presenting something complex (especially when we need someone to make a decision based on the material), and particularly when we write a resume. Make sure that the first few paragraphs contain some sort of summary, something that will convince the reader that it's worth continuing. If a resume starts with the details of the candidates current job, it better be a very interesting job, and if I'm your reader you've got less than 5 seconds to convince me. Bullet points are easy for me to scan in that time; dense text isn't. As you increase my interest and commitment, you can be more demanding of me and I'll be more tolerant.

When you're working on the web you have other structure you can work with as well. Maybe you can build something with Javascript so that the details are available only when the reader asks for them; in that case you don't need to adopt the linear, gradual descent style of the newspaper, you can make the details available wherever they're needed. You can also present sidebars, summaries and pictures that might not have a place in a text only, paper based document.

You may or may not need to give the reader a sense of closure. If you need a decision or an action, you need to make that clear early on, but you should also restate it at the end of the work. You might also benefit from a summary of the main points, related back to the original introduction. But for something like a resume you can probably get away with "here are the rest of the details" - it's expected, and the reader knows they'll only be interested in some of it, but you still should make it easy to pick one point from another.

Be conscious of this approach - see if you can spot in what you read, and bear it in mind when you're writing. Eventually you'll refine it until the transitions are seamless, and your reader will never know why they find your work so interesting!

Thursday, March 15, 2007

Building a store

I just finished watching the video of Building the Store from ClickableBliss, which explains why Mike Zornek build his own web store, and what he learned.

My notes from the presentation:

  • ELC Technologies RoR::PayPal - not a complete interface, doesn't provide express checkout, which is essential

  • vPayPal gem : never got it to work, seemed to have deficiencies, used as a reference

  • Tobias Lutke's PayPal gem - not specific to websites payment pro, related to instant payments

  • ActiveMerchant : couldn't get certain things related to PayPal to work, code submitted by contributor, not maintained. But it's now 1.0 and may work better.

  • SOAP : not used SOAP before, but was the eventual solution

  • These experiences were from about August 2006.

  • If you're going to accept confidential information in a Rails application, make sure you don't log it:

    class ApplicationController < ActionController::Base
    filter_parameter_logging "password"
    filter_parameter_logging "credit_card"
    end



Sorry if I'm cryptic - the video is worth watching :-)

Quicksilver

My Quicksilver education continues. I watched the Merlin Show on using menu items from within Quicksilver (episode 8), and thought it was a great idea (especially for Textmate, which I'm also trying to learn). But when I tried out the example in my QS, it didn't work; at least not at first. So here are the prerequisites for getting menu items to work:

  1. Activate "Enable Advanced Features" in Preferences -> Application

  2. Activate the "User Interface Access (+)" plugin

  3. Make sure that "Enable access for assistive devices" is selected in OS X System Preferences -> Universal Access. I don't have this enabled by default because I use iKey during training courses and it only works if access for assistive devices is turned off.


Hopefully that's it! But if not, Howard Melman has written an excellent Quicksilver User's Guide.

Monday, March 12, 2007

Design Improvement bids close this Friday

A reminder for anyone considering the Design Improvement workshop that bids close this Friday. We've got 12 distinct bidders at the moment, so if you're interested you should probably make a bid near your final limit rather than trying to be tactical about it.

Also a little advance warning - we're looking at running an EAT Design Patterns workshop in May, so watch out for that or let me know if you're interested in getting mail when it's announced.

Thursday, March 8, 2007

Upgrading to Webgen 0.4

I use Webgen to build my website, and I've just finished upgrading to the latest Webgen release, 0.4.2, from version 0.3.8, which was over a year old. It was a bit of a pain, and the Webgen documentation is a little lacking, so I thought I'd share my experiences.

First, I could see that I needed to change the format of my block declarations in my content pages from


blocks:
- {name: content, format: textile}
- {name: sidebar_heading, format: textile}
- {name: sidebar, format: textile}


to

blocks: [[content, textile], [sidebar_heading, textile], [sidebar, textile]]


Not a big deal, though I needed to do it in every file (I need to find a way to get rid of this duplication). I thought that would be enough to get me running, but to my surprise every page generated the message "Invalid structure of meta information".

The problem was that my files (originally created in Windows and now living on my Mac) had lines ending in \r\n and Webgen didn't like this. Things worked better when I changed each file to have lines ending simply in \n.

Next I had to replace references to block content in templates from from
{block_name:}

to
{block: block_name}

After that I was 90% of the way there, with all the standard stuff covered. The next step was to handle two places where I'd used included content.

Webgen 0.4 changes the order of the steps in the evaluation of page files. The new order is:

  1. convert to HTML;

  2. then ERB;

  3. then webgen tags.


In earlier versions I believe the steps were performed in the reverse order. This change in ordering broke some of my "custom" code, where I was including common Textile content into a number of pages by reading it from a file via ERB. Since ERB is now run after the conversion to HTML from Textile I was getting the included Textile content rendered as HTML without translation.

One thing I was using this for was to include a common sidebar. However Webgen now supports nested templates, and that's a better way to solve the common sidebar problem. I now have a template that looks like this:


---
template: ../default.template
--- content
{block: content}
--- sidebar_heading, textile
Services
--- sidebar, textile
<div class="training">
* <a href="{relocatable: eat.page}">Easy Access Training</a>
* <a href="{relocatable: index.page}#softwareDevelopment">Software Development</a>
* <a href="{relocatable: index.page}#coachingAndMentoring">Coaching and Mentoring</a>
* <a href="{relocatable: index.page}#training">In-house Training</a>
</div>
For enquiries regarding any of our services, please <a href="mailto:info@cogentconsulting.com.au">email us</a>.


Pages that want the common sidebar use this template and only need to provide the body content.

The other thing I was using an ERB include for was to provide a common set of textile link aliases (things like [three_rivers_essay]http://www.threeriversinstitute.org/steve%20hayes%20essay.htm). These need to be in the same file as the textile source at the time it's converted to HTML which is before either ERB or tags are handled, so it looked like I was out of luck. My solution was to write my own tag, called "site", which provides the same sort of functionality. A reference to the tag looks like {site: three_rivers_essay} or {site: {name: three_rivers_essay, text: "a different piece of text"}} - I'll include the plugin code at the end of the post.

It's good to see Webgen in active development, I like nested templates, and it's quite easy to write plugins. It would be good to see better documentation (hopefully that will come from the new activity as well) but Thomas Leitner provides excellent support via the forums.





class SiteTag ["Suncorp-Metway", "http://www.suncorp.com.au"],
"three_rivers_essay" => ["software tyranny", 'http://www.threeriversinstitute.org/steve%20hayes%20essay.htm']
# and so on
}
infos( :name => 'Custom/Site',
:summary => 'Return standard sites and labels')
register_tag 'site'
param('name', nil, 'The name of the site that will be linked to')
set_mandatory('name', true)
param('text', nil, 'The text that will be displayed for the link')
def process_tag(tag, chain)
return self.link
end
def link
name = param('name')
definition = @@definitions[name]
raise('Could not find site named ' + name + ' in ' + @@definitions.to_s) unless definition
url = definition[1]
text = param('text') || definition[0]
return "<a href='#{url}'>#{text}</a>"
end
end

Wednesday, March 7, 2007

Maven doesn't work for me

I sometimes joke that I don't know anything at all, I just know people who do know things and ask them what to do. The joke is that this is partly true - in software development it's impossible to know everything, so it's important to rely on people you trust. Which brings me to Maven 2.

I've had a number of people that I respect recommend that I start using Maven 2, so I thought that I would try it on a project that's just starting out. On the other hand, I heard from people on related projects that they'd tried it without success. No problem, I thought, I've got access to some people who have used it, who have a fairly good idea of what I'm after in a build, and I'll be able to get some guidance from them. Given that I had conflicting advice and I was the one advocating Maven, I decided I should do the implementation myself rather than delegating the potential pain to someone else, and that's what I did.

I've spent a day and a half on this and got something that's working ok, but when I get to work today I'm going to back it all out and go back to the Ant-based approach that other teams are using. Why? Because although Maven 2 may work, I can't make it work the way I want it to (the "I" in that sentence is quite important).

First, I love the Maven 2 dependency mechanism. It's great, and even though Maven doesn't rock my world the experience has encouraged me to go and look at Ivy (though that's in the future). My problem is that Maven 2 wants me to conform to its view of the world, and that doesn't match what I want to do. That would be fine if there were plenty of hooks to let me do it my way, even if that was expensive, but either these hooks are missing or the documentation on how to use them is nonexistent or inaccessible (and it's probably a mix of all of these).

So what do I want my build to do that's "non Maven"?

  1. I want to run separate unit and integration tests in one project, and have reports (test results and coverage) for both of them, and I only want to run the tests once to get it. There is a note in the documentation that says that Cobertura will force the tests to run twice and that this will be fixed in future, but every configuration I tried ended up running the tests even more than this.

  2. I want to be able to package the code with instrumentation, run integration tests using this code in a WAR, and measure the coverage.

  3. I want Checkstyle (and Simian and Complexian) to run over all my code, including the tests


I tried separating the integration tests into a separate module and deploying a jar from the "core" module to the integration module, but that didn't give me coverage of the integration tests because the code in the jar wasn't instrumented. The alternative seems to be to compile the code again so I can run the integration tests over it - this seems like a great big hack, and seems to predict more great big hacks down the way.

The idea behind Maven 2 is great, and if you're happy with the outcomes that's great, but the current implementation and documentation doesn't provide the level of customisation I'm looking for.

If anyone has a POM that handles the three points that I would like in my build, than I would be more than pleased to receive it and blog about my experiences using it. I want Maven 2 to work for me, and it's disappointing that it doesn't.

Tuesday, March 6, 2007

Tasmania Trip

Not long ago I had a week's vacation in Tasmania. If you're interested you can read a little more on my personal blog.

Monday, March 5, 2007

Carbon offsets follow up

Following the post on carbon offsets I received an email from Climate Friendly. I'm impressed that they're watching the blogosphere (my wife hates that word), and that they're willing to participate in even small discussions like ours.





I've read the discussion and wanted to mention that the approach that Climate Friendly takes to the issues you're discussing is to communicate a complete message covering efficiency, renewables and offsets plus advocating very strong government policy. For example a number of our customers have a Prius, run their home on Green Power and offset their car emissions, while others do whichever of these they can afford today. Our interest in promoting efficiency is evidenced by the fact that we have many of Australias leading energy efficiency companies, engineers and architects as customers. Picture sof the buildings they have designed are in the URL below. One of these cut emissions 60% by efficiency measures and then used our GreenPower plus carbon offsets to achieve Climate Neutral status. We are very active promoting the achievement of Climate Neutrality through a combination of efficiency, GreenPower and offsets.

My contribution to the more general question of how offsets can be meaningful in an overall context is summarised in an article sent to New Internationalist regarding their article last year about carbon offsets.
URL is
http://www.climatefriendly.com/pdfs/climate%20friendly%20-%20%20Reduce%20Renew%20and%20Offset%20strategy.pdf

This covers voluntary action but we need regulatory action too, urgently.

An article advocating strong government policy is available at http://www.climatefriendly.com/newsletter/goodpolicy.php

Kind regards
Joel Fleming | Managing Director | Climate Friendly

By the way for our emission calcs we are very careful to use the correct emission factors for the baseline case that our projectrs avoid.
For the NZ wind project the carbon credits are based on an "Avoided" gas power plant ..which creates a very low quantity of credits. This means that if you buy carbon creidt from us its not overclaiming by using "brown coal" baseline.