Monthly Archive for March, 2009

Job vs. Work

It’s amazing how my job can get in the way of me doing any useful work.

My work calendar so far for this week (blurred to protect the guilty) …

Quick web-dev environment found.

A while back, I was trying out cold fusion to see if it could become my new “quickly get a website up and running” environment.  I was pretty dissapointed with it.  The speed / power / ease tradeoffs just didn’t feel like they were in the right place.  Ever since then I’ve been using a pretty standard J2EE solution.  While I’m quite happy with how that works out, I really wish I had something faster to develop quick ideas with.

Yesterday, I spent about half the day learning / working with ruby on rails.  In that half-day I wrote a simple web application for a content editor I’ve been working on that:

  1. Allows a user to create “lessons”
  2. Allows the user to tag those lessons and search based on tags (with a nifty Ajax interface)
  3. Writes the lessons out into our version control system (with an index in a db)
  4. Allows the user to launch a Flex application (which I had already written) to actually preview or edit the lesson through a REST api

Now, if I had been working in my J2ee environment, I bet I could have written it in about the same amount of time.  BUT, with RoR I also had to

  1. Set up a development environment
  2. Learn enough ruby on rails to get this done
  3. Figure out how to actually use TextMate well

So overall, I think next time I could have written this thing in just an hour or two, which is pretty damned amazing, even for such a small application.

I’m not sure whether or not I’d go the J2EE or the RoR route if I was just starting a large complex site, but for small simple things, RoR is my choice for now on.

Oh, for books, I had grabbed the OReilly ruby book and Sitepoint’s “Simply Rails 2″.  The ruby book is great, really explains the language well.  The rails books is really just walking you through one example without a lot of “why” so I’m pretty dissapointed with it.  It wasn’t enough for me to build this simple example and I relied on google for a lot, but it was enough for me to understand what rails could do for me and to figure out what I should search for.

Update:

Spent 3 more hours with it today and added:

  1. Account creation / signup
  2. Authentication (Login / Logout)
  3. A comment system to let people comment on lessons in progress
  4. An audit log for all changes done to a lesson

RoR rocks my socks.

My recurring anti-pattern

I don’t know why, but I keep falling into a development pattern that I’ve long since decided that I don’t like.  Imagine this… you have some object.  That object has a set of properties, that might change over time.  So instead of making a bunch of variables on the object, I make an array of some property object.  Something like this…

  1. public class Attribute
  2. {
  3.   public var name:String;
  4.   public var value:Object;
  5. }
  6.  
  7. public class MyClass
  8. {
  9.   public var attributes:ArrayCollection; // Array of Attribute objects.
  10.   … some more stuff
  11. }

It’s a design flaw I made while working on TimelinerXE that I’ve come to regret due to the added complexity it adds, with the minimal benefit it gives.  It might *feel* like you’re getting a lot of future proofing.  Someday, in some future version, when we add a feature to Timeliner so the flags can have a glow-color, it’s just a new attribute in the list.  No new properties.  No new XML encoding/decoding.  It’s beautiful.  But in reality it doesn’t give you a whole lot since when new attributes are added in the future, you inevitably need to change code in several places anyways.  You still have to write the code to render the new property.  That “no new code” for xml encoding/decoding isn’t true since you now have to worry about backwards compatibility and setting a default value if none is set in your file.

But it sure adds a lot of complexity.  Instead of your view binding to a property, it has to listen for collection change events, AND bind to values within the array.  Instead of just watching for the “title” property to change, you have to be ready for:

  • A brand new attribute named title to get added.
  • That attribute to change value
  • The title attribute to be removed

And you have to be careful not to have multiple attribute objects of the same type in there.  It’s just not worth it.

Lately, I was working on a proof of concept for a content editor for a new product, and I fell into the same trap.  It worked well for the proof-of-concept, but that was only because it was a very simplistic thing.  No undo/redo, no saving, no stateful navigation.  Just a quick & dirty thing to show how something might work if we spent some development dollars on it.

I started taking that proof-of-concept to an actual working application, and ended up taking along that design.  Luckily, I decided to give Moccasin a try for a framework to build the thing in.  Mocassin doesn’t support this sort of data model, so I began hacking it in.  I spent a few frustrating hours putting it in before realizing that I was solving the wrong problem.  Instead of making the framework compatible with my screwed up data model, I should just make my data model compatible with the framework.  In all of 15 minutes I changed my model to a much simpler “normal” property based data model, and bamn.  It all works far more easily, and I’m a lot happier with it.  Going forward it’ll be a lot eaiser to finish this project.

So Joe, thanks for not having support for something like this in Mocassing, and making me think about doing it the simple, right, way.

A single command that costs $325 to run!

I just ran what might be the scariest command line I ever have… here it is:

ec2-purchase-reserved-instances-offering --offering c48ab04c-c057-457e-a4d8-a0f172f4db2d --instance-count 1

