Values, or quirks, of John Duff

Values

A few months ago I was introduced to this blog post by Luc Levesque titled How to help new employees be rockstars, a new approach. In this post Luc talks about his “Blueprint to Luc and his Quirks” which outlines the things that are important to him and some of his particular quirks. Luc then gives this to his new employees and goes over it with them when they start so that they understand a bit more about him and how he works. The idea is that if there are no surprises, all the expectations and potential quirks are put out there straight away, then there will be less questions about how someone new should react or how Luc will react to particular actions.

I thought this was a great idea and a tool that I could make use of for myself at Shopify. This should be considered a constant work in progress, I am constantly changing the way I work and what I take on, so it only makes sense that some of my values and quirks will change along with that.

The Values, or quirks, of John Duff

Caring
I care about Shopify and what we are doing. I jump on things that need to be done, dig into problems and make Shopify better. I’m around when issues come up. I fight for code quality and correct solutions.

Responsiveness
Being responsive allows us to move at incredible speed. I might not get back to your email or question a minute later (often I will), but you will hear something within the day. Making sure people have the information they need is super important to me. I use my phone for email, code review and everything in between so that I can always respond.

Ownership
When I tackle a problem I try to understand every aspect of it. I think about the solution and what it will mean in the long term. There are endless interesting things to do at Shopify, but completing one of them is worth more than starting ten. Have the determination to see things that matter through to completion.

Growth
I am always trying to improve and am constantly pushing myself. I take on as much as I can handle, then I ask for a bit more. By pushing myself and what I am capable of, I am learning and growing – and so is Shopify.

Passion and Drive
I love what I do. Shopify is my startup, it is as important to me as anything I would start on my own. I am invested in our success and the success of everyone on the team.

Doing it
If I see something broken, I fix it. If someone needs help, I help them. I don’t complain, I get in and do something about it. I do what I think is right first and ask for permission later.

Insatiable Curiosity
I ask questions about what I am doing if I’m not sure. I am always open to new ideas or solutions. I like to back things up with data or alternatives and question the necessity of features and changes. Every decision is mutable.

I found it a great exercise to even just come up with these values, let alone share them with everyone. Big thanks to Luc for providing the inspiration for this and Cam Gregg for suggesting I give this a shot.

October 06, 2013 | View Comments

Riding the Monorail

Monorail

A few months ago I had the amazing opportunity to speak at BigRubyConf. This is a new ruby conference all about people doing big things with ruby and it was amazing. It was great to get together and talk to people who are dealing with the same or similar problems that we do at Shopify with running large Rails applications.

One interesting thing I started to notice when talking to all these developers with applications at a similar scale to Shopify (code and/or traffic wise) is they often referred to it as their ‘monorail’. This came up again a couple of times when I was at RailsConf as well. This was a new thing to me and as I talked to more people the meaning of this term became clearer and clearer.

When people used the term ‘monorail’ they were referring to their single, core rails application. This is usually the application that the company started with. This is also the application that they are often chipping away at to turn into services. This is all well and good, the interesting part to me was that almost everyone who referred to their ‘monorail’ did so in a negative way. This was the application that was really hard to deal with, or that they were breaking apart into services or the code was really complicated and scary.

So, back up a bit, I said we have a similar sized application at Shopify but we don’t refer to it as our ‘monorail’. We have a few services around it, supplementary apps etc, but still we don’t call the largest of them a ‘monorail’. What do we call it? It is ‘Shopify Core’. Another interesting point is we don’t refer to ‘Shopify Core’ in a negative way, I am extremely proud of this application and the code that it holds. I tell all developers, even non developers, that this holds the answers to all the questions you may have about Shopify or how to do just about anything in Ruby or Rails. “Chances are the problem you are trying to solve has been solved in Shopify Core”. Since Shopify has been in development for almost a decade, started even before version 1.0 of Rails, then it is likely the git history holds the solution to most Ruby / Rails problems in ANY version of Rails. I find this incredible.

