2008-02-29

Grails app.version & plugin utopia

I was catching up on my reading recently when I came across
this post. The technique Darryl is using to show application version numbers to his users is:
v${grailsApplication.metadata.'app.version'}

Which makes perfect sense to me. In fact, I don't understand why it's not in the Grails defaults to show the version number. If you add that line to your grails-app/views/layouts/main.gsp or add the version number to the default title every page would get a version stamp. I can't see how it would be obtrusive either since you could remove it or change where it was placed yourself later.

The other news that I think is interesting on aboutGroovy.com is the Selenium plugin for Grails. This is indicative of what could be a major selling point for Grails. It can easily make use of all kinds of existing Java tools as plugins. And do it today.

But, it's not only that you get to use these tools, Grails provides an interesting distribution mechanism for the tools as well.

You install grails plugins from the command line and you list out available plugins the same way for example:

$ grails list-plugins

Welcome to Grails 1.0 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /usr/local/grails

Base Directory: /home/shawn/workspace/myproject
Environment set to development
Running script /usr/local/grails/scripts/ListPlugins.groovy
[mkdir] Created dir: /home/shawn/.grails/1.0/plugins
Plugins list cache does not exist or is broken, recreating ...
Plugins list cache has expired. Updating, please wait... ...

Plug-ins available in the Grails repository are listed below:
-------------------------------------------------------------

acegi -- No description available
aop -- No description available
autorest -- No description available
axis2 <0.1> -- Add Web Service support for Grails services using Apaxhe Axis2.
cache -- No description available
cas-client <0.2> -- This plugin provides client integration for JA-SIG CAS
code-coverage <0.7> -- Generates Code Coverage reports
converters <0.3> -- Provides JSON and XML Conversion for common Objects (Domain Classes, Lists, Maps, POJO)
dbmapper <0.1.7> -- Database relation to domain object generator
dbmigrate <0.1.5> -- Database migration tasks
djangotemplates -- No description available
dojo <0.4.3> -- Provides integration with the Dojo toolkit http://dojotoolkit.org, an Ajax framework.
dwr <0.1> -- This plugin adds DWR capabilies to the services in a Grails application.
eastwood-chart <0.1> -- This plugin wraps JFreeChart's Eastwood servlet for Grails app
echo2 <0.1> -- Echo2 capabilities to Grails applications
ext-ui -- No description available
fck-editor <0.3> -- FCKeditor
feeds <1.2> -- Render RSS/Atom feeds with a simple builder
flex <0.1> -- Provides integration between Grails and Flex
google-chart <0.4.3> -- This plugin adds Google Chart API features to Grails applications.
gwt <0.2.4> -- The Google Web Toolkit for Grails.
i18n-templates <1.0.1> -- I18n Templates
ivy <0.1> -- The Ivy Dependency Manager for Grails.
jasper <0.5> --
jcaptcha <0.2> -- Grails JCaptcha Plugin
jcr -- No description available
jms <0.3> -- This plugin adds MDB functionality to services.
jsecurity <0.1.1> -- Security support via the JSecurity framework.
jsf -- No description available
laszlo <0.6> -- OpenLaszlo plugin for Grails
ldap <0.1> -- Adds easy to use LDAP connectivity
liquibase <1.5.2.0> -- LiquiBase Database Refactoring for Grails
modalbox <0.1> -- This plugin adds the ModalBox to your Grails applications.
mondrian <0.1> -- This plugin installs Pentaho Mondrian into your Grails application.
ofchart <0.5> --
portlets -- No description available
quartz <0.2> -- This plugin adds Quartz job scheduling features to Grails application.
radeox <0.1> -- A plugin for the Radeox Wiki-render engine to allow easy markup and cross-linking.
remoting <0.3> -- Adds easy-to-use server-side and client-side RPC support.
richui <0.2> -- Provides a set of AJAX components
scaffold-tags <0.7> -- Adds tags to support fully-customizable & dynamic scaffolding
searchable <0.4-SNAPSHOT> -- Adds rich search functionality to Grails domain models.
staticresources -- No description available
webtest <0.3> -- A plug-in that provides functional testing for Grails using Canoo Web Test
wicket <0.3> -- Provides integration between Grails and the Wicket framework
xfire <0.7.4> -- Add Web Service support for Grails services using XFire.
xmlrpc <0.1> -- This plugin adds XML RPC functionality to GRAILS
yui <2.5.0> -- Yahoo! User Interface Library (YUI)
yui-widgets <0.1> -- Yahoo! User Interface Library (YUI) Widgets

