The Voice Behind the Code

I recently listened to The Changelog episode about a static site generator called Middleman (as an aside – The Changelog is an amazing podcast about all kinds of open source software – kudos to Adam Stacoviak). Now I’m not a user of Ruby (haven’t had time to play with Ruby nor Rails) but after listening to this episode I really want to try out Middleman and in fact I put it on my list of projects to play with when I have time.

Why? Because I liked how Thomas Reynold presented himself on The Changelog, I like his philosophy in developing and managing Middleman. It’s a side project that he’s been maintaining for a long time and he’s committed to maintaing it for a long time still. Furthermore, his technical decisions and evolution of Middleman shows me that he’s someone who’s willing to evolve his software rather than let it fade away in a morass of old crufty code.

My immediate reaction of putting Middleman on my project playlist made me consider my own approach for selecting software. I used to look at software based on popularity as measured by techie blogs and the latest fad. Somewhere along the line I changed my approach and how I purchase software. Somewhere along the line, I started paying attention to the the voice behind the code.

These days – when I come across an interesting product – I start reading the blog of the developer (or company), and then I move onto any podcasts that the developer has participated in. It’s an oddly personal path to a product. I suppose that marketeers will call it ‘personalization’ or some such thing.

When did this start for me? When did I change from a blind purchaser of software to a more reflective one? (I think this is more applicable to Mac software purchases than iOS products where I’ve bought lots of crap before stopping my purchases for the most part)

I think it started with the Build and Analyze (B&A) podcast where I heard Marco Arment talk about software development. I found out about B&A from a Merlin Mann podcast called Back to Work.

I bought Marco’s Instapaper app because of B&A. Here was an opinionated developer that wasn’t afraid to tell why he did or didn’t do certain things when it came to Instapaper. I liked the guy’s honesty, hard headedness and general East Coast demeanor. Marco sold Instapaper in 2013 and I thought that Instapaper was doomed to take a long slow nosedive into oblivion. But I was wrong because Marco entrusted his software baby to a great steward for his product.

He moved on from B&A to the Accidental Tech Podcast. He also created The Magazine but I didn’t buy it because it was not my cup-of-tea as a product (Apple’s Newstand never seemed right to me so I never bought anything in it).

He recently created a fantastic podcast client which I’ve been enjoying since day one of its launch. Overcast embodies Marco’s sensibilities and his choices fit the checkboxes that I have for a podcast client.

It’s funny how all of this started because of a podcast and listening to some anonymous guy passionately talk about his software and why he made certain choices when designing that software.

I have yet to be disappointed by a product purchase that is based on the voice behind the code. I’m not sure if this is a great approach to purchasing software but it works for me.

Voices that I’ve liked:

Advertisements

Book Review: “Childhood’s End” by Arthur C. Clarke

Warning: Spoiler Alert: If you intend to read the book, please do not read this review.

Rating:

  • Harlequin level: n/a
  • Plot/action/story: 5
  • Solid conclusion: 5
  • SciFi thrill: 5
  • Fantasy thrill: 5
  • Part of a series but doesn’t skimp: n/a

Overall thoughts about the book

While I’ll do my best to describe my impression of “Childhood’s End”, I have to admit that words fail me. It is a stunning novel beyond description. I read it on my Kindle and immediately ordered a 1953 hardcover version the moment that I finished it. I rarely do that…actually, I never do that.

While I understand that scifi purists might scoff at Clarke’s combination of scifi and the paranormal, I don’t think anyone can deny his storytelling mastery when it comes to both.

Clarke divides the book into 3 parts:

  1. Earth and the Overlords
  2. The Golden Age
  3. The Last Generation

In Earth and the Overlords we are introduced to the mysterious Overlords that show up just as man is about to take off to the stars. This theme of man being prevented from reaching the stars is repeated over and over again and the last part of the book resolves this fundamental issue. Mankind does not ever take off but man’s children leave on a completely different route into the universe.

Getting back to this first part, Clarke plays with and refuses to answer whether the Overlords are ‘good’ or ‘evil’. Are they really here to help mankind or do they have a different agenda? He also taunts the reader with the most basic of questions – what do the Overlords look like and why do they refuse to show themselves?

