TriTarget.org

A blog of personal quality

Be a yardstick of quality. Some people aren't used to an environment where excellence is expected.
~ Steve Jobs

New Site; Ship-It!

This new site uses a lot of technologies behind the scenes. A side effect of this is that the build from zero to upload to web server takes a little bit of time. About 10 seconds on my Mac Pro and about 4 minutes on my Pentium Ubuntu (tablet) server.

I wanted to be able to advance the code without the need to clean/update/build/rsync all the time. Especially if I need to space out when I deploy and when I update. I really liked the idea of de-coupling the act of development and the act of deploying.

What I came up with was a deployment system that uses a chat bot (Hubot) to trigger my off site deployment scripts. This allowed me to deploy from any where, be notified when complete, choose which branch to deploy from (feature tests and easy reverts), and not tie up my laptop waiting for files to upload.


#iheartmywife

For those tracking me on twitter you probably have noticed my daily postings tagged with #iheartmywife. Well, there is a story behind these tweets.

This year on Valentine's day my wife gave me one of the most creative gifts I've ever received. She gave me a jar full of little strips of paper. Three hundred sixty five strips to be exact.

Jar-of-Love #iheartmywife (thumbnail)

Each piece of paper was a little note that offered a unique reason why she loved me. Things like: "I love learning new things about you."

After the initial goo-goo eyes and honey glow I decided something like this needed to be shared. Others needed to know that there are good things to see on the internet. Love is something much bigger then the day to day. I also wanted to tell the world that I love my wife.


Monads by Mistake

The wonders of monads are finally revealed without resorting to Category Theory or Haskell. It turns out that monads are trivially expressed in JavaScript, and are one of the key enablers of Ajax. Monads are amazing. They are simple things, almost trivially implemented, with enormous power to manage complexity. But understanding them is surprisingly difficult, and most people, once they have that ah-ha moment, seem to lose the ability to explain them to others. Douglas Crockford Monads and Gonads

Well I'm not going to try. I do, however, wish to convey my realizations about monads.

First let me just offer this piece of Underscore code:

var x = [ [1, 2], [3, 4], [null, 5], [6, false] ];
x = _.flatten(x);
x = _.compact(x);
x = _.map(x, function(y) { return y * 2; });
_.forEach(x, function(y) { console.log(y); });

Basically take the input and perform a series of computations on them with each step returning the result of the computation ready for the next. But that code looks... well... yucky. Lets try again:

var x = [ [1, 2], [3, 4], [null, 5], [6, false] ];
_.forEach(
  _.map(
    _.compact(
      _.flatten(x)
    ),
    function(y) { return y * 2; }
  ),
  function(y) { console.log(y); }
);

Holy Pyramid of Doom Batman! Lets not do that again. Thank goodness Underscore offers such better expressive syntax. Using the chain() method wraps a variable in a special Underscore object. When you call a methods on that object the return value of the method is the same wrapped object.

var x = [ [1, 2], [3, 4], [null, 5], [6, false] ];
_(x).chain()
  .flatten()
  .compact()
  .map(function(y) { return y * 2; })
  .forEach(function(y) { console.log(y); });

Much better. It's readable, concise, and guess what... That's a monad! Yes it is a way to represent data with a wrapper around that data that exposes a way to do computations on the data. This opens up the opportunity to expressively compose those computations in a human readable way. There are many other advantages as well which are out of scope for this post. Oh, and in case you hadn't made the connection, jQuery is also a monad!

My monad discovery