To find more info about plugin type 'grails plugin-info [NAME]'

To install type 'grails install-plugin [NAME] [VERSION]'

For further info visit http://grails.org/Plugins


This is interesting not because this is new for Java programs, but, because the Grails plugin repository is now a Java Software distribution system. I think we'll see this eventually morph into something like a Gentoo or CPAN type distribution system where the real "all-stars" of development are known for having useful or interesting plugins.

The problem is. Even now this list is getting big. One of the attractions to Grails for new developers... like it or not... is that there are fewer choices. It's kind of funny but too many choices (as Scott Davis has pointed out in his "Paradox of Choice" talk) leads to people making no choice at all.

So already there are getting to be too many choices in Grails plugins. Now, admittedly, if you stuck to 1.0 and above releases you actually have only 4 plugins to choose from. But, very soon many of those "beta" plugins will be 1.0 and either way you still see them... still deal with the choice. This is an interesting problem that is going to be coming very rapidly for Grails. How do you deal with all that adoption and all that interest.

I think it will be very vital how the Grails team handles the next 18 months. They will have to find a way to deal with all the plugin contributions they get and how to limit choice intelligently.

Will they go the CPAN route? I'd like that since CPAN was (and technically still is) the best feature of Perl. Just as Ruby Gems is also a vital feature of Ruby. But, Gems lacks some of the features that made CPAN so popular. CPAN has code author based search and other web search features that allow you to read through PerlDoc (the Perl version of JavaDoc) for each module. The author recognition was not vital to Perl or CPAN but I think it helped authors to make contributions.

Will they choose an elitist mentality and have "levels" of plugins which are gold, silver, bronze? Sort of a Gentoo approach which was the best feature of Gentoo. Or perhaps it's too soon to think about yet. After all there aren't too many plugins yet...

At some point we'll need to see some categorization from the command line of plugins. We'll need search features for plugins. And, we'll need a mechanism for at least three levels of plugins... "production", "test", and "development" because we will need to allow for beta code to be distributed... and for developers to work on advanced features that rely on other plugins that aren't even released yet.

We'll need to do some level of OSGI in Grails... at least something that handles plugin dependencies and manages them. At some point the Grails ecosystem could grow large enough that you could have plugins that require other plugins. That could get very interesting.

2008-02-25

Logging in a Unit Test of a Service in Grails

Here's the scenario: You've got a grails project and you have a simple service you'd like to test. Let's say it's just something like:

class MyService {
boolean transactional = true
def myMethod() {
log.debug "MyService.myMethod() was called!"
}
}


If you were to hook up a quartz job to this service and then run "grails run-app" to test your service you would see the service happily chirruping away. Now if you were using Eclipse or some other IDE you might try to write an integration test of some kind and run that test from your IDE. You'll get an automatically generated test for that service if you used the grails commands... let's say you edit it so the test looks like:

class MyServiceTests extends GroovyTestCase {
void testMyMethod() {
def myService = new MyService()
myService.myMethod()
}
}

Now try and run that from your IDE. The test may fail with...

groovy.lang.MissingPropertyException: No such property: log for class: MyService

... what to do?

Grails is injecting the "log" property for you. That means if you want to test that class outside of Grails you'll need to do the same. So, you could do this:

import org.apache.log4j.*
class MyServiceTests extends GroovyTestCase {

def myService
def log

void setUp() {

// build a logger...
BasicConfigurator.configure()
LogManager.rootLogger.level = Level.DEBUG
log = LogManager.getLogger("MyService")

// use groovy metaClass to put the log into your class
MyService.class.metaClass.getLog << {-> log}

myService = new MyService()
}

void testMyMethod() {
myService.myMethod()
}
}


Now if you run this in your IDE you'll see your service pleasantly chirruping away in your IDE console window.

2008-02-21

Why do we write software?

I feel I have to ask: Why do we write software?

I ask this because I think the why gets lost too easily. I've recently worked on a project that modeled a name and email address in JSON like this:

[
["PRXYY_298_NAFR","Bob",""],
["PRYXY_LARFN","Roberts",""],
["PRH_2810_EMA","bob@email.com","email"]
]

... why do that?