He constantly hints at a hidden agenda and he uses the relationship of overlord Karellen with the human Stormgren to both clarify and obscure the Overlord/mankind relationship. This part of the book is best summed up by the last paragraph of part one:

And Stormgren hoped that when Karellen was free to walk once more on Earth, he would one day come to these northern forests, and stand beside the grave of the first man ever to be his friend.

There’s this bittersweet tone that the above paragraph sets for the next section of the book – The Golden Age.

In The Golden Age we are immediately shown what the Overlords look like. Sure it’s 50 years later and the Overlords have had time to affect man in a way that brings utopia to all mankind. But it’s still shocking to find that the Karellen (and therefore all Overlords) looks like Satan.

At this point I was sure that the Overlords’s agenda was ‘evil’ and of course I was wrong once again. Clarke is like an amazingly strategic volleyball player that sets up a fake spike and has one of his compatriots slam the ball on his confused opponents.

Mankind’s utopia is in full swing when we’re introduced to Rupert Boyce. Through Rupert we meet George Greggson and his future wife – Jean. And through Rupert’s séance party Clarke shows us some slight hints to the Overlord’s actual agenda. It has to do with Jean revealing the exact location of the Overlord’s homeworld (actually the location of their sun). In the process of showing us this we are also introduced to Jan Rodricks, who in the last section of the book, turns out to be the last man on earth.

Jan figures out a brilliant way to be a stowaway on an Overlord ship reaching for the stars and visiting their world. This daring move in conjunction with time dilation assures his place as the last man on earth.

The Golden Age closes with a one-two punch. The first punch is Karellen’s clear dictate that mankind would never reach the stars:

“It is a bitter thought, but you must face it. The planets you may one day possess. But the stars are not for man.” “The stars are not for man.” Yes, it would annoy them to have the celestial portals slammed in their faces.

The second punch is the bittersweet passage that continues the build up of the ending in this constant circular drumbeat sort of way. As I mentioned before – words fail me.

It had been the Golden Age. But gold was also the color of sunset, of autumn: and only Karellen’s ears could catch the first wailings of the winter storms. And only Karellen knew with what inexorable swiftness the Golden Age was rushing to its close.

The Last Generation begins with the pettiness of George Greggson and the eventual move of both him and his family to New Athens – a sort of modern day commune. Here in New Athens Clarke builds up and hammers through the transformation of the Greggson’s children and the eventual transformation of all of the children of the world.

As a parent, some passages are utterly terrifying:

“I’ve only one more question,” he said. “What shall we do about our children?” “Enjoy them while you may,” answered Rashaverak gently. “They will not be yours for long.” It was advice that might have been given to any parent in any age: but now it contained a threat and a terror it had never held before.

and

It was the end of civilization, the end of all that men had striven for since the beginning of time. In the space of a few days, humanity had lost its future, for the heart of any race is destroyed, and its will to survive is utterly broken, when its children are taken from it.

Here Clarke reveals the full plan of the Overlords and the upcoming extinction of mankind. He also intersperses Jan’s journey to the Overlord home-world. It is a sort of high-tech rendition of biblical hell with less drama and lots of tech. Through Jan we get to see that the Overlords are really in their own sort of purgatory.

Jan is truly the last man on earth and through him we see the ascendence of man in the form of the children’s merger with the Overmind. Yet this merger is strange and inexplicable. We don’t know what really becomes of the children, we just know that they are no longer an obvious remnant of mankind.

They were emptier than the faces of the dead, for even a corpse has some record carved by time’s chisel upon its features, to speak when the lips themselves are dumb.

The Overlords are stuck in their own hell. They are servants to a master that they cannot understand. They are at an evolutionary dead-end and the only thing that they can do besides serving the Overmind is to do their best to understand that which they cannot understand. And yet Karellen assures us that they will not bow their heads without a fight.

Yet, Karellen knew, they would hold fast until the end: they would await without despair whatever destiny was theirs. They would serve the Overmind because they had no choice, but even in that service they would not lose their souls.

