Software dev, tech, mind hacks and the occasional personal bit

Category: Technical Page 14 of 15

Using floating point variables to represent money => not a good idea!

I was reading through some code the other day and was surprised to find that it was using doubles to represent dollar amounts. Reason for the alarm bells is that doubles and floats cannot accurately represent many decimal fractions (eg, 0.1), since doubles and floats internally work with powers of 2 rather than powers of 10. These inaccuracies are likely to lead to significant errors, especially when performing arithmetic (eg, adding up a table of dollar amounts). See this IBM article for a more in depth explanation and examples. The solution is to use types that work with powers of ten internally. In C#, you can use ‘decimal’ and in Java or Ruby, ‘BigDecimal‘, to avoid these problems.

AntiPattern: BusinessObjects in the driving seat

When you have a rich domain model with a business object centric design, and a Windows forms GUI, it can be very tempting to start putting significant process logic in the business objects. After continuing along this path a little further, you may realise that the process needs some sort of user input, and you use events or some sort of notifier pattern to gain user input required by the process, while still maintaining layering in terms of referencing. Then additionally you may need to access some sort of external service.

Here is an example:

class Order : BusinessObject
{
  public void SendOrder(INotifier notifier)
  {
    if (ReadyForDelivery ||
        notifier.Confirm("Are you sure you want to send order lines? They are not ready for delivery."))
    {
      OrderLine[] orders = GetLinesToSend();
      foreach(OrderLine line in Lines)
      {
        SendLine(line); // send line using a web service?
      }

      Notify("Lines sent successfully.");
    }
  }
}

interface INotifier
{
  void Notify(string msg);
  bool Confirm(string msg);
  OrderLine[] GetLinesToSend();
}

I would like to suggest that this is an anti-pattern and a trap. Although there is no direct reference from the Business Layer to the GUI layer (INotifier is implemented in GUI and passed down), the Business Layer now requires the ability to stay instantiated, pause while waiting for responses from the notifier, and then continue execution. This will work for rich client applications, but not in a stateless web environment. The ideal of being able to swap in/out the GUI layers on top of the Business layer is now compromised.

Instead, it would be possible to drive form the GUI layer, and call a service to send the Order Lines. In pseudo code below:

void SendMenu_Click(...)
{
  if (Order.ReadyForDelivery ||
      MessageBox.Show(...) == DialogResult.Yes)
  {
    using (ChooseLineForm chooseLineForm = new ChooseLineForm(Order))
    {
      chooseLineForm.ShowDialog()
    }
    SendingSevice.SendLines(chooseLineForm.selectedLines);
    ...
  }
}

If the logic in the GUI layer became much more complex, it may be a good idea to pull it out into its own class (eg, LineSender). This class would be a type of GUI level controller, responsible for orchestrating the send process.

Using this approach, there are a number of benefits:

  • BusinessObjects have no reliance on GUI implementation, so can be used for Rich Client and Web Client indiscriminately.
  • Web developers are free to implement the user input process in stateless way more appropriate to their platform.
  • Functionality for sending Order lines (some sort of integration with a web service?) is pulled out into a service class which can be reused elsewhere (potentially sending other types of objects?) and unclutters the Order business object and removes its dependency on an external service.
  • Code is simpler and easier to follow.

In Defense of Simplicity AND Complexity

Simplicity and complexity seem to have become hot topics for some of my favourite technical bloggers of late. These fine people have taken the view that things should be either simple or complex. Right, seems logical, these are opposites. However, I would like to suggest that in a well designed appliance which addresses a complex process, it should have both a simple AND a complex interface.

A couple of years ago, I bought a LG “Fuzzy Logic” washing machine. It has lots of buttons and settings on the front and one big button that says something like “Start”. 97% of the time, I throw in my washing, some detergent and press the big start button, and the washing machine works out all the settings, displays them and then starts. In the 3% of the time when I want to do something different (eg, just a rinse), I use the more complex part of the interface to change the ‘cycle’ settings.

Recently, I bought an IXUS 65. It’s a lovely digital camera, and it provides both a complex and a simple interface. As soon as I put in the battery, I was able to take pretty nice pictures by just clicking the big button on the top. No problem, I was very happy. Over the next few days, I glanced through the manual and fiddled with more complex settings for ISO, colour etc. However, in 95% of shots, I simply want to click the one big button that takes a nice auto-everything picture. It’s only occasionally that I want to change the settings to achieve a particular effect or to override a mistake in the auto settings.

To conclude, I think that my talented fellow bloggers are all right. People like complex interfaces and simple interfaces, just at different times, for different tasks. The best gadgets and appliances offer both.

Pandora – Streaming music

I’d like to point my readers to Pandora, a streaming music service which lets you define multiple channels for the different types of music that you like. You start each channel with a seed, which is a song or artist that you like. The service chooses songs similar to this and you then mark them as thumbs up or thumbs down, thus refining the channel more towards your musical taste. It is Flash and browser based, no downloads necessary. Sign up is easy, and the service is free, though add supported. Highly recommended!

