IExtendable while (this.IsAlive) self => self.UpdateAll()


Chef, Windows, & Docker

At Redacted Industries we use Chef to deploy our applications to various environments. An environment for us is a complete set of servers and applications configured to talk to one another. Environments are designed to mirror prod as much as possible.

The majority of our applications are written in C# and target the Windows operating system. Accordingly, developers are assigned a windows VDI and given access to a spate of tools for Windows-based development.

Our DevOps group on the other hand primarily works in Chef & Ruby. Their standard-issue hardware is a Macbook Pro.

Ruby on Windows

Ruby is less than awesome on Windows. There are a host of issues, but the main problem is that gem does not want to install binaries to the host OS. Rather, gems that require C-compilation are built from source when they are installed on the target OS. Gem developers do not always test their C-compilation on both Linux & Windows so Windows compilation is often neglected.

The community attitude toward this problem tends toward "Show me the PR!" This is a typical attitude in open-source, but few modern developers have the stamina to master the vagaries of C-compilers so the reality is these sorts of problems are seldom touched.

Despite these problems, I am able to develop Ruby applications on Windows with relative ease. It takes some time and effort to learn where the dragons are and slay them, but it can be done.

ChefDK & Embedded Rubies

Ruby devs often want to build gems against different versions of Ruby. Controlling which version of ruby you're using at any one time is a challenge. There are tools such as rvm & rbenv to help but the tools are not awesome. To further complicate matters, OS/X comes with its own embedded Ruby as does ChefDK.

It is a challenge to keep straight which code is supposed to be installed in and run in the context of which version or Ruby, especially since Chef can be used to install versions of Ruby different than what it is running under. Further, the ChefDK is not designed to play-nice with other Rubies. In discussions with the developers at OpsCode, they say that the ChefDK is designed for people who are not going to be developing Ruby applications in any environment other than Chef. It becomes problematic when the Chef docs tell you to install certain gems and you end up installing them into the wrong Ruby. Gah!


If you haven't read about Docker yet, stop reading this blog and go read about Docker. Docker lets you create lightweight VMs known as containers. A container isn't really a VM--it's a process. I think of it as a process that thinks it's a VM.

What if we could create a docker container pre-configured with the ChefDK such that the Chef tools are deployed correctly in a way that is isolated from my other Rubies? Ideally, I'd be able to point the ChefDK container to my local source files on Windows. I can still be on the network, have access to email and company chat, use my favorite text editors--but when I need chef commands, I can duck into the container context long enough to do what I need to do there and get out.

Sounds awesome!

The DockerFile

A Dockerfile is a description of an image that you wish to build. Here is a sample:

FROM ubuntu
MAINTAINER Chris McKenzie <>

RUN apt-get update
RUN apt-get install -y curl git build-essential libxml2-dev libxslt-dev wget lsb-release

# RUN curl -L | sudo bash
RUN wget
RUN dpkg -i chefdk_0.6.2-1_amd64.deb && rm chefdk_0.6.2-1_amd64.deb

RUN chef verify

RUN apt-get autoremove
RUN apt-get clean

First, you use the Dockerfile to build the image.

docker build -t chef-workstation .

The Powershell Script

