Grant Skinner

The "g" in gskinner. Also the "skinner".

@gskinner

Media Keys In OSX For Any Keyboard

I recently bought a shiny new mechanical keyboard to use with my Mac. So far, I’m liking it, but I miss having media keys for controlling volume and music playback like on my Apple & Logitech keyboards.

To address this, I wrote a few simple Applescript services that you can bind keyboard shortcuts to, which enable media commands (volume up/down, mute, play/pause, and next/prev track) for any keyboard.

You can download them by clicking here. Once downloaded and unzipped, simply double click each workflow file to install it. Note that these are only tested in OSX 10.7 Lion.

To bind keyboard shortcuts to the scripts, go to System Preferences > Keyboard > Keyboard Shortcuts. Select Services in the left panel, then scroll down to the script you want to assign a shortcut to. Double click on the right side of the row to edit the shortcut. Now, just hit the key combination you want to use, and make sure the checkbox to the left is checked (it likes to uncheck when you edit the key combo).

I used the following shortcuts:
Command +:
F13 – Volume Down
F14 – Mute
F15 – Volume Up

Command + Option +:
F13 – iTunes Volume Down
F14 – iTunes Mute
F15 – iTunes Volume Up

Command + Control +:
F13 – iTunes Previous Track
F14 – iTunes Toggle Pause
F15 – iTunes Next Track

I chose these because they are conveniently grouped at the top right of my keyboard, and I don’t use them for anything else. Note that you seem to need to include a Command in your key combo for it to work everywhere.

Also note that I made the system volume control fairly granular (5% increments), and the iTunes control fairly coarse (20% increments) based on my personal preference. You can easily edit these values by opening the workflow files in Automator. The scripts can be found at ~/Library/Services/ once installed.

8 Years, a Retrospective.

I was looking at the blog today, thinking how neglected it is, when I realized that its 8 year anniversary had recently passed. That got me scanning nostalgically through old posts, and wistfully pondering how much has changed since my very first post on Sept 1, 2003.

At the time, I was a spiky-haired, fresh-faced, freelance developer who had just recently won my first few awards, and had spoken at my first few conferences (a thoroughly nerve-racking experience). I was completely unsure of my place in the industry, had no idea how to promote myself (though I was starting to learn), and wasn’t sure what I wanted to be when I “grew up”. I just knew that I REALLY loved building cool things in Flash.

Eight years later, a lot has changed, but the important parts have stayed the same. I’m a grizzled veteran, with more than a few white hairs, and am no longer so fresh of face. I’ve spoken at hundreds of conferences and events around the world, but I still get completely stressed out before every single one. I lead a team of 14 absolutely amazing developers and designers, working on cutting-edge projects for some of the biggest brands in the world, but I’m still not sure what I want to be when I grow up. I just know that I still REALLY love building cool things and sharing them with the world.

There are a few reasons why I still love my work so much. Foremost, I love the continuous challenge and the sense of creation. I don’t think I’ve had a day in the past 8yrs when I haven’t either learned something new, or built something (however small) that I can be proud of. I also appreciate the diversity – I’m sure I’d be a much wealthier man if my company focused on building “enterprise blah blah blahs for the yadda yadda market vertical”, but I much prefer constantly tackling new challenges. We’ve worked on everything from intros & micro sites to frameworks & enterprise apps to games & installations to technical demos & art pieces.

I also really appreciate the people. My own little team is made up of intelligent, creative, and fun people that I genuinely love working with. Our clients tend to be smart, savvy, and eager to do fantastic, progressive work. And, the communities I’ve been honoured to participate in have been hugely supportive and giving. Seriously, the Flash community is one of the coolest groups of like-minded folk I’ve ever had the pleasure to interact (and party) with. I’m still getting to know the HTML/JS community, but I’m hoping they will be equally cool.

I know it’s a bit sappy and cliché, but I have a deep passion and love for what I do, and a great deal of respect for the people I’ve been privileged to work with over the past decade. I’d like to think that’s helped make my work better, but if not, at least I’ve been having fun the whole time!

(and, yes, I will try to post more often – Twitter and G+ have made me lazy)

Creating Great Developers: Conclusion.

Earlier posts in this series: “Introduction“, “Hiring“, “Orientation“, “Training“, “Planning“, “Production“, and “Shadowing“.

At the end of shadowing, the trainee has been with us for 10-12 weeks, has received intensive classroom-style training, has planned and developed a small project from start to finish, and has worked on real commercial projects in parallel with a few of our most senior developers. Throughout this, we have been assessing and providing feedback on their productivity, code quality, communication skills, time management, and problem solving ability.

At this point we know for certain (hopefully) if they are going to be a great addition to the team.

As the 3 month mark approaches, we schedule a meeting with all of the senior staff who worked with the trainees. We compare notes, and discuss the strengths, weaknesses, and growth of the trainee, citing specific examples wherever possible. I take a lot of notes, and bring them into the review.

I like to keep reviews informal, usually over lunch or a beer. I talk to the trainee about what they are doing well, and how they could improve. Again, I try to use concrete examples where possible, so they can relate the input to real experiences. I give them lots of opportunity to ask questions or provide their own feedback on their performance and the training they’ve received.