Windows Crash: multiple_irp_complete_requests Stop: 0x00000044

Thought I’d do a bit of a defrag on my old Windows 2000 box. A few minutes in, I got a blue screen:

multiple_irp_complete_requests
stop: 0x00000044 (0x852CCE68, 0x00000D39, 0x00000000, 0x00000000)

Tried a chkdsk but got the same error, even when running it on boot in console mode.

After some web trawling, found this google answer, which suggested that the problem was caused by ‘Intel Application Accelerator’ conflicting with recent service packs.

After uninstalling the ‘Intel Application Accelerator’ my chkdsk finished successfully and defrag seems to be going fine.

Thank goodness for the internet and its wealth of technical solutions!

Bye Bye EDI… Hello ThoughtWorks

Well, after almost four years at EDI (now called CargoWise edi) I am leaving. I finish in the middle of January next year. It has been an interesting time, and I have learnt a lot working with very talented people and from building the framework for a big solution suite (around 4 million lines of C# code). I’ve also had the opportunity to experience the very different joys and pitfalls of product management.

I will be starting at ThoughtWorks (of NUnit, Jim Webber and Martin Fowler fame) in the middle of February in the new year. I’m expecting that there will be a lot of new exciting stuff to learn, and a lot of variety in terms of clients and technologies. ThoughtWorks are strongly XP, do a lot of development on client sites and even have some Rails projects. The people I have met from ThoughtWorks have all been very friendly and I look forward to starting there soon 🙂

Thai Ordering and Development Mode vs Production Mode for Rails Apps

A while back, I wrote a little rails app for Thai food ordering at my work. My colleagues place orders using the system and then bring money to the nominated orderer of the week. Once all orders are in and paid for (this is also tracked in the app), the orderer rings up our favourite Thai restaurant (Laddas) and places the order.

I have the app running from fairly cheap shared hosting. At peak times during the ordering, I guess that they’d be 15 or so people simultaneously using the app. We’ve used it many times without problems. Thus, I was quite surprised and displeased (as were my colleagues), when my hosting account was suspended and we couldn’t see what had been ordered this morning. A hasty email to my hosting provider revealed that my account had been suspended due to high load and “ruby flooding”. They were kind enough to un-suspend my account and we completed the ordering process.

I remembered seeing something about production mode in ‘environment.rb‘. Some googling confirmed my hunch – in development mode, rails apps are much more resource intensive. Caching is not used, and every single file needs to be reloaded every time it is required. After changing my app to production mode, it seemed to run noticeably faster. Michael and I ran ‘top’ and it looked like each request used less CPU.

So, should you be in a similar situation, this is how to change your app to production mode on fast-cgi Apache shared hosting:

  1. Confirm that ‘database.yml‘ in your app’sconfig‘ directory has a section for production mode, and that it has up to date database connection details.
  2. Edit ‘environment.rb‘ in your app’sconfig‘ directory.
  3. Add this line:
         ENV['RAILS_ENV'] ||= 'production'
  4. Run ‘ps -u [your_user_name]’ to find if you have any ‘dispatch.fgi‘ processes running.
  5. If so, kill all of them (they’ll restart and use your new config settings).
  6. Browse to your app, it should now run faster.

Rails and the initialize() method

I spent a bit of time this weekend on a pet rails project. I came across a strange error when trying to create new records through the application. Editing was working just fine, but creating a new record just seemed to hang.

Breakpoints came to my rescue. In Ruby, they’re really handy. You can put a ‘breakpoint’ call anywhere in your code, and if you have a breakpointer process running (start this with the command ‘ruby script/breakpointer’), you jump straight into an interactive ruby console debug session when the breakpoint is hit.

Using the development log and a few breakpoints, I found the that the error was:

ArgumentError: wrong number of arguments (1 for 0)

And that it was caused by a line similar to this:

@order = order.new(params[:order])

Ie, the controller was creating a new order from the post parameters.

Then all became clear – some time earlier, I’d overridden the initialize() method in the order to default some dates. My code was similar to this:

def initializesuper()
  if (@new_record)
    self.validFrom = Date.today
    self.validTo = 1.year.from_now.to_date
  end
end

Great for creating new objects in my tests and console sessions where I always just created the object and then set properties. However, the controller was relying on passing in the post parameters in the constructor.

The solution is to accept any number of params and pass these to the base class:

def initialize(*params)super(*params)
  if (@new_record)
    self.validFrom = Date.today
    self.validTo = 1.year.from_now.to_date
  end
end

That way, the order can accept the post parameters in its constructor.

I’m very pleased to say that I can now create new records again!

Learn English using a Blog and Programming Tools!

My fiancee, Soosun, is brushing up on her English skills before going to uni next year. As part of the plan to improve her writing, she’s started a blog. Friends and family can write comments on her posts to help improve her written English.

She just wrote a nice article on making kimchi, and I posted a comment containing a copy of her article with English improvements. But how can she tell what I’ve suggested? The solution we decided to use is kdiff3, a tool I use at work for comparing and merging source code. You can download it here. If you turn word wrap on, it is great for comparing English – shows up the differences beautifully.

Ruby on Rails Hosting, Setup And Migration

I’ve been doing a little rails of late.. Here’s a summary of the stuff that I’ve learnt.

What hosting should I use in Australia for rails?

NOT JUMBA – SEE UPDATED REVIEW BELOW

I’m using jumba (http://www.jumba.com.au). Jumba is very cheap (~$30AUD/year), and they give you shell access, mysql etc. However, there was a period of several weeks when they moved me to some server without an install of rails and kept promising to install rails and never did. I finally got them to move me back to their main server which has rails installed. It was a painful process, so I’m not sure if I would recommend them. That being said, things are going OK at the moment, and I’ve got a few development apps up and running on their service.

UPDATE 29 March 2006: Jumba summarily stopped rails support without notice and was rude when I contacted them about it. I would not recommend Jumba for web hosting anything – they have frequent down time, server switches and reboots and their low price is made up for by the amount of time you waste. They used to be OK, but no longer. I’m in the market for a new host, will post on how it goes.

How to set up rails applications in your home directory (in public_html) under a UNIX/Apache/cgi/fcgi environment

  1. Upload or create your application in your home directory. Eg, ~/MyRailsApp/
  2. In your public_html directory, create a soft link to the public directory of your app. Eg,
    ln -s ~/MyRailsApp/public ~/public_html/MyRailsApp
  3. Make sure dispatch.fcgi in the ~/MyRailsApp/public directory is executable. If not, chmod it a+x.
  4. Confirm that dispatch.fcgi has a valid path to ruby on the first line. If you’ve created this project on another machine, you’ll quite possibly need to update the path. The path is often something like ‘#!/usr/local/bin/ruby’, but check what it is under your system with ‘which ruby’. Special note for InstantRails users – you’ll always need to update the path when uploading to unix hosting, as instant rails uses a windows style path with the slashes the other way around.
  5. Update your ‘database.yml‘ file (in the ‘config‘ directory of your app) with correct database names, user names and passwords.
  6. Run ‘dispatch.fcgi‘ (in the ‘public’ directory of your app). If you see an ‘Internal Server Error’ message, you know things are going OK. If you’ve got the path to ruby wrong on the first line, or some other similar problem, you’ll find out about it here, where as if you run through the web, you don’t get these sorts of problems reported in an easy to understand way.
  7. Check out your running system in the browser (eg, browse to http://myhostingcompany.com/MyRailsApp/)

Tips for trouble shooting rails errors

  1. A good place to start is by reading your logs in the ‘log’ directory of your rails app. If you’re running a development configuration, have a read of ‘development.log’.
  2. Try manually running ‘dispatch.fcgi‘ in the ‘public’ directory of your app. If you get an ‘Internal Server Error’ message printed out on the console, it’s probably working ok. Alternatives to this are reports of missing files and unable to find ruby – often these aren’t shown when browsing to your web site.


Rails problems and solutions

1. Browser and logs show: Application Error – Rails app failed to start properly

I got this after my app was moved from one unix host to another by my hosting company. I tried heaps of stuff to try and resolve this. Eventually I created a brand new dummy project on the unix host called ‘Test’ and Test worked fine from the browser. I then tried my original project again and suddenly it worked fine! It has been working fine since. I can only imagine that there was some sort of problem in temporary files or similar which got flushed. No good explanation for this currently.

2. in `start_engine’: undefined method `add_path’ for Controllers:Module (NoMethodError)

I got this one when migrating a project from rails 1.1 to a later version of rails. The solution is to force update your rails engines:

script/plugin source http://svn.rails-engines.org/plugins
script/plugin install engines –force
script/plugin install login_engine –force

3. My app works fine if there is a trailing slash on the url. Otherwise, I get a ‘Bad Request’ error page. Eg, ‘http://myhost.com/myapp/’ works, but ‘http://myhost.com/myapp’ does not work.

Add a RewriteRule to the .htaccess file in your application’s public folder:
RewriteRule ^.*myapp$ http://%{HTTP_HOST}/myapp/ [R=301,L]

My basic .htaccess rewrites are as follows:
RewriteEngine On
RewriteRule ^.*myapp$ http://%{HTTP_HOST}/myapp/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]

I tried removing the RewriteCond !-f, and my pages lost their styles. I think the condition allows the rails framework to load .css files directly without having the requests go through dispatch.fcgi.

Page 14 of 15

Powered by WordPress & Theme by Anders Norén