Tag Archives: Work

How to get a job at Puppet Labs

I’ve been working at Puppet Labs for 4 months. It has been awesome! But, I almost didn’t get a job here. I’m going to tell you the secret to getting a job (or at least in development) at Puppet Labs or any open source company.

The interview process goes like this (and here’s the prep guide):

  • Initial interview with senior developer
  • Interview with VP of Engineering
  • Half day of 1:1 technical interviews
    • 2 technical interviews
    • Cross-functional interview (maybe with UX or QA or Ops, etc)
    • Pair programming
  • Interview with Luke

Yes, the CEO still interviews everyone we hire (and many we don’t). I think it’s awesome that Luke makes times for candidates. It makes him more approachable.

Here’s what it takes to get a job offer:

  1. Be awesome at something
  2. Make us passionate about you

Both are well within your power.

We used to have a panel interview in place of some of the 1:1 technical interviews. I had a ho-hum panel interview. I wasn’t mentally prepared for it. I thought I was coming in for a couple pair-programming sessions, not a panel and then pairing. So I was caught a bit off-guard for the panel, and it showed. It wasn’t terrible, just not enough to make them passionate about me. Fortunately, the NEXT day was a Triage-a-thon. I showed up and managed to close a couple tickets. I also continued to submit pull requests for open tickets.

I didn’t do it to suck up to the interviewers. I did it because I was trying to learn more about the product and the codebase. I had barely used Ruby or RSpec at that point and I had *never* submitted a pull request. I needed to learn them, and I was upfront about being a noob. This is what got me the job, not the interviews. Puppet Labs knew I was capable of doing the job, and the hiring risk was low.

That’s the key to making us (or any employer, really) passionate about you:

Show that you can do the job by doing the job.

We have a couple thousand open tickets. Find something that you think you can do and submit a pull request. Rinse, repeat, apply.

I look forward to the pull requests…

EDIT: updated with the refined interview process and official interview prep guide. Yea, feedback in action!

Note to Self: How to Puppetize Interns

Our open source team at Puppet Labs has two interns this summer. It turns out that I will be managing/mentoring them while we refactor Facter.

More than anything, this is a note to myself of things that I want to impart to them.

  • Software Engineering is a balance of business and Computer Science
  • Learn to talk your users’ language
  • Tests accelerate development
  • Software development is a team sport
  • Know whose problem you’re solving
  • Your code has to be maintained by someone half as smart

Software Engineering is a balance of business and Computer Science
Software Engineering is just as much about the business side of what you have time to do, what you’ve negotiated to do, and the realities of shipping software as it is about interesting Computer Science problems. Fortunately, Puppet Labs has both.

Learn to talk your users’ language
Even if you don’t have direct interactions with your users, learning their jargon and language is invaluable. If for no other reason than you don’t have to do the mental translation between what something is called in the code and what something is called in the UI.

Tests accelerate development
Tests help you know if you’ve broken something, but only if you’ve written them and they’re good. A written test is almost always better than an unwritten one, even if it’s the “wrong kind,” i.e. integration instead of unit, acceptance instead of integration.

Software development is a team sport
Developers have to work with other people, that’s just how it is. Other developers, QA, marketing, sales, support, customers, managers, etc.

Know whose problem you’re solving
Solving the right problem for the wrong type of user (or worse, for you) can be devastating to your software. Have some empathy, get inside their head, understand their motivation.

Your code has to be maintained by someone half as smart
It’s usually you, sleep-deprived and under a severe time-crunch. Don’t be overly clever. Later you’ll say, “Who the hell wrote this crap? Oh yeah, me…”

Windows Service and Remote Desktop Mutex Sharing

Yesterday I ran into some weirdness while trying to implement System.Threading.Mutex synchronization between one of my Windows services and a colleague’s application.  The synchronization worked great in the debugger, but when running on a test system, the apps stomped all over each other.

Both had code somewhat like this:

  System.Threading.Mutex mutex = new System.Threading.Mutex(false, "SHARED_MUTEX");
  //some prep work

  //get the mutex for the shared resource
  mutex.WaitOne();

  //work with the shared resource

  //done, release the mutex
  mutex.ReleaseMutex();

Wha?!

I double checked the system mutex name, that was fine.  Didn’t seem like it should be a permissions issue.  The note in the documentation about Terminal Services kept nagging at me.  We weren’t running Terminal Services on the virtual test machine, but we were using Remote Desktop (Terminal Services lite, if you will).

I started by prefacing the mutex from my colleague’s app with “Global\”.  All of a sudden, the apps were working fine on the test system.  But I hadn’t changed my windows service app’s mutex name to look at “Global\”!

  System.Threading.Mutex mutex = new System.Threading.Mutex(false, "Global\\SHARED_MUTEX");
  //some prep work

  //get the mutex for the shared resource
  mutex.WaitOne();

  //work with the shared resource

  //done, release the mutex
  mutex.ReleaseMutex();

It turns out that because my portion was a windows service, it’s execution context changed from being part of the Terminal Services/Remote Desktop session, to being global.  The other app was still in the Terminal Services/Remote Desktop session context because it was an interactive application.  In order for it to lock on the same mutex, it had to explicitly look for the mutex in the Global namespace rather than the Local session namespace.

Makes sense, I guess, but still a little weird. Glad I didn’t spend all day tracking it down either…

How To: WCF Serialization Using Both XmlSerializerFormat and DataContractSerializer

On one of my projects, we’ve recently decided to switch from a SOAP-based interface for our SDK to a REST-based interface.  One potential problem: we can’t break the old SOAP interface.

Ideally, we’d be able to use the same underlying business objects for both access paths, but we were unsure how well WCF’s DataContractSerializer and XMLSerializerFormat would play together.  Our existing SOAP interface made heavy usage of the DataContractSerializer; I know we could have used that for the REST interfaces as well, but we needed to support XML attributes to align and integrate with other internal projects.

It turns out that you can mock up the business objects with attributes for both DataContractSerializer and XmlSerializerFormat, but the interfaces that expose these objects must be different.  So you can’t have, say, an IDataService that functions for both a DataContract interface and an Xml interface.  The attributes annotating the interface methods must be distinct, otherwise the DataContractSerializer will usurp the XmlSerializerFormat.


[ServiceContract]
[DataContractFormat]
public interface IDataService
{
  [OperationContract]
  List<MyObject> GetMyObjects();
}

[ServiceContract]
[XmlSerializerFormat]
public interface IDataService2
{
  [WebGet(UriTemplate="")]
  List<MyObject> GetMyObjects();
}

[DataContract]
[XmlRoot("myObject")]
public class MyObject
{
  [DataElement]
  [XmlAttribute("name")]
  public String Name { get; set; }
}

This may be not be ideal because now we have two interfaces. So, an alternative is to change to a single interface and pushing the attribute annotations to the implementations. That looks more like this:


public interface IDataService
{
  List<MyObject> GetMyObjects();
}

[ServiceContract]
[XmlSerializerFormat]
public class RestDataService : IDataService
{
  [WebGet(UriTemplate("")]
  public List<MyObject> GetMyObjects() 
  {
    return new List<MyObject>();
  }
}
 
[ServiceContract]
[DataContractFormat]
public class SoapDataService : IDataService
{
  [OperationContract]
  public List<MyObject> GetMyObjects()
  {
    return new List<MyObject>();
  }
}