If things didn’t work out, I make a point to provide them with honest feedback on what I think they need to work on if they want to continue in the industry, and where they could go next. I ask them how they’d be most comfortable with me announcing their departure to the team, and we generally have beers as a group to see them off amicably.

If things went well, I welcome them to the team, ask them a bit about their goals for the future, and start talking through possible projects we could put them on. From this point on we work aggressively to keep them busy on real projects, under the watchful eye of more senior staff who can ensure the quality of their output, and help to continue their growth in the company.

Of course, this whole process requires a large up-front investment which is wasted if we can’t retain our staff. I try my best to make gskinner.com a great place to work. We keep regular office hours, encourage our team to have a life outside work, pay fairly, have a good bonus model, offer praise and appreciation for accomplishments, foster continuous learning, promote a fun work environment, try to book interesting projects, and protect our staff from abusive clients. I would much rather lose a bad client than a good developer.

I have an amazingly fun and talented team that I love working with, and one of the things I’m most proud in my professional life of has been keeping them together over the years.

This concludes the Creating Great Developers series. Hopefully it helps inspire other dev groups to mould a new generation of creative, competent developers, and treat them with the respect they deserve. Interactive development is a creative pursuit, and I’m a strong believer that you can’t get exceptional results by treating developers as a commodity.

Note: I’m planning to revisit this series to do some editing (I’m not completely happy with the quality of writing), flesh out some details based on feedback, and add a persistent index.

Creating Great Developers: Shadowing

Earlier posts in this series: “Introduction“, “Hiring“, “Orientation“, “Training“, “Planning“, and “Production“.

Once the new hire has successfully delivered their internal project, they are ready to move to the next phase of training: project shadowing.

We pair the new hire up with one of our senior developers, and have them work on the same project and tasks in parallel. At the start of each week, the senior developer will sit down with the new hire to outline the goals for the week, help prepare micro-deadlines (ie. production targets for each day), and provide some guidance on architecture and approach.

Throughout the week, the new hire works towards the assigned goals, and is free to ask their mentor for help or advice in an appropriate, organized manner. We schedule time for the senior developer to account for this, so that it does not create a burden on them.

At the end of the week, the trainee is provided with the mentor’s source code and given some time to compare it to their own efforts. They then sit down with their mentor to review their code quality, communication, and productivity. This also gives the trainee an opportunity to ask additional questions that arose during development or (more critically) while they were comparing their efforts to the senior developer’s work.

Besides being another great learning opportunity, it also provides the trainee and the senior staff with applied benchmarks as to how they are performing on a real project, without the risk associated with actually placing them on a client project. An important factor is that shadowing is treated as a serious project by both the trainee and the team, with a project manager, deadlines, and testing / quality control.

We repeat this process for 3-5 weeks, depending on the trainee’s performance. Most weeks we will switch mentors, so that the trainee is exposed to a variety of working / coding styles.

At the conclusion of shadowing, the trainee has been with us for between eight to twelve weeks, and is ready for their three month review, which will is the subject of the next article, available here.

Creating Great Developers: Production

After an extended hiatus, for which I apologize, I’m finally going to wrap up this series with the last 3 entries: Production, Shadowing, and Conclusion.

Earlier posts in this series: “Introduction“, “Hiring“, “Orientation“, “Training“, and “Planning“.

With their plan in hand, the trainee now has 3-4 weeks to develop their internal project. They are assigned a project manager, and expected to treat this project as though it were real client work. This includes checking in regularly to version control, tracking their time, adhering to deadlines, and effective communication of issues to their manager.

They are provided full access to the team in order to ask questions or seek feedback, but are briefed on strategies to leverage this resource effectively without distracting others.

Every week (on beer Fridays) the new hire presents an update of their progress to the entire team. They walk everyone through their code, and ask for input on things they are having difficulties with. This provides the entire team with an opportunity to interact with them, get a sense for their strengths, and provide input on their code quality or approaches. It also gives the trainee experience with managing client feedback and change requests mid-production.

This weekly review is supplemented by ongoing reviews from a senior mentor who will check in every day or two to ensure the project is progressing well, validate their approaches, and do a quick review of their code.

By the end of production, they will ideally have completed coding their project, documented it with ASDocs, fully tested it, and debugged it. The final project is staged, and the trainee presents a full project debriefing which includes an analysis of what went well, what went poorly, and what they would change if they started again.

The senior staff then reviews their progress according to a variety of criteria, including:


  • Adherence to timeline and micro-deadlines or ability to notify management appropriately of non-adherence. Estimating time is hard when you’re new to it, so we expect a lot of inaccuracy. The important thing is that they communicate that back to their project manager in a timely manner.
  • Communication. Did they effectively communicate changes and issues to their manager. Did they utilize the support of the team in an appropriate and non-invasive manner? Did they accept, understand, and implement feedback well? How well written were their docs?
  • Introspection. How well did they judge their own abilities. Were they able to identify weaknesses and work to address them? Do they show an improved understanding of time estimation based on their own productivity? In brief, do they demonstrate an ability to analyze their own performance and work to improve it?
  • Tool use. How well did they use tools like SVN, time tracking, Basecamp, and their developer tools?
  • Code. Adherence to company standards, architecture, appropriate commenting, documentation, use of appropriate frameworks / libraries / patterns.
  • User experience: Did they attempt to create a usable, aesthetically appropriate interface? Do they demonstrate an understanding of UX core concepts and underpinnings.
  • Productivity. How productive were they in the time they had, accounting for things like necessary rewrites, and accommodating feedback?