The above passage reminds me of Invictus and the way Clarke applies it applies to the Overlords – man’s version of Satan is quite astounding.


>Invictus by William Ernest Henley

Out of the night that covers me,
Black as the pit from pole to pole,
I thank whatever gods may be
For my unconquerable soul.

In the fell clutch of circumstance
I have not winced nor cried aloud.
Under the bludgeonings of chance
My head is bloody, but unbowed.

Beyond this place of wrath and tears
Looms but the Horror of the shade,
And yet the menace of the years
Finds, and shall find me, unafraid.

It matters not how strait the gate,
How charged with punishments the scroll,
I am the master of my fate:
I am the captain of my soul.


Man’s children have ascended and become something else (we don’t know if they’re in ‘heaven’, we just know they’re in ‘something else’). But the Overlords…they’re still fighting to be the captains of their soul.

Amazon Web Services Lesson – S3 Bucket Names are Universal so get your domain named S3 bucket before someone else does

I recently subscribed to Nicholas Zakas’s excellent http://www.nczonline.net newsletter and came across a shocking realization about Amazon’s S3 service: all S3 bucket names are universal. Let me explain what this means.

It all started with wanting a static image server for my blog

A few weeks ago I wanted to host all images for this site on images.eli4d.com. Why? Well I wanted to be able to easily move my blog without worrying about static assets. I also wanted to explore an AWS service such as S3.

I finally got it to work after beating my head against some security policy issues (this had more to do with me than Amazon but this is for another post). One of the key points that I learned when doing this is that the simplest approach to create an S3 based static site requires naming the S3 bucket with the name of the domain.

But then I read the following from Nicolas Zakas’s newsletter

From http://www.nczonline.net/blog/2015/08/wordpress-jekyll-my-new-blog-setup/

But then I read the following from Nicolas Zakas's newsletter

OMG – what?

image attribution: https://flic.kr/p/8Y1Mp9

OMG - what?

So what does this mean?

It means that if you have any intention of ever having a static S3 based website, then you should create the S3 buckets with the various permutation of your domain’s names before someone else does (so domain.com, www.domain.com, blog.domain.com, etc…). This is worth doing even if you don’t use those S3 buckets.

Keep in mind that you’re not locked out of using any other S3 buckets for your domains. But you have to deal with some unnecessary hoops.

So what does this mean?

Thanks!

Many thanks to Nicolas Zakas for documenting his experience with S3.

How to use Google Forms to track anything


Ever had a need to track something? Ever had to ask you spouse to help you track something? Google Forms can be very helpful.

Summary

In this post I go over some quick steps to create a google form to track cat vomit (yes – I’m serious). I discuss the steps of form creation, and how to easily access this form from your smart phone (I use the iPhone as the example) so that both you and your spouse can track a common issue or thing.

Detail

I know…you’re thinking ‘cat vomit – couldn’t you pick something better?’ My answer is that I try to pick real life examples, and this is as realistic as it is going to get. My cat, Max, has started vomiting recently…at least I think it was recent. I can’t tell if it’s a pattern or if it’s been happening for a long time and I’m over-worrying about him. I don’t quite know the line of cat weirdness and health problem…so it’s time to get some data.

Putting my engineering hat on – I know that the first thing I need to do in characterizing any system is to collect data. Lots and lots of data. Granted I wont have a Hadoop cluster crunching this data, but I at least want a spreadsheet that I can show to my vet. It’s better than going in with the “I don’t know” response to everything that s/he will ask (like ‘when did it start’, ‘how long’, how often’, etc…).

Challenges:

  • Speed of entry: I need to enter this data quickly. The quicker, the better.
  • Ease of entry: While I can deal with most user interfaces, my wife is not so forgiving. She’s a pragmmatic ‘show me how to bring up the app/form and get out of my way’. She also doesn’t tolerate lots of extraneous UI crap because she has better things to do (and she really does have better things to do).

In considering my budget (i.e. $0) and the problem at hand, I chose to use Google Forms to enter Max’s data.

A word and warning about Google Forms