To make the Docker image usable, I need to create containers from it. Containers are instances of an image that you can use. Containers are disposable. To that end let's write some powershell to wrap up complex docker commands into something I can call easily.

  $username = $env:UserName

  function Invoke-Knife() {
    $cmd = "docker run --entrypoint=knife --rm -w='/root/src' -v /c/Users/$username/.chef:/root/.chef -v /c/Users/$username/src:/root/src -it chef-workstation $args"
    write-debug $cmd
    Invoke-Expression $cmd

  function Invoke-Chef(){
    $cmd = "docker run --entrypoint=chef  --rm -w='/root/src' -v /c/Users/$username/.chef:/root/.chef -v /c/Users/$username/src:/root/src -it chef-workstation $args"
    write-debug $cmd
    Invoke-Expression $cmd

  set-alias knife Invoke-Knife
  set-alias chef Invoke-Chef

This script defines 2 functions: Invoke-Knife and Invoke-Chef. Let's break this command down step by step.

  • docker run
This command runs a container
  • --entrypoint=knife
Tells Docker to execute 'knife' automatically when the container is created.
  • --rm
Tells Docker to remove the container after its process stops.
  • -w='/root/src'
Tells Docker to run 'knife' in the working directory '/root/src'
  • -v /c/Users/$username/.chef:/root/.chef
Tells Docker to share the .chef directory from the Host OS to '/root/.chef'
  • -v /c/Users/$username/src:/root/src
Tells Docker to share the src directory from the Host OS to '/root/src'
  • -it chef-workstation
Tells Docker to allocate a tty for the container process and create the container from the 'chef-workstation' image
  • $args
This is the powershell variable containing the arguments passed to `Invoke-Knife`. These arguments are simply forwarded to knife when the container is executed.

What Happens Next?

When I execute 'knife search ":"', 'knife' is an alias that executes Invoke-Knife--which starts the container and passes 'search ":"' to the knife executable in the container. As soon as the 'knife' process finishes its work and emits its results, the container is shut down and deleted. If I execute 'chef generate cookbook fredbob', a similar process happens except that the 'chef' executable creates a cookbook in '/root/src' on the container--which is mapped to my source directory on Windows. Both executables use the chef credentials I've defined in my .chef directory on my Host OS.


I'm putting this out there because I've found it helpful, however there may be simpler, better ways of doing things. I'm open to comments and suggestions for other ways to resolve any of these issues, or for more interesting ways to use Docker.


Of Purple Squirrels – How to Work with an Agency Recruiter


We all get them, those emails from recruiters in our inbox breathlessly telling us about some new opportunity somewhere. If you're like me, you just delete most of them unread. In my case they're usually for other cities, or from my old hometown 3000 miles away. This tells me that the recruiter in question hasn't read my updated profile. This is what we all hate about recruiters... until we need them. This love-hate relationship with recruiters gets even more complicated when you are a hiring manager.

I married a recruiter. My wife places Accounting & Finance professionals for a recruiting firm in downtown Seattle. It's interesting hearing about her work. Listening to her gave me a whole new appreciation for what she's up against.

First, all you need to enter the profession is a phone and a computer. The barrier to entry for recruiters is very low. Many recruiters begin and end their careers in a matter of months. It's important to understand this because many of the junk mails you receive are likely from amateur recruiters who have no other tools at their disposal than an email blast and buzzword bingo. If you paint all recruiters with the same brush, you risk missing out on some great partnerships both as a candidate and as a client.

A good recruiter is more than just a resume service. To work with recruiters well, you should understand the problems they face. Pro tip--many of the problems they face are you.


For most of us in tech, hiring is an annoying chore that distracts us from our real work. If this describes you, change your attitude. Hiring is the single most important way you will impact your company's culture. No other single decision you will make has broader reach. Make hiring the most important thing in your list of things to do.

Ask yourself, what makes hiring such a chore? For me it was the endless stream of annoyingly similar resumes and blah candidates on the phone. I decided to arm my recruiter with tools to slow down the rate at which they send me resumes. "Unless the candidate says something like x in response to question y, I don't want to talk to them."


Hiring Managers tend to hate talking to recruiters. Recruiters always seem to have another resume in their back pocket. Resumes are boring and don't really tell you much about a candidate anyway (except that one I got that was a photocopy of a coffee-stained piece of paper--I learned everything I needed to know about the candidate from that one!) Recruiters aren't any more psychic than you when it comes to resumes and phone screens... or you. The best they can do is integrate your feedback into their process moving forward. In order to do that, they have to actually get your feedback.

There are some things you can do to make sure they get the information they need.

  • Don't hide behind HR. HR departments are great for running background checks and whatnot. But they necessarily don't know you, your department, or your culture. Include HR on the search details, but if you have an HR department that likes to run the hiring process for you, insist on taking control yourself. At the very least you should be involved in every step of the hiring process.
  • Commit to a 24hr response time on hiring-events. This includes (but is not limited to) emails, phone screens, in-person interviews, texts, etc. If you talk to a candidate and fail to deliver feedback to the recruiter, you are telling the recruiter that your hire is not a high priority. If it's not a high priority to you why should it be a high priority to them?
  • Arrange a weekly or even semi-weekly checkin call to see how things are going. If you're doing Scrum you already have daily checkins. Treat hiring just like any other project. When you hire a recruiter, you are partnering with them to find a good fit for your open position. Treat them like a member of your team. Find out what's going well and what's not. If they need something from you to be more effective and it's reasonable, give it to them.

Purple Squirrels

Third party recruiters often work solely on commission. They often receive searches that they call "purple squirrels." A purple squirrel is a difficult-to-fill requirement. When you're paid on commission, you want to work searches that are easy to accomplish. Purple Squirrels are the opposite of that. They take more work to understand the client and the culture. They take more work to identify matching candidates. Since the likelihood of finding a matching candidate is lower, purple squirrels get lower priority on your recruiter's desk.

If you have a Purple Squirrel and you want them to treat you like a priority anyway you'll need to sweeten the deal:

  • Tell your recruiter that you have a purple squirrel (use the term--they know it and will appreciate that you know it).
  • Commit to giving your recruiter access to the hiring manager
  • Reduce or eliminate their competition. If you trust your recruiter, give them the exclusive search. It might seem to you like you're better off having an army of search firms trying to find your perfect candidate, but the reality is you're simply reducing their motivation to work for you.
  • If you can't commit to an exclusive, give your favorite recruiter a 2-4-6 week head start.


It bears repeating--giving your recruiter an exclusive on your search is the best way to get them motivated to find your purple squirrel. If you're not comfortable with an exclusive, at least give them a good head start. I've told my primary recruiter that as long as I have high quality candidate flow the search is his exclusively. I've also been very clear that I prefer quality to quantity.

Clear Acceptance Criteria

If there are criteria that rule a candidate out for you, be up front with your recruiter about that. If you can't clearly define who you're looking for, how do you expect your recruiter to? Give them open-ended questions they can ask candidates before sending them to you. Tell your recruiter the kinds of answers you would like to see. Tell your recruiter what kinds of answers would mean you don't want to talk to the candidate. I asked my recruiters to tell me what candidates found interesting or exciting about our job description. I told them what was important to me about our job description. Paying attention to clear acceptance criteria will help the recruiter filter candidates for the ones you actually want to talk to.

As a hiring manager you should have some idea of the skills and interests you are hiring for. If you tell your recruiter you want a "rock star" but don't offer any clarification you shouldn't be surprised if your candidate shows up to the interview both late and high. It's fine to refine your requirements as you interview more and gain better insight into who works and who doesn't. However, if you're making radical shifts in your hiring requirements between candidates, your recruiter has no idea how to work for you.

When you're hiring, don't just think about the work you want done--think about who wants to do that work. Often it's not somebody who's already been doing it for years, but someone who wants to learn it. Some things you can teach and some things you can't. Be clear-headed about what you're willing to teach and what skills and knowledge are an actual requirement.


If you don't trust your recruiter you should find a new recruiter. If you don't trust any recruiter, then perhaps the problem is you, no? Some people are afraid to tell the recruiter what they're looking for for fear that the recruiter will coach the candidate to answer certain questions in certain ways. I'm sure that there are some unscrupulous recruiters out there who would do that, but it's short-sighted. Most contracts with recruiters are written so that if there's a "fall-off" (i.e., the candidate leaves or is fired) in a certain time-frame, then the recruiter is on-the-hook for a free replacement. Search firms will often even assess the recruiters commission for the original placement after a fall-off. Recruiters are not financially rewarded for placing bad people in your department.

My Experience

Prior to implementing these ideas into my hiring practices I hated hiring. It was a chore. My email was always full of new resumes to review, more phone screens to schedule, and more on-sites to waste my time on. Phone screens often yielded candidates that seemed surprised by questions like "What sorts of things do you do to keep your skills up-to-date?" On-sites showed that even "experienced" candidates couldn't solve simple algorithmic problems at the keyboard. Eventually, after enough time wasted by myself as well as my team-mates we would eventually find someone we wanted to hire. I now think of this as the "brute force search" method of hiring. As developers we know that this is inefficient.

After implementing these ideas, my inbox dried up considerably. Instead of 10-25 resumes in my inbox every week I would get 1 or 2. When I talked to the candidates on the phone I almost always wanted to bring them in for an on-site. The on-site interviews have almost all been positive. We went from a department that made offers to candidates 5% of the time to a department that makes offers 80% of the time. In short, my recruiter now does most of the initial filtering for me. Sometimes our check-in calls consist of him telling me about the candidates he chose not to submit to me. When he wants to send someone over to me, I've learned to trust him that I should talk to them. Because I did a good job telling my recruiter who we're looking for, we now get candidates who want to work in an environment like ours. We have candidates self-select out because we do a good job of describing our environment up front. All-in-all, our search is now targeted which means it takes less of my time on a day-to-day basis to find quality candidates. I win.

Tagged as: No Comments

Richmond 0.3 released

Release Notes


  • Richmond was failing on binary files. Richmond can now be configured to ignore
    or target specific files or directories via a .richmond file found in the root
    of the directory being processed.


Richmond will look for a file called .richmond in the root directory you are running against.
If it finds the .richmond file, it will load it.

You can use the select or reject methods to change which files Richmond will include or exlude
in it's processing.

# Richmond doesn't like binary files
Richmond.reject do |file|
  file.match /images/

# I only want to parse .rb files do |file|
  file.match /\.rb$/
Tagged as: , , No Comments

My First Gem – Richmond

The Context

I'm building a Ruby API in Sinatra and publishing it's documentation using Swagger. I didn't really like any of the tools to generate swagger docs from the Ruby code so at first I was handwriting the JSON files myself. Then I decided that it would be easier to manage in YAML.

YAML was definitely a better solution than handwriting the JSON, but I was still wishing that the documentation for the models and API's were embedded in the code they described.

The Solution

I decided that the documentation would live with the code come hell or high water. I figured I could use Ruby's block comments with a little bit of special formatting to identify documentation sections throughout the code base and lace them all together into one or more output files. The result is Richmond (named after the character in the IT Crowd who would have benefitted from some documentation telling him what all the blinking lights did).


After you install the gem, you can execute the gem from the command-line like so:

richmond /dir/to/scan

You can find the code for richmond on github, as well as additional documentation.


Installing an Optimal Vim Experience on Windows


I'm assuming you'd rather not compile Vim for Windows yourself. I don't blame you. I tried it and it's a nightmare.

These are manual steps, unfortunately. :(

For the best vim experience you should get the version compiled with Ruby and Python support.

Ruby and Python support does not necessarily mean that you will be coding in Ruby or Python, but many of the plugins that you will want to use require vim integration with Ruby and Python.

These instructions assume you are working in a Powershell console and that Chocolatey is installed.

Install Ruby

choco install ruby -Version

If you need other version of ruby, go ahead and install them now.


You only need to install uru if you are using multiple rubies. Rvm does not work on Windows and Pik is no longer supported. Uru works fine.

Install Uru

You'll need to add your ruby installations to uru using

uru admin add /path/to/ruby/bin

Installing Python

choco install Python2

Install Vim

Now you are ready to install vim.
Unfortunately, the version available on is hard to get to work with Ruby and Python on Windows.
However, Alexander Shukaev (Haroogan) has compiled a version that works nicely.

Download Vim from Here

Extract the zip file where you want it and make sure the location of vim.exe is in the path before any other vims on your system (for example, if you have msysgit installed).


If this works, you should be able to execute the following commands in vim.

:echo has('ruby') => 1
:echo has('python') => 1

Install .vimrc

I keep my .vimrc file as a gist.

I clone it into my C:\git directory.

git clone vimrc

Then I create a symlink from my $HOME directory to the vimrc file. This allows me to maintain the file across machines using git as a synchronization tool.

From powershell

cmd /C mklink .vimrc C:\git\vimrc\.vimrc

The "cmd /C" section is necessary in Powershell because not all cmd.exe commands have been ported yet.

Install Vundle

Vundle is a package manager for Vim. It uses github as a package source. This is about as easy as it gets :)

git clone ~/.vim/bundle/Vundle.vim

Install Bundles

Open vim and run


This should download the bundles specified in .vimrc

I'll maintain this documentation in my configure-win-dev-workstation repo.


What We Can Learn From Usability Failures in Destiny

Destiny is a great game. It is getting a lot of complaints due to some obvious failures such as not having enough content, lacking LFG or match-making mechanics for the more difficult missions, and not having a lot of character customization options. These are all true and valid criticisms, but I still find myself playing the game a LOT.

Recently I've found myself focusing on another kind of failure in the game. These are user-experience failures. I thought that it might be fun and useful to clearly identify them because some of the principles involved may be useful in other kinds of software.


Destiny is constructed as a series of play areas where you can do different things. There are areas with missions and enemies (Venus, Earth, the Moon, and Mars), a safe-zone on Earth called The Tower in which you can trade with merchants and receive bounties, and Orbit where you can see all these areas and decide where you want to go next.

Orbit is useless.

It should not be in the game.

Orbit basically lets me look at a map of places to go, select one, and go there. This would be fine if I didn't have to pay the cost of load-time in order to transition from one area to another. If I'm on Earth and I want to turn in some bounties and then go to Mars, I have to:

1) go to orbit (load time)

2) go to the Tower (load time)

