Monday, 26 March 2012

Programming and premature optimization

I recently watched a lecture by Jonathan Blow, which can be found here. In it he talks about the kinds of challenges that you have to go through being an independent game developer. The main point to take away is that you really have to take a holistic view of the whole "business" and not just the "beauty of computer science" bits which programmers tend to focus on. Once of the main points he covers is to avoid at all costs the sin of premature optimization. The argument goes that if you spend too much time looking for the "perfect" way of doing something, you're likely going to over optimize it and have both wasted your own time on a problem, where you won't get the return on effort that you needed and ended up with code which can't be easily reused.

One of the ways that he gets this message across is to take a look at one of his games, Braid, which it turns out is approximately 90,000 lines of code. He makes the point that the industry average for "lines of code" per programmer, per year is 3,250. At this rate, it would take some ridiculous amount of time, like 28 years to produce a game. So, in order to launch a game by yourself you have to be "super productive" and spending time on anything which won't lead to the game launching (like implementing complex algorithms, which only optimize the game by 0.5%) will without a doubt result in failure.

It's a compelling point and one that can be seen at work in the real world. It's often not the "best" code that ends up being successful, but rather code that ships. The trade-off I guess is that this "ship first" mentality means that a lot of the time, the user ends up with poor quality code, buggy and resistant to upgrades.

Thursday, 9 February 2012

Converting param values in Grails

There are some cases in Grails where you want to compare values as Integers instead of the default String objects. There are two ways to do this. The first is to use either the "parseInt" or "valueOf" methods which are original Java methods. The other way to skin this cat is to call the "int()" method on the params object:

if(Integer.parseInt(params.user.id) != user.id){
...
}
if(params.int('user.id') != user.id){
...
}


There are other methods which the params object has to easily convert HTTP post values to well known data types, such as:

param.short(...)
param.byte(...)
param.long(...)
param.double(...)
param.boolean(...)


Another nice feature is that these methods accept a second optional parameter, which is the default that the value is set to, in the case that there is an error in the conversion:

def price = prams.float("seventy", 0.0)

This behaviour is documented in the Grails documentation here. Although, there doesn't seem to be a comprehensive list of the methods available at the time of writing.

STS/Eclipse version control plugins

STS/Eclipse has a number of plugins which make it easy to work with your version control system right in your IDE. Which one you install largely depends on which version control system you're working with.

If you're working with Subversion, you'll want to use the Subversive plugin. There is also a Subclipse plugin which apparently does the same thing, but I haven't had time to try it out as I've been quite happy with Subversive and if it's not broken...

If you're working with Git, you'll want to use the EGit plugin. I've used this plugin to hook up my projects with GitHub and haven't had any major dramas with it so far.

Wednesday, 8 February 2012

Grails - Setting failOnError globally

One of the small annoyances with Grails that I've found is that the application doesn't fail when a call to the "save" method fails. One of the ways to fix this is to pass the "failOnError" parameter to the save method, set to true:

def book = new Book(title: "The Shining").save(failOnError: true)

However, this gets annoying, having to pass the parameter every time that you call the "save" method. A solution is to declare it as the default setting and forget about it.

This can be done in Config.groovy, by adding the following line:

grails.gorm.failOnError=true

You can also add this configuration to specific packages, in case that you didn't want the configuration to apply to all of the packages used in your application:

grails.gorm.failOnError = ['com.companyname.somepackage','com.companyname.someotherpackage']

From: http://grails.org/doc/latest/guide/conf.html#configGORM

Tuesday, 7 February 2012

Override the toString method in Grails

The Grails framework is pretty smart in that if you have objects that are related to another object, it will allow you to associate an object at creation time. For example, if you had an User class, which had a "hasMany" relationship with the Post class, when creating a new Post object you would see a drop down allowing you to select a User:


Note that this is assuming that you've used the "generate-all" command to create the default scaffolding. The screen listing the Posts also shows the User:



However, as we can see from the above screenshot the values in the drop down and the User field don't seem to make much sense. The reason for the values are that by default the scaffolding generator calls the "toString" method on the object. Which is set to return the class name of the object, plus it's unique id. While this makes sense to have as the default, we need to change it in order to make it easier for people to read.

Fortunately, changing it is quite straightforward, with us only needing to define (override) the toString method. Simply add the following to the User domain class:

String toString(){
  return username
}