I suspect that this kind of tri-associative array allows for type information to be included in a JavaScript model. The problem is that the data thingy (because that sure ain't no object) is no longer human readable.

But what is worse is exposing this data model in an API to use as a service. This is basically screwing over the integration developer. I can see how you could have easily modeled the JSON object as:

{
PRXYY_298_NAFR: "Bob",
PRYXY_LARFN: "Roberts",
PRH_2810_EMA: "bob@email.com",
}

... and then had a server-side mapping map "PRH_2810_EMA" to "email" on the fly. Even better would have been to use human readable names like "email" and map those to values like "PRH_2810_EMA" if you needed to server side.

Why do it?

I suspect this makes the original system designer's job easier on some level. No thought was given to system integration or how to make data import/export easy. Instead we are working with something that was easy to code but hard to use.

And, that circles back around to "Why do we write software?"

It clearly isn't to make the programmer's life easier is it? The programmer should be trying to make their user's life easier. After all isn't that why a programmer even has a job?

I mean "programmer" from the perspective of the one writing the program or API... and user being the person who is going make use of this product later. That means as a programmer I'm the user of PHP, Python, Perl, Ruby, Java, Scala, Groovy, or other technology. It means that if I write Rails, Grails, Maven, CakePHP, JSF, or other framework I'm using a programming language and creating tools that other programmers will use themselves. The role of programmer and user can switch. I could write an API then have to use it later.

So you would think that being a user of programming tools themselves the designer of our tri-associative array would have some sympathy... empathy... care for... the user of their tool since they are so very similar people. But instead of thinking about why the tool exists and who is going to use the tool our programmer chose the path that would give them the easiest success.

I don't like that very much.

As programmers our job is to do the hard things so our users don't ever have to care. The simpler we can make very hard things seem the better we are doing. For example Google probably has one of the most powerful and complex search engines on the planet. It is clustered and redundant and complex and beyond many programmer's or user's comprehension. Yet to use it you type text in one box and hit one of two buttons.

The user experience is simplified to almost a ridiculous level.

The Macintosh is like this too in places. And, so are some places in Windows. And, so are some places in Linux. Each one of these systems has traded easy in one place for hard in another. For Macintosh... hardware is harder... for windows security is harder... for Linux desktop user experience is harder. In Macintosh what does work works well and without a manual... in Windows you never wonder "will it work with windows?"... in Linux you never wonder if it will scale well or stay secure.

Each has taken a specific user experience and simplified that particular "most important" case.

So I ask you: What is your most important case? Why are you writing this software? Why will anyone bother to pay you? What would cause them to not pay you?

Features should be designed and implemented by order of priority.

So maybe my tri-associative-array friend never saw integration as a priority. But, we should have. And that should have meant we didn't pay him and instead paid for someone who aligned with our priorities.

And that is my big thought for today: Ask why you are writing software and ask whether you should write it at all first.

2008-02-17

The Singularity is Ni

Recap: The technological singularity is the moment when human intelligence finally exceeds that of machines.

Wait. Sorry.

The technological singularity is the moment when intelligence finally exceeds human machines... no wait.

The technological singularity is the human that finally exceeds the moment of machines.

Uh, that sounded profound at least.

Sorry. I've taken such a long break from thinking deeply I've forgotten how. I'll be back soon.

.... and what is that thing up there?

2008-02-06

Grails 1.0 is out

It looks like Grails 1.0 is officially out. If you don't know what Grails is go check it out now: http://grails.org/.

2008-01-27

Paradox/Parabox of Choice

A late night post due to a late night. Some things are bothering me and I decided to put them in words.

Consider this post on slashdot this is problem is real and a real burden to many shops. If you were a LAMP shop and that 'P' was Perl and then you add PHP because marketing wants something... and then you add RoR because somebody thought it was cool. Then you add Java to the mix. How many platforms are you supporting? How many different server configurations... and what is that costing you?

Even if you are a Java shop which kind of Java shop are you?

Both Neal Ford and Scott Davis talk about this idea called "The Paradox of Choice." The problem is that in Java land there are far too many choices between frameworks for anyone to comprehend and deal with. The paradox is that when given too many choices people can't make any choice.

Java has so many frameworks for so many different environments that it has become a joke amongst techies: "How many Java frameworks are there? Dunno, a new one comes out every second so what time is it?"

In typical tongue-in-cheek fashion I will instead refer to The Farnsworth Parabox of choice. This is a technique that I think will help. See the Parabox is a box that Professor Farnsworth put the universe inside... or is it a box with a universe inside it? Anyway at the end of the episode the Professor had created a box that contained our universe. Grails is your box. Grails contains the universe of Java but it fits neatly into a box.

Think inside the box. Check to see what works well with Grails. No seriously. If you use the Grails "defaults" you can effectively eliminate the need for making dozens of choices. Which framework to use? Well, what is the Grails default? Spring it is. Which application server to use? Which one comes with Grails? Jetty it is.

When you reach the edge of the box or can't fit a need you have into that Groovy/Grails box that's okay because the whole universe of Java is inside that box too. All you have to do is reach down deeper beneath the Groovy skin and dig into Hibernate, Spring, or EJB3 and that whole cosmos is ready and waiting for you. Conversely, if you are comfortable floating around in the gigantic universe of Java then you can reach down into the box and take out what you need.

Grails is the Java universe in a box.

2008-01-19

the vessel of ideas

Earlier I said:
The word is the vessel of ideas. The written word is the preservation of ideas. The computerized word is the execution of ideas.

Programming is about thinking. It is nothing else. Programs only execute the rules we believe to be true as we have written them down. What do we know? What do we believe?

Take the idea of person, parent, or child these are very basic ideas on the surface but surprisingly few people understand in context the ironic trap that the idea of an
Object then introduces. In the sense of a program...

An Object is a thing.

An Object may have things.

So it seems natural that a parent is a person and a child is a person. That makes sense. A parent has children. A child has parents. That all makes perfect sense. In the now.

We might say:

class Person {
def name
def birthday
def gender
}

... to say a person has a name, a birthday, a gender...

class Parent extends Person {
static hasMany = [children:Person]
}

... to say a parent has one or more children ...

class Child extends Person {
Person mother
Person father
}

... to say a child has one and only one mother and one and only one father... (in the real world we would probably fold Child attributes back into Person)

The terms I've used so far are more or less permanent. Once you become a parent you are never not one. Once you become someone's child that status is never removed. But sometimes there are statuses that are more flexible that aren't modeled correctly by using the "is a" idea. This becomes more apparent when dealing with a term such as employee.

A person is an employee as long as they are employed. You might be employed, unemployed, and re-employed multiple times with the same employer. So should "person is a parent" be modeled the same as "person is an employee" or is being an employee different?

Could it be that ...

class Employee extends Person {
static hasMany = [employers:Employer]
}

... such that we we would add and remove employers over time to an employee?

But that doesn't really get at the idea of being an employee. You are one from one date to another and you might be again. So really you would want to say:

class Employment {
Person employee
Employer employer
Date start
Date end
}

So that a person is an employee if a person has an employment that has a start before now and an end after now. So many other relationships turn out share this same kind of temporal basis. Sadly, marriage does too... some of the data I have to model deals with people who have children and get divorced. The parent-child relationship is unbreakable and begins on the date of birth of the child. However, marriages don't work that way and at least once we've had the problem of modeling a marriage, divorce, and re-marriage. The systems can't handle that idea because they weren't built to hold it. They are poor vessels for these ideas.

It stands to reason that the attribute of being something when it comes to people is not in fact the same as being something when it comes to objects. People are objects in every sense but the being is not the same. A person has attached to them attributes ... like tags more than attributes ...which makes them one thing or another.

The relationship itself is an entity or an object.

The person is an employee by the virtue of possession of a relationship. Once in existence the relationship of employment carries its own being. It has its own data, attributes, and validity independent of the employee or employer.

Likewise the idea of a relationship between people carries similar intrinsic existence independent of the people. For example parent. The person as an object is not really modified but rather a new external relationship is created. In this case a child is created that then points back to the parent.

That means the "class Parent" is actually redundant. A person is a parent if any other people point back to them as a mother or father. If you wanted you could add a deceased date that would remain unused inside the person class and leave it undefined during life and set after death. But that's getting into the morbid.

Consider the employee again. This is a person object who has a record of employment. The employment is distinct and independent of the person. The relationship itself can have attributes without involving the people.

This is all pretty basic but if you continue to expand these ideas shifting your attitude about what an object is you find that mapping objects and relationships starts to get easier. You get to a model that has fewer impedance mis-matches with a relational database for example.

If the vessel will not hold your ideas change the vessel not your ideas.