I guess the big question to ask is why do we look at Shopify Core so differently? I would imagine the applications have a similar amount of code and complexity, what makes us different? I think a big part of this is the fact that Shopify has been built and is still being driven by a team that holds a lot of value in writing quality code. We even recently started a rotating team of developers where when you are on that team your mandate is to reduce technical debt and improve the quality of the code base. This is time when we don’t work on features and make the code base better. Awesome.

Now, we’re not all magical developers that write perfect code. Far from it. I think the difference is that we are able to and encouraged to go back and improve things. I’ve heard Tobi talk often enough about how while he was learning to program his mentor would often rip apart his code and ask him to throw it away and write it again. This leads you to not being tied to the code you write; it’s just a tool to get a task done. This is a concept that Tobi and the rest of the team tries to ingrain in developers. Once you get this it is much easier to throw away a piece of code and rewrite it. It also helps that the core development team that wrote most of the code that Shopify launched with is still at the company.

Do I have a good answer for why we look at Shopify Core differently? Not really. I have no concrete reason for why look at our core code base so differently than other companies. It might have to do with the focus on quality, or maybe not being tied to the code you write. It might be the type of people we hire, or the culture of the company itself, I really don’t know. To be honest it doesn’t matter to me that much; I’m happy that I work on a code base that I can be proud of and that I enjoy working with everyday, that’s all that really matter to me.

June 05, 2013 | View Comments

One Month in At Shopify!

Like the headline says, I’m a month into my new job at Shopify and it’s going great! I thought people might be interested in hearing what it’s like getting started there.

What is Shopify?

You haven’t heard of Shopify? Where have you been?? Just kidding, it’s okay if you haven’t heard of them before :). Shopify is a web application that lets you set up an online store to sell your goods. It integrates with a tone of services for acceptings payments, shipping and anything else you might need to run an online store. This is all done using amazing technologies like Ruby on Rails, jQuery, Redis, AWS and much more. Did I mention we’re location in the ByWard Market in downtown Ottawa? Yes, it is awesome.

The First Day

So, my first day. The hours are pretty loose, people come in anywhere between 8 and 10am, I like to come in around 9 am myself. So I come in and I’m met by Brittany in HR and we start out with a bit of paperwork, then the fun begins. It starts out with getting a big gift bag with my ‘welcome package’ and what a welcome it is. Gift cards, some chocolate, a notebook and some Shopify schwage. Then we walk over to the one free desk in the main dev area, or ‘The Pit’, where I will be sitting. A nice big Cinema Display is already sitting there, but no laptop, we had to go over to the Apple Store and get a new one of those.

Once I’m all set with a desk and computer I spent a little time getting things installed, my dotfiles setup and Shopify checked out running. Next up I spent some time with Dennis Theisen who points me to a couple of bugs in the Partners Area of Shopify. I spent the rest of the day fixing the bugs Dennis assigned me and a few more things that I found along the way. I got to put some bug fixes into code review and the code went into the master branch that day and in production the next. I’ve got to say that is pretty satisfying; first day in and already committing code.

Day Two

For my second day I spent the morning pair programming with Jesse Storimer, continuing on the invoicing refactoring that I was helping him with during my interview pairing. It’s always fun working with Jesse, I always learn something new and on top of that he’s a VIM guy as well :). After the pairing I spent some time fixing up some of the other bugs I found in the Partners Area the day before. I’m probably skipping over all the fun stuff like going out to lunch in the ByWard Market, talking with some of my awesome new coworkers and all that stuff, but be sure lots of fun stuff is happening everyday.

The rest of the Month

The rest of the month has went by crazy fast and I’ve already gotten a chance to work on a lot of different things. I’ve done a little bit of work on ActiveMerchant, added SSL to the Partners Area, fixed a few IE and other bugs, some work with invoicing, Google Base and a little bit of work for the contest we just launched. A pretty busy month, but that’s the way I like it. Oh ya, I’m also working on a Shopify App in my Friday afternoon time. It has been great so far and I’m looking forward to every new day of it.