3) go back to orbit (load time)

4) go to Mars (load time)

Instead I should be able to:

1) go to the Tower (load time)

2) Travel to Mars (load time)

In fact, I should be able to travel directly from any one area to any other area without having to load a special context in order to see a map. If I want to skip the Tower, I should just be able to:

1) go to Mars (load time)

Why is orbit even a thing? Why can't I access the map from any location? Why can't I stay in the world I'm in after a mission?

The Sin: Wasting User's Time

Destiny shoehorns the player into a workflow that doesn't make sense for the player and wastes their time. If there is a technical reason for this workflow, Bungie should solve the underlying problem in such a way that the user's play flow is streamlined.

Joining and Leaving a Fireteam.

Let's say I'm in the Tower and I'm invited to join a fire team. Let's stipulate further that the fireteam is also in the Tower. The game

1) immediately takes me to orbit

2) and takes me back to the Tower.


Likewise, if I'm in a fire team and I leave it the game almost always takes me out of where I am and sends me to Orbit (which as I've already stated is useless).

The problem here is likely technical (but it's solvable). I imagine that the issue is that I'm in the The Tower on a different server than the rest of the fireteam. Bungie has chosen to solve this problem by taking me out of the current server and completely reloading a new context on the new server with the same fireteam. Other MMO's have faced this problem and solved it without forcing the player to reload the same environment they're already in.

The Sin: Wasting User's Time

Destiny is forcing the player to endure the consequences of their bad design decisions.

Cut Scenes

OMFG I can't believe I'm even having to say this so late in the development of video games. Unskippable cut-scenes are the 2nd to worst sin in games. The first is unskippable cut scenes that start immediately before an epic battle which will likely kill the hero many times before the player succeeds. Having to watch the same cut-scene over and over between attempts frustrates the player and drains enjoyment out of the game-playing experience. Some games are so bad with this that I have stopped playing them altogether.

Attention Game Developers--I'm interested and willing to watch your cut-scenes once. I know you put a lot of work into them and want the players to see them and enjoy them. However, the game is supposed to be fun, and watching the same @$#*$_)(*!@&)(*&$ movie over and over again makes the game not fun. Please for the love of all that is bright and good in the world, stop!

If I was a professional game reviewer, I would immediately dock 20% off of the game score for doing this once. In Destiny, no cut scenes are skippable. Gah!

The Sin: Wasting User's Time

Failing to understand what the player wants out of your game and instead pushing your own agenda on the player leaves a bad taste in the player's mouth.


Hmm, it looks like all of these problems are a variant of the same thing. The user's time is valuable and the workflows you design for your software should be designed to get user's where they want to go as fast as possible.

Destiny is a great game. It's a well-executed MMOFPS and I'm still enjoying playing it. However, it has some serious warts. All it will take is a more competent competitor to enter this space to get me to play (and recommend to my friends) something else.

Filed under: Uncategorized No Comments

Seattle Code Camp 2014

I gave 2 presentations at Seattle Code Camp today.

The first was a talk about our internship program. I'm still trying to start the conversation on this one. So far it appears no one is talking about this topic. My powerpoint is here: Scaling Craftsmanship Through Apprenticeship. It's not much more than just a memory-jog for me, but they were asked for so I'm posting them.

The second talk was about Unit Testing Your Javascript. This one sort of went sideways when Chrome refused to load my demo site. That was a challenge! Still, I think it went off okay. The unfortunate reality is that unit testing in Javascript is still pretty hard.  It still feels like a lot of duct tape and baling work to make it work. That said, I've put together a demo application that shows how we do it at work.

Thanks to everyone who attended my presentations. I hope you enjoyed them!

Filed under: Uncategorized 1 Comment

Running a Software Development College Internship

Introducing an college internship program into a development organization can be a difficult challenge. There are precious little resources available on the topic. Here are some thoughts I’ve put together after working with interns over the last year and a half.

What Does Your Department Want?

Deciding what value you hope to gain will go a long way toward helping you decide what the features of a good internship program should be. From the intern’s perspective, they want an opportunity to learn, to network, and to gain experience. If you don’t have anything that you want out of offering an internship, it will be hard for you to run it effectively.

For our part, we want to expand our existing “learning organization” culture. We regard our interns as potential sources of hiring. We want to improve the overall quality of software in general by teaching new programmers some of our hard-won knowledge of principles, patterns, and practices. We want to aid our business by making interns available to work on small-scale projects that almost never get prioritized.

Establish a Primary and Secondary Mentor

Each intern should have a primary mentor who is responsible for directing their day-to-day activities. In addition, each intern should have at least one adjunct mentor who checks in with them each week to see how they are doing. Often a different ear will hear things that the primary mentor will not, such as if the primary mentor is moving too fast or too slow, or if a different teaching technique would be helpful. This feedback is important to gain early so that the learning process can be tailored to the individual intern.


As a mentor and trainer to interns you will be confronted with the sheer number of concepts, processes, tools, techniques that you simply take for granted. In our shop interns have routinely never seen source control, build servers, unit testing, code bases with more than a few hundred lines, third party tools such as ReSharper, third party libraries such as jQuery, and project management tools. We have to teach them all of those things before they can be productive in our business.

In its current incarnation, our interns spend 20+ hours per week in the office. Below are the materials that I really want them to learn over the course of their internship. Time is short and there is a lot to learn, but the mentor should resist the desire to go too fast. I’m covering concepts with my interns that it took me 10 years to learn. I’m trying to introduce them to these concepts so that they understand them well enough to begin using them in just over a month. This is an enormous challenge for both the intern and the mentor. The mentor needs to remain patient and allow the intern time to digest and practice what has been covered so far before diving into the next subject.

Most importantly, do not push the interns to learn topics that build on other topics they do not yet understand. For example, don’t teach mocking tools before they’ve learned the basics of Test Driven Development.


Interns need time to practice the material you are teaching them. Remember, you have been doing this for years. They’ve been doing this for days. The difference is important. Given them breakable toys to work on. Teach them the concept. Pair with them to practice the technique the first time. Follow up with a different practice exercise for them to do on their own to be sure they have it. If you can’t find a good practice exercise, create one. If the intern does not seem to be “getting it” from you, consider having the intern work with someone else for the material in question. Sometimes an alternate perspective is all it takes to make the material sink in. If that still doesn’t work, move on to something else and come back to the material later.


It can often be hard for interns to “get started” with whatever task they’re supposed to be practicing. For example, after reading about Test Driven Development, they may feel confident that they understand the concepts. In practice however, they are often unable to write their first tests. As the primary mentor, you will need to work directly with them to help them “get over the hump.” By pairing with them, you will see concretely what they do and do not understand. You should give broader context for what they do understand, and direct their learning and practice toward what they do not understand.


Learning is what the intern is here for, but where do you start? How do you work with someone with no prior work experience? How do you teach them all those things you take for granted? We want to welcome new people into the software development industry, but we don’t want to sacrifice code quality.

I accomplish this in a couple of ways.

The first thing I do with a new intern is setup an online Kanban board with them. I’m using Trello right now. This is important to keep track of each intern’s progress. Further, the intern’s learning is a project in it’s own right, so it’s natural to treat it the way we treat other projects.

During the first month they are given the time and space they need to read, watch training videos, and practice what they’ve learned on breakable toys. I spend 1 to 3 hours per day working side-by-side with the intern during this period to guide their learning. The order of the learning is not terribly important, though there are logical dependencies between some concepts that need to be observed.

I require that all of their work is placed into source control. I want the intern to get comfortable with github right away as all work should be done using source control. Many interns have never worked with source control at all, so learning git right away can be challenging. A good exercise for learning github is to have them import their school projects into github. If the intern likes the command-line that’s fine, but I usually tell them about great GUI tools such as SourceTree. I find that the GUI really helps people new to Git grok the concepts. (I still use the GUI myself Winking smile .)

The other thing I think it’s important to discuss early is the value of clean code. Our interns are given copies of Clean Code and Clean Coder on their first day. Of all the books listed, this is the one it’s most important to me that they read. A recent idea I had about how to practice cleaning code is have the intern use their own school projects (now conveniently located in github) as refactoring exercises.

An intern is not going to master any of the content (that takes continued practice over years), but they will be much further ahead starting their career armed with a basic grasp of the principles, patterns, and practices that it took the rest of us years to learn. The learning should be aggressive and focused on making them productive in your environment as quickly as possible.

Real Code

It’s natural that interns would want to work on something useful for the business. The biggest bottlenecks to making that happen for us are process compliance, automated testing, their ability to navigate large projects, and knowledge of software architectural patterns. Our shop places a high value on automated testing for production code. TDD is difficult for experienced developers to learn, so asking an intern to do it on the first day might be a bit much. This is why we don’t expect useful code out of our interns in the first month. That time is to be spent learning.

After the first month we begin introducing them to code bases we intend to use. These code bases are typically larger than the code that they have been working with in school, so it’s important to spend some time teaching them how to navigate the projects. This time should include a discussion of the logical division of responsibilities inside the project as well as mundane items such as useful keyboard shortcuts in whatever developer tools you are using.

Internship Curriculum

Below is the basic curriculum I put interns through in their time with us. I encourage them to get through as much of the reading and training materials as possible. I start putting them on real code after the first month. I pair with them to find out what they do and do not understand. I do not push them to study topics that build on concepts they do not already grasp. This curriculum is tailored for our environment. We are a Kanban, C#, Continuous Integration shop that highly values clean code. Your curriculum should be tailored to the tools that you use every day in your work.


Onion Architecture Presentation Resources

Thanks to everyone who attended my presentation at #SeattleCodeCamp this morning!

The code I demoed this morning is currently on the “develop” branch on github.

Here are some of the resources for further reading I alluded to.

I had some additional thoughts for future revisions of the presentation.

  1. OA is not just about coding to interfaces. It’s also about coding to the right category of interfaces.
  2. My presentation is in C#, but the same principles apply in any programming language. The implementation details in other languages may differ.
  3. Every recommended approach to Onion has a “fat” layer where the important code is. Other layers are basically façades and coordinators.
  4. In the future, I’d like to show my code diagram first, then show the code, then show the other Onion diagrams.
  5. I need to update my image for my code diagram as the font doesn’t show up well on washed out projectors.

I’d also like to find a DDD implementation of OA and at least one written in another language (not Java).


Isg.EntityFramework 0.9.0 Released (Bug Fix)

Release Notes

  • Fixed a bug in TypeInterceptor in which IsTargetEntity() was not being called before passing the handling down the inheritance chain.