After putting this into the User controller, restart the grails application and you should see the usernames of the users in the drop down when creating a new Post:


This works for any class that you can think of. Simply override the toString method to make it more presentable to the people using the site. I do this almost automatically for all of my domain classes.

Saturday, 28 January 2012

How to setup Apache as a Tomcat proxy

In this post we're going to setup Apache to act as a proxy for the Tomcat application server on Ubuntu. First off we need to install the "tomcat6" package from the Ubuntu repositories, which is as simple as:

sudo apt-get install tomcat6
and answering "Y" to download Tomcat along with all of its dependencies. To make sure that the Tomcat server is running, try to open up port 8080 on the machine in your browser. If all is well you will see the Tomcat server Welcome page. If not, you may need to start up the server, which can be done with:

sudo service tomcat6 start

Next we need to install the Apache HTTP server, which "apt-get" also makes easy for us:

sudo apt-get install apache2

Again, just enter "Y" when asked whether to download the package and all of its dependencies.

In order to enable Apache to act as a proxy for Tomcat, we're going to need to make use of the "proxy" and "proxy_http" modules. Unfortunately these two modules don't come enabled by default, so we're going to have to enable them and restart apache for the changes to take effect:

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo service apache2 restart


Now we need to tell the proxy module how to proxy the requests and where to proxy them to. For this I've created a "tomcat-proxy" file under /etc/apache2/sites-available/, which we're going to enable using Apache's a2ensite command. The file itself looks like the following:

ProxyRequests Off
ProxyPreserveHost On
ProxyTimeout 1000
TimeOut 1000
#
# Configure the mod_proxy
#
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/


After editing the file we enable the site and reload Apache's configuration:

sudo a2ensite tomcat-proxy
sudo service apache2 reload


And that's it! If everything's gone to plan we should be able to hit up port 80 on our server and get the Tomcat welcome page.

Note that this isn't the only way to configure Apache as a proxy. A more sophisticated way is to make use of the AJP protocol/module, which is custom designed to work with Tomcat.

To get Apache proxying to Tomcat using the AJP protocol, we have to enable the Apache module and restart Apache for the changes to take effect:

sudo a2enmod proxy_ajp
sudo service apache2 restart

Next we have to enable the AJP connector in Tomcat. This is done in the /etc/tomcat6/server.xml file. If you edit this file you'll need to uncomment a line, which looks like:

<connector port="8009" protocol="AJP/1.3" redirectport="8443"></connector>

and restart Tomcat:

sudo service tomcat6 restart

The next step is to simply go back to our configuration file under /etc/apache2/sites-available/tomcat-proxy and change the protocol and port of the URL's we supplied the ProxyPass and ProxyPassReverse directives:

ProxyRequests Off
ProxyPreserveHost On
ProxyTimeout 1000
TimeOut 1000
#
# Configure the mod_proxy
#
ProxyPass / ajp://127.0.0.1:8009/
ProxyPassReverse / ajp://127.0.0.1:8009/


You'll notice we've replaced "http" in the URL with the custom "ajp" protocol. Restart Apache and hitting port 80 on the server should redirect you to the Tomcat welcome page as before.

What's the difference between the two approaches to proxing? Functionally there's not really any difference that the user gets to see. However, the AJP is a binary protocol, compared to the regular HTTP proxy method that the first approach uses. This should mean less data passed between the proxy and application server as well as lower latencies. Look out for a future post benchmarking the two approaches to see what the real-world difference in performance between the two approaches is.

Thursday, 26 January 2012

How to export your Blogger posts to Wordpress

I've been trying to export my Blogger posts to Wordpress for some time now. The reason was to assure myself that if in the future I wanted to migrate away from Blogger for whatever reason, there was an easy way to transfer all of the content to an alternative system. In order to do this, I was trying to get the Blogger Importer plugin to work for ages, but it constantly errored out, giving a message about Google denying the request due to it being malformed.

I had almost given up on finding a way to import the content, when a google search led me to the "Importing Content" section of the Wordpress Codex. This was useful as it lead me to this page:

http://blogger2wordpress.appspot.com/

which usefully converts your blogger export file into the Wordpress format and gives it to you as a downloadable file. After downloading, I just went to the "Tools", "Import" section of the Wordpress admin console, selected the "Wordpress" link, installed the plugin, selected the file and viola! The posts were imported along with the images which had been saved as attachments. The only missing feature that I've found is that the import didn't import the labels that accompanied each post.