Based on this review, we may ask them to spend another week or two cleaning things up or extending the project, or we may proceed into the next phase, project shadowing.

This internal project development gives the new hire a great opportunity to learn and apply new technical concepts while gaining an understanding of our processes and all the elements that go into delivering a successful project. It also gives our senior team to evaluate the new hire in a near real-world situation, without any real-world risk.

The next article, on project shadowing, is available here.

Spelling Plus Library (SPL) Version 2 Released

I’m happy to announce that we have released version 2.0 of our Spelling Plus Library (SPL). SPL provides real-time (as you type) spell checking for Flash, Flex, and AIR applications built with AS3. Version 2’s most significant new feature is full support for TLF text and components, including the Spark component set in Flex 4. We’ve also made a number of other bug fixes and enhancements.

To make up for the long wait for this version, we’re offering existing customers who purchased SPL within the past year a free upgrade, and a significant (~60%) upgrade discount to everyone else who owns a previous version of SPL.

We’ve already started work on SPL 2.1, which will add a number of new features targeted at mobile, and will be a free upgrade for all SPL 2 owners.

For more information on SPL, check out the product page here.

Why I’m Excited About FITC Toronto

I try not to spam my blog with posts about every conference I’m involved with, but I’m genuinely excited about FITC Toronto this year. Beyond the usual collection of reasons I like this conference (great speakers, awesome people, good vibe, etc), there’s a list of reasons that are specific to this event:

  1. It’s the 10th anniversary of the conference, and I imagine Shawn (the organizer) has some cool things planned to celebrate it.
  2. It’s being held in the Guvernment, which is a cool space & the first venue I ever spoke in, way back during Flash In The Can 2003 (before it became just “FITC”).
  3. It will be the 20th FITC conference I’ve spoken at, including events in: Toronto (x9), Edmonton (x2), Ottawa, Montreal, Tokyo, Amsterdam (x3), Hollywood, SF, & Chicago. Scary!
  4. I’m going to be super involved. I’m doing 4 separate talks, including my main talk (see #5), a retrospective panel (for us old coots), a Voodoo lounge talk on HTML5 & Flash, and one on one Q&A at the Get A Job event.
  5. I’m switching out the talk I originally planned to do (“ADHD FTW, LOL!!”) for a new talk that I put together quite recently (“The Art of Being Inspired”). In some respects, it’s similar content, but presented in a way that better reflects my current creative optimism and showing some stuff I’ve been playing with recently. Don’t tell Shawn – he hates when I change sessions last minute!
  6. I think it’s a very dynamic time in the industry, and I’m genuinely excited to see what people are working on and thinking about. There’s so much change and that’s bringing so much new opportunity – it’s just a great time to be exposed to other people’s thoughts and inspiration.

Anyway, I know this is pretty last minute, but if you’re in the area, and not going you might want to consider it. I’m not trying to sell tickets, but I think it’ll be a great event. I hope to see some of you there!

The Case of the Disappearing Number

On a current project we were experiencing an issue with a specific numeric ID not working correctly. After some exhaustive debugging, it was isolated it to a seemingly bizarre phenomenon that manifests in both AS3 and Javascript: a missing number.

Specifically, we found that the number 10100401822940525 appears to simply not exist in these programming environment. You can test this for yourself, simply trace or log the following statements:
10100401822940524
10100401822940525
10100401822940524+1
Number(“10100401822940525”)
(10100401822940525).toString()

All of the above statements will output “10100401822940524”, when obviously all but the first one should return “10100401822940525”.

Theres no obvious significance to that value. The binary/hex value isn’t flipping any high level bit, and there are no results for it on google or Wolfram Alpha. Additional testing showed the same result with other numbers in this range.

I thought it might be related to the value being larger than the max 32bit uint value, but adding a decimal (forcing it to use a floating point Number) does not help, it simply rounds it up to “10100401822940526” instead. Number should support much higher values (up to ~1.8e308). I confirmed this with:
Number.MAX_VALUE > 10100401822940526 // outputs true

As it turns out, the issue is a side effect of how Numbers are stored. Only 53bits out of the 64bits in a Number are used to store an accurate value. The remainder are used to represent the magnitude of the value. You can read about this here. So, the maximum accurate value we can store is:
Math.pow(2,53) =
9007199254740992 < 10100401822940525 This means that the precise value is not stored. Knowing this, we can rework our logic to store the value in two uints / Numbers. Thanks to everyone on Twitter that provided input to this article. I'd name contributors individually, but I had a lot of duplicate responses, and don't want to leave anyone out.