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) …
Comments and thoughts on technology from Marc Hughes
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) …
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:
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
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:
- Account creation / signup
- Authentication (Login / Logout)
- A comment system to let people comment on lessons in progress
- An audit log for all changes done to a lesson
RoR rocks my socks.
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…
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:
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.
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.
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.
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.
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.
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?