If any of this sounds pretty cool to you we are hiring for a number of different positions. If you want to know more just give me a shout or send in your resume.

April 29, 2011 | View Comments

tmdb_party 0.9.0 Released

Over the weekend I spent a little bit of time cleaning up some of the code and adding a few new features to my gem gem for talking to themoviedb.org, tmdb_party. If you’ve never heard of themoviedb.org you should really check it out. It’s a lot like IMDB but it is completely user generated and has an open api that anyone can use.

So, what’s new in 0.9.0? Well, under the covers I did a bunch of house cleaning, moved some files around and removed some useless extensions to core classes that were used internally and just cluttering up your classes. Nothing too special there, but should make the code a lot easier to understand and maintain.

I also managed to implement two new features that I’m pretty happy about. The first one is based on some work I noticed in forks by willchang and razielgn. They had both implemented the Movie.browse method from the api, but because of my recent changes I couldn’t pull either of them very cleanly. Since it was a pretty straightforward change I just added it myself, but kudos to those guys for making me realize it was missing. Here’s a little example of what you can do with this new method:

tmdb = TMDBParty::Base.new('key')
tmdb.browse({:query=>'Transformers', :rating_min=>3, :min_votes=>3})

There’s a number of different options, all of which can be found in the api docs.

The other feature I added is something I find really cool. This comes from talking to John Tajima who told me about this cool idea of being able to generate a unique hash from a video file which you can use to identify the video. It turns out that themoviedb.org api already supports searching based on the file hashes when using the Media.getInfo method. So I went ahead and grabbed the hashing algorithm, made a few changes and here we are. Here’s how we use it:

tmdb = TMDBParty::Base.new('key')
File.open('transformers.avi') do |file|
  info = tmdb.get_file_info(file)
end

This will generate the hash for the given file and use that in the query to Media.getInfo returning all the information for whatever movie that might be. Now you can easily figure out what all those randomly named files on your disk really are.

The last thing I wanted to point out was some work that Mange did awhile back adding support for retrieving results in different languages, lots more tests, person search and whole bunch more. Almost all of the methods take an optional final parameter for the language you want your results in:

tmdb = TMDBParty::Base.new('key')
tmdb.search('transformers', 'fr')

So that’s all there is for now, thanks again to everyone who has contributed to this project with code, ideas, comments and everything else. If you need help getting started check out the readme or give me a shout and I’ll gladly help you out.

March 14, 2011 | View Comments

Learnings Jan 27 2011

Wow, it’s been a long time since I’ve posted some learnings. Or anything for that matter. Well, I’ve been saving them up so here’s a few from a little while back. Hopefully I’ll be getting back into the swing of things and start writing some real posts. For now, this is it.

  • When doing a screen recoding with Quicktime in Snow Leopard before starting the recording there’s a little drop down to the right that can be used to select which microphone to use. A nice walkthrough can be found here.
  • with jQuery.extend the first hash is modified, the result is also returned:
    jQuery.extend({"one":"one", "two":"two"}, {"two":"three"}...) => {"one":"one", "two":"three"}
    
  • -k option to IExplorer will start it in full screen kiosk mode
  • ActionController::Base.helpers gives you access to the Rails html helpers (div_for, content_tag, etc)
  • link_to “something”, :controller=>:something, :action=>"…" will map to :controller=>"devise/something" if called when rendering a devise view. Use dynamic helper methods (ex. something_path) to get around this issue.
January 27, 2011 | View Comments