I have used Google’s services for years. I’m sure that they have a large data dossier about me due to my Gmail and Google docs usage (which includes forms). Putting aside the question of whether Google is evil, the key fact is that Google is a business and all of us users who use its ‘free’ services are its product. So if your data is sensitive, then you should NOT use Google Forms. Just think of yourself as a contestant in the TV show Big Brother, and Google is monitoring everything from the moment you use sites that utilize Google ads or enter their properties (Gmail, docs, Google search, etc…). If you’re in any way uncomfortable with this, then you should find a different way of recording your data.

In this case, I’ve made the soul-searching decision that Max is ok with being tracked. Granted, Google might attempt to monetize on his vomiting when he surfs the web. But it’s a compromise that I’m willing to make, and he’s fine with it though he negotiated some additional treats for this concession.

Lets go to the Google Form site

OMG – a picture of smores! Google Forms are like smores? Maybe the graham crackers are the forms and the marshmallow is the data. So in this case the chewy center is vomit related data…fantastic.

Click the “Go to Google Forms”.

Lets go to the Google Form site

Now you’re in a blank form

Most of the entry form is self explanatory. The key tools to use are:

  • Question editing tools (1)
  • Choosing the question type (2)
  • Add an additional question to your form (3)

Now you're in a blank form

Renaming my form

Renaming my form

Creating a question with a date/time

I put this as the first question because the date/time when I (or my wife) remember something about Max’s behavior may be different than the current time/date of this data’s entry. Notice that I made this an optional question (as most are on this form) because I don’t want my wife to not to use the form.

Creating a question with a date/time

Creating a question about the event

This is a dropdown for the type of event that happened. This ends up being somewhat of an extraneous question (see further down this article in the ‘fine tuning’ section).

Creating a question about the event

The meat of the form

This is the fundamental and most important question of the form. There should be at least one required question. In this case, the event detail should be the only required question. I didn’t check the ‘Required question’ box here but I will later (see ‘Fine Tuning’ section).

The meat of the form

My catchall question

I obviously wont remember all the possible Max issues and behaviors, so I have a catchall (the is the ‘else’ part of my if-elseif structure for my dev friends).

My catchall question

Now it’s time to view the life form

Steel yourself – this will be an exciting form.

Now it's time to view the life form

The form is beautiful

This is the screenshot from a browser. However, the mobile version should be pretty usable since there are few fields. So it should be ok in terms of my ‘speed of entry’ and ‘easy of use’ criteria.

The form is beautiful

Track Max the Cat – Google Forms

Track Max the Cat - Google Forms

The Google Form response spreadsheet

Google automatically creates a Google Sheet (i.e. spreadsheet) for the data that gets entered into the form. This is one of the key benefits. I can also print it and download it as an Excel file (so I can email it to my vet…s/he LOVES email attachments >:-) ).

The Google Form response spreadsheet

Time to test my form

I want to test my form as a non-logged in user. In this case, I use Chrome’s incognito mode. In this way I’m guaranteed to view the form as a non-logged-in user. If I wanted more privacy, I would use Firefox rather than Chrome since it guards privacy better, but since I’m using Google’s services – it doesn’t really matter since my data kimono is already open.

Time to test my form

I test my form and get this as the result

I test my form and get this as the result

I re-check the form response Google Sheet

Notice that the form response Google Sheet will always have a Timestamp column (the first one), which is why additional date/time is optional and only useful if the actual event’s time/date is significantly different from the time/date when the form is used.

I re-check the form response Google Sheet

Using the time/date question

I have some retroactive vomit events that happened and I enter them

Using the time/date question

The update to response form

The update to response form

Now it’s time to put this form on my iPhone (and my wife’s iPhone)

For this form to really be used by me and my wife, I need to place it on our iPhones. What I’m actually going to do is I’m going to place it as a link via the “Add to Home Screen” feature of the iPhone. This features allows you to create a an icon on the iPhone and when you tap it – your iPhone’s browser will go straight to the specified link. In our case, I want to go straight to the form.

Now the form that I just created is a huge long url. To save it on the phone I can do 2 things:

  • Email it to myself and my wife.
  • Use a URL shortner (such as bit.ly) to create a memorable link so I can easily put it in the phone. I’m a big fan of http://bit.ly and the company behind it.