That baby reserved an Amazon EC2 instance for me for one full year at a cost of $325.  No “Are you really sure you want to pay $325?” No receipt, no “type in your credit card”. Just type that in, and BAMN $325 gone from your account and an instance-year of reserved time added. Screw up that –instance-count and type 10 instead of 1? $3250!

I ALMOST got it wrong and typed:

ec2-purchase-reserved-instances-offering --offering-id 438012d3-d93c-4fbd-a245-33b4bf0930ec --instance-count 1

That would have bought a 3-year offering!

Can YOU tell the difference? It’s in that offering ID.

To find out what offerings are available you run this command:

ec2-describe-reserved-instances-offerings

Which spits out this output, note the line in bold. That’s the one I used.

OFFERING    e5a2ff3b-f6eb-4b4e-83f8-b879d7060257    us-east-1a    c1.medium    3y     1000.0    0.06    Linux/UNIX
OFFERING    248e7b75-afbc-4724-82b2-d78353299433    us-east-1c    c1.medium    3y     1000.0    0.06    Linux/UNIX
OFFERING    60dcfab3-d5b8-4d3d-9f38-480b34d38239    us-east-1b    c1.medium    3y     1000.0    0.06    Linux/UNIX
OFFERING    c48ab04c-42bb-4e5b-8c1b-c015f9604dd5    us-east-1a    c1.medium    1y     650.0    0.06    Linux/UNIX
OFFERING    ceb6a579-b754-4a50-a53e-36efdb8eb28b    us-east-1c    c1.medium    1y     650.0    0.06    Linux/UNIX
OFFERING    3a98bf7d-b94b-412a-8de5-8c77dfcc4ffd    us-east-1b    c1.medium    1y     650.0    0.06    Linux/UNIX
OFFERING    248e7b75-ed4c-4ca7-b42b-d14ee74a3360    us-east-1c    c1.xlarge    3y     4000.0    0.24    Linux/UNIX
OFFERING    ceb6a579-1420-4728-ace3-9cb73934afcf    us-east-1a    c1.xlarge    3y     4000.0    0.24    Linux/UNIX
OFFERING    60dcfab3-97dd-421b-8f75-c126de7741ce    us-east-1b    c1.xlarge    3y     4000.0    0.24    Linux/UNIX
OFFERING    ceb6a579-f9b0-4bff-994c-c62030080d27    us-east-1c    c1.xlarge    1y     2600.0    0.24    Linux/UNIX
OFFERING    4b2293b4-cb88-480b-999d-a17683faa92f    us-east-1a    c1.xlarge    1y     2600.0    0.24    Linux/UNIX
OFFERING    60dcfab3-fa53-4d32-97cc-2fd1a0a8c0ac    us-east-1b    c1.xlarge    1y     2600.0    0.24    Linux/UNIX
OFFERING    649fd0c8-8bd3-489e-904c-4c5dfcb131ea    us-east-1c    m1.large    3y     2000.0    0.12    Linux/UNIX
OFFERING    d586503b-6876-4d40-8f94-1b2dde6b0ead    us-east-1a    m1.large    3y     2000.0    0.12    Linux/UNIX
OFFERING    248e7b75-5324-48e5-9749-fd3b4de01829    us-east-1b    m1.large    3y     2000.0    0.12    Linux/UNIX
OFFERING    248e7b75-a817-462e-996a-8ea7b4810a0e    us-east-1c    m1.large    1y     1300.0    0.12    Linux/UNIX
OFFERING    649fd0c8-4af1-4f63-bbdb-1a05951886a4    us-east-1a    m1.large    1y     1300.0    0.12    Linux/UNIX
OFFERING    c48ab04c-280c-4879-8119-63ac87002498    us-east-1b    m1.large    1y     1300.0    0.12    Linux/UNIX
OFFERING    248e7b75-0799-4a55-a0cb-f8d28eb11921    us-east-1b    m1.small    3y     500.0    0.03    Linux/UNIX
OFFERING    3a98bf7d-96c3-4d2f-a263-123fa6b46d61    us-east-1c    m1.small    3y     500.0    0.03    Linux/UNIX
OFFERING    438012d3-d93c-4fbd-a245-33b4bf0930ec    us-east-1a    m1.small    3y     500.0    0.03    Linux/UNIX
OFFERING    4b2293b4-1e6c-4eb3-ab74-4493c0e57987    us-east-1b    m1.small    1y     325.0    0.03    Linux/UNIX
OFFERING    60dcfab3-a56c-4092-8c90-3677e9da02b7    us-east-1c    m1.small    1y     325.0    0.03    Linux/UNIX
OFFERING    c48ab04c-c057-457e-a4d8-a0f172f4db2d    us-east-1a    m1.small    1y     325.0    0.03    Linux/UNIX
OFFERING    d586503b-20ad-4beb-bc88-60a1333c2b98    us-east-1a    m1.xlarge    3y     4000.0    0.24    Linux/UNIX
OFFERING    649fd0c8-4767-43a1-a530-b4a1f0c08c31    us-east-1b    m1.xlarge    3y     4000.0    0.24    Linux/UNIX
OFFERING    c48ab04c-6769-4bc1-966e-f7b0326001dd    us-east-1c    m1.xlarge    3y     4000.0    0.24    Linux/UNIX
OFFERING    c48ab04c-119e-41f1-8b0f-b83c4fc4f869    us-east-1a    m1.xlarge    1y     2600.0    0.24    Linux/UNIX
OFFERING    c48ab04c-63ab-4cd6-b8f5-978a29eb9bcc    us-east-1b    m1.xlarge    1y     2600.0    0.24    Linux/UNIX
OFFERING    e5a2ff3b-8646-4f48-912a-aaeba5823c73    us-east-1c    m1.xlarge    1y     2600.0    0.24    Linux/UNIX