Learnings for Week 39 2010

  • If you need to access Git on a remote machine and can’t add an ssh key from that machine to the server adding a few options to the .ssh/config should do the trick:
    User jduff
    Host git.server.com
    
    If you then ssh to the machine passing the -A option (to forward the agent) git should work perfectly.
  • In windows Run => \\tsclient (Terminal Server Client) will list network drives
  • With Rails 3 unobtrusive Javascript (using jquery-ujs) adding ‘data-remote=true’ and ‘action=URL’ attributes any input element can be made to do an ajax request without any extra work.
November 24, 2010 | View Comments

Learnings for Week 38 2010

Not much for learnings for a couple weeks so skipping a few.

  • Rails error messages can be cleaned up so that the user isn’t overloaded by adding the simple helper described here
  • Setting up an app to authenticate with Facebook using Devise is really straight forward. We have a sample Rails 3 app right here that you can check out.
November 06, 2010 | View Comments

Learnings for Week 36 2010

  • Google provides some modern webfonts that anyone can use through their font api.
  • SQL Authentication can be turned on for SQL Server through the Management Console under the Server Properties. More details can be found here.
  • Using the Facebooker2 gem you must call ‘fetch’ on the Facebook user to get their user details.
    current_facebook_user.fetch
    
  • Posting to a users feed is really easy with Facebooker2
    current_facebook_user.feed_create(Mogli::Post.new(:message=>message))
    
  • You can prevent Parallels from automatically switching to Coherence mode by changing the Startup View in Startup and Shutdown options for the VM. More details here.
  • Came across an article with 15 CSS Tips and Tricks that a had a few interesting points (IE6 PNG with filters) that I hadn’t known about.
  • Rails 3 respond_with calls as_json on objects when returning a json response instead of to_json
  • Rails 3 respond_with returns " " on successful update or delete calls. jQuery has trouble parsing this as json so always fails. On the jQuery side this can be fixed by adding this line (I came up with this based some of the suggestions in this article:
    jQuery.ajaxSetup({ dataFilter: function(data, type){ 
      return (!data || jQuery.trim(data)=="") ? "{}" : data; 
    } });
    
October 27, 2010 | View Comments

Introducing Todoly.net

So, I’ve been really slacking with the blogging lately, I haven’t even been posting my learnings which is a 10 minute process at most. Hopefully I can get back in the habit, no promises though. Okay, so what have I been up to the last little while? Well, I’ve been working on a little side project app that I recently put up and wanted to talk about a little bit.

What is it?

Well from the post title you can probably guess it is called Todoly and can by found at todoly.net. Todoly is a really simple todo list application with very few features and is happy that way. I can hear you now, “Why did you bother writing another todo list app, have you not heard of X, Y or Z?”. Because I wanted to dammit, that’s why.

Background

More than just wanting to write something I did have a few specific goals that writing Todoly has helped me to achieve.

  1. Build something using Rails 3.
  2. Try out my Rails App Template and expand on what is included in it.
  3. Actually finish something and get it deployed publicly.

Todoly has done all these things for me and more. I’ve been able to play around with some of the cool new things in Rails 3 like the new query interface, unobtrusive javascript, responders and much, much more. I’ve found a number of bugs in my app template and have a few ideas on things I can add to make it more complete. Last, but not least, I got to try out deploying an app to Heroku (which was amazingly simple) and have it running in the wild.

This last point was really important to me and was the main reason for choosing a simple todo list application. I’ve worked on a number of side projects over the years but never actually released a working application because I got bored with the project, had another idea or life distract me or whatnot. I’ve released lots of bits and pieces to my github account but it feels very different being able to finish a project and put it out there.

What’s under the hood?

Todoly is a pretty straight forward Rails 3 application running locally under MySQL and under PostgreSQL on Heroku in production. I used a number of gems and open source projects include, but not limited to:

Did I mention that the source for the whole project is up on GitHub so you can check it out yourself if you want. This has already led to some cool stuff, like a friend of mine taking the idea for the app and implementing the same features in Node.js. You can take a look at that on GitHub as well, right here.

Why is Todoly better than X, Y or Z?

In all honesty it probably isn’t any better than the other, countless, todo list applications out there. I have been using it regularly for a little while though and like it for a number of reasons.

The main reason I like it is the interface is really simple. It’s all about adding tasks and completing them, so that’s what the interface helps you to do. I added a cool little feature that lets you focus on a groups of tasks by selecting the tag you’re interested in. I find this to be all I really need to keep track of what I need to do.

Since I have the code and can push a new release whenever I want if there is ever something I need from the application I can just add it. Since the project is open source you can fork it and do the same. I’ll gladly pull in new features and bug fixes and release them to the main Todoly.net website as well.

Where to now?

I have a number of features I would like to add to the application such as task reordering, making a better homepage and making some tweaks to clean up the UI a little more. I probably wont get to those until it becomes a problem with my everyday use.

Until then I’m going to start working on a native iPhone application that talks to Todoly. I fixed up the styling the other day so that it works pretty well in Safari on the iPhone but going with the same premise for the Todoly web application, I want to actually finish and release an iPhone app. I’ve already started and the source will also go up on GitHub once I make a little more progress. I’m also going to try and make it so you can point the iPhone application to a different url for it’s data, so if you want to run your own Todoly somewhere else or run glongmans version it should “Just Work”™ with those backends.

I’m also curious about making a Rails app an Oauth2 provider so I might build this into Todoly to start playing around with that. There doesn’t seem to be a whole lot of up to date information on doing this so it would be nice to get a good example or even extract a gem out of the work.

Anyways, that’s all I have to say about Todoly at the moment. Please check it out and let me know what you think, either in the comments here or by sending me an email at jduff@todoly.net.

October 24, 2010 | View Comments

Learnings for Week 34 2010

  • In the latest version of X11 (on Snow Leopard at least) there is an option in the preferences to allow clicks to go through windows. This makes applications like Gimp actually usable in OS X since you don’t have to click twice anymore (once to activate the window and another time to click the actual tool or menu you wanted)
  • The Asterisk background command can take multiple files to play, each joined by ‘&’
  • Adhearsions get_digits, :play[“file1”, “file2”…] plays the files in order and is interruptible by pressing a key, much like the Asterisk background command.
  • If naming a class/module/file with the same name as something in the Ruby Standard Library they should be scoped by a unique name to prevent clashes.
  • Rails adds ‘collection_ids’ method to models that have a belongs_to association. This gets you all the ids of the associated objects in an array. ex:
    Organization.user_ids
    
  • If you’re having trouble with the Glassfish Admin not loading it could be it’s trying to check for updates over the network. We found some good instructions on how to disable this by editing the glassfish domain.xml and removing some jars. Note that in our setup the xml file was at
    %GLASSFISH_HOME/glassfish/domains/domain1/config/domain.xml
    
  1. Update the
    %GLASSFISH_HOME/glassfish/domains/domain1/domain.xml
    
    <java-config> 
         <jvm-options>-Dcom.sun.enterprise.tools.admingui.NO_NETWORK=true</jvm-options>   
    </java-config> 
    
  2. Remove update tool jar (Backup and remove this JAR)
    %GLASSFISH_HOME/glassfish/modules/console-updatecenter-plugin.jar
    
  3. Delete this dir:
    %GLASSFISH_HOME/glassfish/domains/domain1/osgi-cache%GLASSFISH_HOME/glassfish/domains/domain1/generated
    
  • To follow redirects with curl add the -L option
    curl -L http://example.com
    
  • We watch a new webcast on JRuby that highlights a few interesting features, most notable being that the next version of JRuby and warbler will allow you to build a executable jar file with a embedded web server. This is also interesting because you can have it only package class files so you don’t need to distribute your source with the application.
  • Also from the JRuby webcast some interesting tools:
  1. VisualVM for profiling your java or jruby applications.
  2. jps to show java process status.
  3. jstack to print the stack of a running java process.
September 17, 2010 | View Comments