I came to understand monads only after I accidentally created one. I was working on a piece of browser code. A plug-in for text fields. I needed to create and modify DOM elements. I wanted to do this without jQuery, and support IE8 (don't ask). I realized that there was a lot of complexity supporting IE8 with Vanilla JS so I wanted to write a simple abstraction around it.


Virtual Tours FTW

I had the most amazing time visiting some friends in North Carolina's Blue Ridge Mountains. The area is very beautiful and I highly recommend anyone looking for a quiet and relaxing vacation to take a look at renting a cabin and seeing this area for yourself.

Here are a few pictures I took in Burnsville, NC:

  • The view from the porch with a creek running under it (thumbnail)
  • A mural of the yellow brick road from Wizard Of Oz on a brick building (thumbnail)
  • A rock sculpture in the Blue Ridge Mountains (thumbnail)
  • The same rock sculpture with a little B&W flare (thumbnail)
I also got to practise my Panoramic skills by creating my first virtual tour of a House that, in my humble opinion, is one of the most beautiful houses I've seen. (Permission granted by owners to use these on my blog).

Click on anyone of the following to start the virtual tour. If your on an iPhone or iPad then you will have to click each one manually and the quality is not as good so I recommend you view these on your desktop.

CattailBalcony (thumbnail)


3D Photography

I've been getting into some 3D projects. These are images created and rendered entirely on a computer using Blender 3D 2.68. I started this project in the intent to build objects for SecondLife. Here is my gallery of images I've made so far:

My first project was to build a Snow Globe inside Secondlife. Then I tried making my own in Blender 3D by making a stack of books, I rendered four different style each with a different level of detail. I moved on to modeling from a picture so I created an image for my work which included an internal logo / mascot. Finally I took a YouTube tutorial and created an impressive water simulation:

  • A X-Mass Snow Globe with a snowman in Secondlife (thumbnail)
  • Stack of books (thumbnail)
  • SeeClickFix Man (thumbnail)
  • Water in my glass (thumbnail)
  • SeeClickFix Man diving into water (thumbnail)


TiAppCamp 2013

Had the wonderful opportunity to attend TiAppCamp 2013 in Atlanta, GA. I had a wonderful time and learned a lot about the platform I use at work to make really cool things happen on mobile phones. While there I had time to take some interesting pictures.

The hotel I stayed at was The Hotel Indigo which is right next to The Fox Theatre. The theme was all the tickets from people who were fans of The Fox Theatre. The from lobby was quite impressive and I tried my best to capture it in this panorama:

IndigoHotel (thumbnail)

I had a little fun with some shots outside. The "Ghosts at the theatre" image was a tone mapped HDR (High Dynamic Range) Photo constructed my layering multiple shots with different exposures on top of each other:

  • Ghosts at the theatre (thumbnail)
  • The Fox Theatre (thumbnail)
  • A building view from Central Park (thumbnail)
  • The Atlanta skyline from Central Park (thumbnail)

My own template engine in Titanium

I ran into an interesting problem while trying to internationalize a Titanium application. The recommended way to do so is to use String.format to interpolate the localized string you grabbed from the L() method. Here is an example:

String.format( L("message_id", "Default %s text"), "foobar" );
// => "Default foobar text"

If I passed in a null reference the application would crash!

This was all well and good till some problems presented themselves. If I passed in a null reference the application would crash! And if I passed in a non string I would get "null" instead regardless of value. The String.format used the printf specifications which means the string had to be aware of both order and type of the values. Either translators needed to understand variable typing ("%s strings and %d numbers") or I had to convert all values to strings (String.format("%s", "" + number_value)). Out of order translations were very cryptic ("out %2$s of order %1$s strings") and the translator looses context of what they want to translate.

With all these problems I ventured on a quest to find a better alternative. And I found one. A very simple solution that you can implement today! Follow me on the journey while I recount my quest and how I found the best solution I know of.


Fun trick with underscore templates (check this out)

Doing some work in Titanium and I found some code I needed to translate and DRY up. In the process I descoved a really cool trick with Underscore's template engine.

When translating strings in Titanium you use the format:

Titanium.Local.getString("message_id", "Default text")

or L("message_id", "Default text") for short. There was an example when this format served a hindrance:

var textField1 = Ti.UI.createTextField({
  hintText: "e.g. 123 Washington Rd. (required)"
});
var textField1 = Ti.UI.createTextField({
  hintText: "e.g. example@example.com (required)"
});
var textField1 = Ti.UI.createTextField({
  hintText: "e.g. (123) 555-5555 (optional)"
});

The above asked to localize three strings that were not easily internationalize-able (e.g. ?) and all of them looked fairly close in concept. Using string interpolation would be a mess and would still require many message ids.

var textField1 = Ti.UI.createTextField({
  hintText: String.format(
    "%s %s (%s)",
    L("example_text", "e.g."),
    L("example_address", "123 Washington Rd."),
    L("required", "required")
  )
});

I'll be honest, "%s %s (%s)" looks confusing as hell.

I'm going to show you how I handled this using Underscore's template engine. I'll explain the process progressively so you can see how I ened up with the cool trick I did. And why I mentioned you should check this out.


Rolling your own event dispatcher for Titanium

I have been working on a lot of Titanium work and on the way I've learned a lot of little tricks. One of which is that you can not use Titanium objects like they were everyday JavaScript objects. Titanium uses a global event model which will leak memory if your not careful to remove your event listeners. And it will also double up on events if your not careful. Personally I like the event model but when my object goes for garbage collection I don't want to worry did I remove any left over events?.

I want to discuss my solution to this by showing a neat trick to roll your own event dispatcher that is object oriented and scoped to your own object. Oh and it is pretty simple.


Private Variables in CoffeeScript

I had a discussion concerning the lack of private variables in JavaScript objects. As it turns out you can fake this using closures and some tracking code. I'm going to illustrate this using CoffeeScript.