This is pretty close to the worst user interface in history :)

But more importantly, what does that DO?

Well, Amazon must need some quick cash or something because they’re offering a new pricing plan for their EC2 service.  Essentially, you pay an upfront fee, and then you get a huge discount on the service for a set amount of time.

Decoding that offering-id line, it’s for 1 year (1y) to run a particular type of virtual server (m1.small) in a certain “availablility zone” (us-east-1a) for a much reduced hourly rate (0.03). This reduced rate cost me an upfront cost (325.0)

Assuming I actually run the server for the entire year it will cost me 24*365*0.03=$262.80, tack on the one time fee $325 + $262.80 and we get $587.80 for the year.

Now, if I hadn’t done this, the normal hourly rate of $0.10 applies. 24*365*0.10=$876 for a savings of $289 a year.

Since I always have at least one m1.small instance up and running, it was a no-brainer to reserve one.

So depending on how you look at this, I typed a single command and spent $325, or saved $289.

BFug meeting tonight.

There’s a BFUG meeting tonight (Tuesday, 3/10) at 7:00 in Newton MA for anyone interested.  Joe Berkovitz will be talking about Noteflight and moccasin, I’m looking forward to it.  I’m hoping I can use Moccasin in an upcoming project here to create an authoring environment eductional step by step explanations of math problems.

Flex modules not rebuilding correctly

We have a class that we use all over our application, including within about 30 modules. I intentionally changed that class in a way that was likely to cause many compile time problems.  I figured I’d let them error out and use that to find them.

I did a clean-build.  No errors.  WTF.

I went in and manually deleted the module .swf files.  Clean build.  Build-All.  Compile time errors, yay.

I fixed them all.

Re-cleaned, re-built, no more errors.  Yay

Submitted my changes to source control.

Continuous integration server tries to build (ant + build script + flex SDK), errors up the wazooo.

I look, sure enough, they’re real errors.  Flex builder isn’t complaining.  I edit the file the error is in, don’t fix the error, save, and suddenly flex builder sees the problem.

I have no idea why this would happen, very annoying.  If I do a clean build, I actually want to build everything from scratch.  I have no idea why some modules are getting an outdated version of a class that has long since been changed.

Safari 4

I grabbed Safari 4 over the weekend. I had read about a bunch of the new features, but the one thing I didn’t get from those reviews was just how fast and responsive it feels. This morning I launched Firefox by habit, remembered I had the new Safari so I launched that as well. Safari was open several seconds before FF, even though it was launched several seconds later. Also, GMail feels faster, from clicking a link to having something happen, it’s definitely better. I’ll have to look for some benchmarks to confirm my hunch.

Update:

I’m having GMail problems.  That’s going to prevent me from continuing to use Safar 4 for a while.  I’ll be trying to send an email and only getting server errors, or it sits there and doesn’t do anything at all.  Oh well, was fun while it lasted.  Can’t wait to try a later build.

AgileAgenda Basecamp Edition (Basecamp + Actionscript)

Over the past few weeks I’ve been working on a version of AgileAgenda (project scheduling app) that tightly works with Basecamp. Previously, we had a fairly poor synchronization between the two. But now AgileAgenda directly reads and writes to your Basecamp project, so it’s a lot cleaner to use. So if you’ve ever wanted Gantt Charts in Basecamp, you might want to take a look.

It’s still a work in progress, but if you’d like to take a look, I’d really appreciate any feedback:
http://agileagenda.com/basecamp/

If you want to just see a glimpse of it, there’s a quick video:
http://agileagenda.com/basecamp/video.html

One neat thing I’m doing that other Basecamp integrated apps might benefit from; I need to store quite a bit of information that Basecamp doesn’t handle natively. Things like associating a duration to a todo item or an estimated start/end date. To do that I’m storing it to an XML snippet, base 64 encoding it, and putting it into a private message within an invisible span tag. In the message I throw in some status info and attach a document, so the message is valuable to more than just the app.
Screenshot of that:

Again, I would appreciate any feedback, trying to make something within a bubble of how I use it can be tough.

Also, as part of this, I’ve been working up a pretty comprehensive AS3 library to deal with the Basecamp API. I’m not sure what I want to do with that yet. Perhaps an open source thing, maybe a for-pay license (maybe even dual-license). Would anyone be interested in something like that?