In this article, I chose to go with the second option. This way I can add it to as many devices as I want to.

So – the first thing to do is to go to bit.ly and log-in. By-the-way – remember the warning that I gave about Google Forms at the top of this article? It applies to bit.ly too (heck – it applies to any web service that you use).

Now it's time to put this form on my iPhone (and my wife's iPhone)

Paste in your form’s URL

I paste in my form’s url here. What’s that? Why am I not showing my form’s url? Because Max wants privacy when it comes to his vomity activities…sheesh.

Paste in your form's URL

Bit.ly creates a link for me

Initially, bit.ly creates an ugly link that I would never remember. So I use the ‘customize’ field to put in something memorable (like ‘superkittyvomit’).

Bit.ly creates a link for me

iPhone – place your newly created bit.ly link in the address bar

I put the memorable bit.ly link that I just created in the the iPhone’s browser (i.e. Mobile Safari).

iPhone - place your newly created bit.ly link in the address bar

iPhone – browser loads my form

Now the iPhone’s browser (i.e. Mobile Safari) loads my form. It’s time to sit back and soak in the form’s beauty 🙂 . I scroll around to make sure it works as expected.

iPhone - browser loads my form

iPhone – more testing of Google Form

iPhone - more testing of Google Form

iPhone – more testing of Google Form

iPhone - more testing of Google Form

iPhone – time to make it easy to access the form

Pressing the small upwards arrow on the bottom of the iPhone’s browser brings up a bunch of options. I choose “Add to Home Screen”. This will save a link to my form as an icon.

iPhone - time to make it easy to access the form

iPhone – Changing the icon’s name

I can change the iocn name but I leave it alone since it makes sense to me.

iPhone - Changing the icon's name

iPhone – Icon is now accessible as another ‘app’

While it isn’t an app, it is easily accessible as one. When I touch the ‘Track Max…’, the iPhone’s browser will open and go straight to my form.

iPhone - Icon is now accessible as another 'app'

iPhone – rinse and repeat with your spouse’s device

I perform the same iPhone steps on my wife’s iPhone. Because of that bit.ly link – I can do this really fast and get back to watching Marvel’s Agents of S.H.I.E.L.D.

Fine Tuning

After creating the form – I re-looked at it and realized that I wasn’t capturing the most important question (i.e. ‘Event Detail’). So I went back and cleaned up the form and placed the most critical question at the top. I also placed the optional date/time question at the bottom. This irks me a bit because I feel like it must be at the top. However, in considering my wife’s usage, I realized that the pragmatic choice is to put the date/time question at the bottom. I rather that the most important question be at the top and everything else come afterwards.

Note that I did not delete any columns (i.e. like the ‘Event’ column) in my Google Sheet. My reasoning is that I can always delete that column in Google Sheets or Excel and I rather make sure that the Google Form operates properly (besides the fact I have very little time to further mess with this thing).

Tada – the final form in all its glory

Well…the final form at this point in time. You may bask in its glory and enjoy.

What’s that? Why am I repeating myself with ‘skip this question’? Well – previous forms/experiences have shown me that my user (i.e. wife) tends to hesitate on whether to answer that question or not. In other words, she’s not sure if she really needs to answer this question (remember – she has better things to do). It creates a sort of cognitive dissonance which may not be worth it. Frankly, I’m tempted to remove this question all together and let my user put the date/time in the ‘Additional Information’ question if need be.

Tada - the final form in all its glory

Conclusion

I can now track my kitty’s behaviors. My wife will hopefully use my fantastic Google Form to help with this data collection. So that’s it – Google Forms at its best (or worst depending on your point of view). You can track anything – pets, kids, car problems, co-workers, etc… . Go forth and Google Form away.

If you like these instructions – put a comment on this article or let me know via twitter.


Updates to this post

  • 2015-09-01: I’ve changed the title and the URL link from “Cat Vomit and how to use Google Forms” to “How to use Google Forms to track anything”. The title just felt wrong and it’s bugged me over the past week. I’ve also modified the summary section to complement the title.