Adding bat fins to a wrist brace


2017-09-04 22:42:20 UTC

If you own a wrist brace, but feel like it’s missing a certain something:

Photo of the augmented wrist brace being worn.
Like the fins from Batman’s gloves!

here’s how you can add that to your wrist brace.

You’ll need:

  • A sewing machine
  • Black thread (polyester is fine)
  • Fabric. You’ve got lots of options, but what you need is something either innately stiff, like vinyl, or thin but stiffened by thin cardboard or stiff interfacing. I used this polyester-backed vinyl.
  • Either the 3D-printed template or the 2D-printed pattern to cut out of the fabric.
  • A leather sewing machine needle, if indeed you use leather or vinyl fabric or you use cardboard as interfacing
  • Tailor’s chalk
  • A wrist brace you can sew the fins onto (I used the Walgreens one, which has a thin stretch-fabric section that covers the appropriate spot on the arm)

Read the rest of this entry »

How to QA


2017-07-03 10:37:02 UTC

In my day job, I’m a QA (quality assurance) engineer for a Large Software Company. Today I’ll tell you how to prepare yourself to do a job like mine.

Fair warning: “QA” is a big tent; the details of a QA job vary widely, and your QA job may be very different from mine.

File bugs

(Ira Glass voice) File a lot of bugs. File a huge volume of bugs.

The ultimate responsibility of a QA team overall, and of QA engineers individually, is to produce actionable bug reports that can and do get fixed. The details vary widely, but everything comes back to that.

A good bug report says:

  • what you did
  • what you expected to happen
  • what actually happened, and how that differed

That’s the minimum, actually. That’s the least that’s needed for a bug report to be actionable.

Ideally, a bug report should also include needed diagnostic info (such as a sysdiagnose on Apple platforms), screenshots/video if applicable—as much info as possible, at least at first, to be sorted through for the gems of info that illuminate the actual problem. As a QA engineer, providing as much of this info you can gather is Actually Your Job.

Ah, but what to file? If you’re QAing something manually, you’re looking for:

  • any sort of friction (possible interface design issues)
  • any sort of fault (crashes, hangs, data loss)
  • anything in between (anything that did not do what you expected it to do)
  • anything you don’t know what you expect it to do (can be a design/empathy-for-the-user issue)

Also test anything that had been broken before. Look for regressions (previous problem returned) or new problems (“OK, you fixed X, but now it has problem Y”).

Practice, practice, practice

For filing formal bug reports, two good ways are filing Apple developer bugs and filing bugs with open-source projects.

A few caveats re open-source:

  • Many open-source projects need fixes more than they need more bug reports, so don’t be surprised if folks don’t rush to thank you for adding to the pile. Concentrate on high-value bugs (security vulnerabilities, crashes, providing desperately-needed steps to reproduce) rather than nitpicks. (Making this judgment call is itself something that’s valuable to practice.)
  • Search for duplicates first. Apple actually generally likes duplicates and uses them to influence triage and prioritization decisions, but open-source projects may resent the extra scut work of duping bugs together. (Finding existing bug reports is an underrated skill that is also valuable to practice.)
  • I’m a cishet white guy. Your mileage may vary a lot regarding how you and your contributions are received if you are not—anything from well-intentioned over-helpfulness (mansplaining, assumed noviceness) to outright misogyny/racism/anti-trans assholery.

Some open-source projects do code review and/or API review, which can be good practice for spotting designs that invite bugs (random example: “you’re taking a pointer but not the size of the buffer, so the API can’t check that it won’t go out of bounds”).

In that sort of setting, practice asking questions. These could be clarifying (“what does it mean if this returns nil/0?” “This is typed as a String. Are there constants, or what sort of strings should folks pass here?”) or more Socratic (“what does this API do if I pass a pointer to a buffer that’s too small? how does it detect that?”). Even if the immediate response is “that can’t happen” or “don’t do that”, established members of the community/team may back up your question with pressure to resolve the issue (“this should take a length with the buffer, or better yet return a Data”).

Lastly, volunteer for beta tests. I’ve beta-tested Flying Meat’s Acorn once or twice, and I think Panic have also solicited beta testers in the past. Beta-testing is extremely good practice for exploring an in-development product looking for friction and faults and writing up your findings.

As a beta tester, write up everything. Don’t be shy—if it looks wrong, write it up. I have sent in multiple pages of issues and you know what? That makes you worth your weight in gold. (90% of volunteer beta testers are just there for the possibility of a free license. Any developer who’s running a beta test program wants bug reports. They want them urgently—preferably while the product is still in beta.) Even if half the stuff on my list is stuff they meant to do, it’s still worth a second look if a beta tester (or more than one) objects to it, and the other half of the stuff on my list is stuff they may not want to ship with.

The QA mindset

Use your imagination. Try things you wouldn’t ordinarily. Follow the “what does that do?” impulse. Find the cold paths.

Everything that the product engineers thought of is probably really well-tested, and any issues that remain have turned into invisible corners. Your job is to remind them of the invisible corners and tell them about the things they haven’t encountered at all.

Question everything. Is that design optimal? Is the UI copy clear? Could a new user understand both? Was that actually the correct result? Was it the best result?

If you find yourself asking “What does that do?”, that can be a sign of inaccessibility to novices. Inversely, you should learn the product’s domain so you can spot things that don’t make sense in the domain. Try to develop the ability to do both: know the product’s domain and simultaneously spot barriers in the product to users entering that domain.

Be an advocate for users

Make sure the interface is accessible (overly-similar names can cause problems for dyslexic folks; reliance on color or images can cause problems for color-blind or visually-impaired folks).

Familiarize yourself with accessibility tools (on the Mac: Accessibility Inspector, everything in the Accessibility control panel, SimDaltonism) and use them on the product, and file bugs when you get stymied.

Challenge ableist/misogynistic/gender-binarist/racist/otherwise-problematic copy or artwork, using the dual justifications of “this is the right thing to do” and “not doing this is going to repel users/customers and/or cause PR trouble”.

Your QA job may vary

As I mentioned above, “QA” is a big tent. What I’ve described is an important baseline mindset and skillset to a QA engineer, but major portions of an individual QA job could be more sysadmin-oriented (e.g., administering an automated testing or CI fleet) and/or include work with specialized, company-specific internal tools that you’ll have no way to practice the use of outside of that department.

Know at least one scripting language such as Python or Ruby, whether for use in your own QA work (e.g., generating test data, filtering logs) or for working on automation systems (e.g., maintaining Python or JavaScript scripts that drive UI tests). If you’re starting from scratch (and absent any particular job-specific requirements), I’d recommend Python, which you can pick up in a few months, and from which you can learn similar languages like Ruby afterward.

Especially as more automated QA (unit testing, UI automation) becomes more the norm, I’d strongly recommend developing your system administration skills on any platforms you may end up working on. It’s been awhile since I had to start from scratch on this, so I invite you to suggest resources in the comments for learning system administration (on the Mac or otherwise) in 2017.

Chess variant idea(s)


2017-05-13 15:24:54 UTC

Each player has one spy among their opponent’s pieces.

On your own turn, you can switch out one of your opponent’s pieces for an equivalent piece in your color (e.g., black rook for white rook), then move it as one of your own. Ever after, it is one of your pieces.

Possible variants:

  • Reveal your spy on your opponent’s turn instead of your own (you take their turn instead of them taking it).
  • Reveal your spy on any turn.
  • More than two spies.
  • Unlimited spies.
  • Double agents (after revealing your spy, your opponent can reveal that it was their own spy, taking the piece back, ending your control of it).
  • Arbitrary-multiplier agents (revealing a double agent does not end control: a N-ple agent can always be revealed to be an N+1-ple agent).
  • A requirement that you choose your spy beforehand and seal the knowledge in an envelope (rather than choosing the spy to “reveal” at any time). Open the envelope when you reveal your spy.

I don’t know enough about chess to be able to predict how well this would work, or whether anyone has thought of this before (it’s quite likely).

Leather dice bag project


2017-05-07 08:37:26 UTC

Last year, I took a sewing class and bought a sewing machine. Since then, I’ve taken another sewing class, bought another sewing machine, and done my first solo project: a leather dice bag, to keep my D&D dice in. (I was keeping them in the tube they came in, but it’s harder to get the dice back in than just pouring them into a bag, and it doesn’t look anywhere near as cool.)

This wasn’t the first drawstring bag I’d made; I’d done one previously at the first sewing class (there’s a whirlwind tour of operating a sewing machine and then they drop you straight into making things; it rocks), and I made a couple of prototypes from cheap muslin before I started actually sewing the leather.

This was the first time I’d worked with leather, however, and that was interesting. Leather is grippier than most fabrics, so you actually need to use a different presser foot on your sewing machine—specifically, a roller foot. Fortunately, I’d bought a no-name variety pack of presser feet off Amazon Warehouse Deals awhile back, so I had one ready to go.

This is largely going to be a photo tour; I took photos the whole way through the project. I posted the photos on Flickr and will be embedding them here.

Read the rest of this entry »

Super simple solder spool spindle


2016-11-14 20:53:46 UTC

(Also works for spools of wire.)

  • One ³⁄₈″-inner-diameter galvanized pipe cap
  • One ³⁄₈″-inner-diameter 4″- or 5″-long galvanized pipe nipple
  • One ³⁄₈″-inner-diameter to ¹⁄₂″-inner-diameter galvanized pipe reducer
  • One ¹⁄₂″-inner-diameter coupler
  • One ¹⁄₂″-inner-diameter floor flange

Screw them all together, in the reverse order, putting the cap on last after you put the spools onto the pipe.

Photo of my solder spindle, along with a prototype of it holding some wire spools.
Left: My solder spindle built from the above recipe. This is with the 5″ pipe nipple.
Right: My wire spindle, built using ¹⁄₂″-inner-diameter all the way down, which it turns out is too big for one of the solder spools. (It was the first draft; the final spindle on the left is the second iteration.)

Learning to solder with the Make kit


2016-10-30 16:49:08 UTC

I bought the Make: Getting Started with Soldering Kit at the Bay Area Maker Faire earlier this year. I recently completed the set of blinky badges included.

The one on the far left is from months ago. I’ve improved a lot since then, as seen by the rest of the badges.

It’s a good start, but incomplete. You will also need:

  • Goggles. The web page for the kit explicitly acknowledges this. You need eye protection because a blob of solder can go flying when you’re cleaning your iron. This happened to me—fortunately it didn’t go in my eye, but I made damn sure right then to get out my safety glasses and wear them for all further soldering.

    I had the freebie Google-branded safety glasses that they hand out at Maker Faires, but if you don’t have any, get some.

  • A soldering iron that isn’t trash. The iron included in the kit takes forever to heat up, and it’s oxidising all the while. Don’t waste time and energy on it—spend the extra $50 or so to get a good iron.

    Mine is a Weller WES51; it heats to operating temperature in under a minute, and has an LED to indicate when it’s ready.

  • A desoldering iron. I found trying to desolder my mistakes using the included solder-sucker tricky. It might have gone better with the better soldering iron, but I already had this thing from Radio Shack by then. It’s not ideal, particularly in how long it takes to heat up, but it’s still better than an unheated desoldering pump.

    Note that you need to tin the tip of a desoldering iron just the same as a soldering iron. In this case, the “tip” is the flat, ring-shaped surface directly around the hole. Lay some solder across the hole, then suck in any excess and spit it out onto your sponge.

  • Tip cleaning wire. I use this Hakko model. The wad of metal is an abrasive cleaner that you’ll need any time you get too much build-up on the tip and the wet sponge isn’t enough. Ideally that should be rare, but if you find yourself unable to tin your tip because the solder won’t melt or won’t adhere (“dewetting”) and the wet sponge doesn’t help, you probably need to jam your tip around in one of these for a bit.

  • Educational resources. The Make kit comes with a little booklet that isn’t bad, but I needed other sources of info:

macOS installer cards


2016-09-29 20:16:20 UTC

Being both a creature of habit and a digital packrat, I never install macOS from the “Install macOS” app.

Instead, what I do is have a cache of 8 GB class-10 microSDHC cards (usually bought from Micro Center, but they make great Amazon filler items, too), which I permanently assign as macOS installer media.

(I would buy SDHC cards, but Micro Center sells the microSDHC cards for cheaper—50¢ cheaper as I write this.)

Populating the card

Once you have a card, you’ll need to put the bits on it. DiskMaker X is the easiest way to do this, though there is also a manual process.

Labeling it

Anonymous cards all of the same capacity and speed and possibly even description does not scale well as an inventory system. Ideally, your card comes in a clamshell case, like the Micro Center ones do, or you can reassign such a case that came with another card. You can probably even buy empty microSD cases, like you can CD jewel-cases.

I have a Brother labeler that I use to print a small label with the release’s version and marketing name on it: “OS X 10.7 Lion”, “OS X 10.8 Mountain Lion”, “OS X 10.9 Mavericks”, “OS X 10.10 Yosemite”, “OS X 10.11 El Capitan”, and now “macOS 10.12 Sierra”. That label goes on the front of the case.

Photo of my flash memory cards on which I have the past several years' macOS installers. Lion was on an SD rather than microSD card; Micro Center have changed their case form factor a few times; I started printing rather than hand-writing labels with 10.9, and I haven't yet labeled the card that will go to Sierra.
I wrote this while the Sierra installer application was downloading.

And then done

The very pretty installation volume that DiskMaker X created for Sierra, complete with window background matching the installer icon.

Now you have labeled, permanent installer media that you can use forever (or however long the cards last). If you ever need to roll back to an old version, reinstall the dot-zero from the card and then combo-update up to whatever version you want.



2016-09-12 21:48:59 UTC

I just got this ad for Jane Kim, who’s running for State Senate here in California:

“JOIN US as we work to lift more families into the middle class through better public education”! and “Median Annual Wage for City College Graduates: $59,800. Median Annual Wage for High School Graduates: $48,700”

Leaving aside the matters of whether those are livable wages in the City, particularly after taxes and any available savings contributions, and especially for “families” as stated in the headline…

“Join us as we work to lift more families into the middle class…”

A “middle class” necessarily implies a lower class and a higher class.

Right off the bat, this proposition does not even consider lifting families into the upper class. Just the middle class—that’ll do for now, right?

Lifting “more families into the middle class” implies not eliminating the middle class—there’ll still be one, which means there’ll still be a lower class, which means there’ll still be people/families in it.

Certainly this proposition does not suggest ending classes altogether—no; there’ll still be classes, at least three of them. And some will be in the upper class and some will be in the lower class and hopefully more of the latter will move up… to the middle.

Oh, OK.

I feel like this is a lukewarm dish. That’s all you’ve got to offer? You want to make this not only a headline on your flyer, but literally the entire topic of an entire flyer?

I’m not even saying it’s a bad idea. Just… it lacks ambition. It feels resigned. This is the best we can do, it implies.


NB: I feel I should make explicit that I’m not against Kim necessarily; I haven’t looked at any other candidates. And maybe she’s got lots of good policies and/or ideas. Just, this one ad caught my eye and got under my skin.

So you want to run an open-source project


2016-09-11 14:12:30 UTC

How much of this you’ll want to do will depend on just how much of a Thing you want your project to be, on a scale from “I’m just gonna drop some code on GitHub” to “I want to wear the title of ‘maintainer’”.


You don’t have to use GitHub as such; Gitlab and Bitbucket are alternatives, and they’re all more or less equivalent. But GitHub has network effects in its favor: Most potential contributors are there.

“Contributors” doesn’t just mean code. Anybody can clone your repository, check something in, and email you the patch. But writing issue tickets and editing the wiki (if you choose to have one) are valuable, too, and those typically require an account.

Your project on GitHub (or wherever) will include one or more of the following:

  • Code/contents (the Git repository from which GitHub and Gitlab take their names)
  • An issue tracker (more on that later)
  • Forks (other people’s copies of your repository, to which they have their own access to push changes)
  • Merge requests (changes made in one fork, then submitted “upstream” toward the original repository for consideration and possible integration into the “main” code base)
  • A wiki (documentation)
  • A website


Like with GitHub, there are alternatives. Travis is the one I’ve used.

Travis is a continuous-integration system. Whenever someone pushes changes to your repository, or submits a merge request, Travis will build your project and run your tests, according to instructions you provide. It’ll then provide an indication—on GitHub, right on the merge request page—of how well or poorly that went.

There’s a related service called Coveralls that tracks the code coverage in your project—how much of your code is being run by your tests. Code paths that the tests aren’t going through are potential bug sites: When that code path does get traveled, what happens might not be what you expect.

Coveralls tells you how much of your code was exercised, as a percentage, and also gives you a line-by-line map of what code was run and what code wasn’t.

Project infrastructure documents: README, LICENSE, CONTRIBUTING/CODE_OF_CONDUCT

(If you write these in Markdown, they’ll have the .md extension:, etc.)


Your README is your Getting Started guide for both users and contributors. Awesome Labs has a template you can follow (optimized for iOS libraries); the basic points you should cover include:

  • What is the product? What does it do? Why do I need it?
  • What does it look like? (Screenshots/example terminal sessions/example code)
  • What does it require?
  • How do I install it?
  • How do I use it, at least in the most common case?
  • How do I uninstall it (if applicable)?


This is where you put your statement of copyright, and the license agreement for your program, outlining what sorts of copying you explicitly allow and which ones you explicitly don’t. Common ones include variants of the BSD and MIT licenses, GPLv2, and GPLv3.

GitHub suggests a few popular licenses when you create a new repository, and provides an advanced section with many more licenses where you can compare their finer points.


This file describes guidelines for contributors, including:

  • Requirements of the contributions themselves. Examples of such requirements include:
    • Please add tests for any new features, and update tests for any behavior changes.
    • Please run the tests and be sure they pass before submitting your merge request.
    • Your change must pass all tests on all supported platforms. See the README for our platform requirements.
    • Please match the style of existing code. In particular, please use one tab/four spaces/eight spaces/6.34 spaces per indent, and please put opening braces ({) on the same line/their own line.
    • Please submit the complete, original series of changes—don’t squash merge.
    • Please squash-merge your changes—we don’t want the complete, original series of changes.
  • Information on how to contribute, if it differs at all from the usual “fork the project, commit and push your change, then submit a merge request”.
  • Requirements of contributors (e.g., a code of conduct such as the Contributor Covenant).
  • Info about any project mailing lists, IRC channels, Slack channels, etc., perhaps with their own code of conduct, such as the Community Covenant.

Codes of conduct are important for making explicit the standards of behavior you expect from project members and contributors. Don’t tolerate jerks—if somebody breaks your rules, even if their contributions are good on technical merit, kick them out. (You define what “kick them out” means, and may want to document it in your CONTRIBUTING file.)

Known jerks continuing to be tolerated/welcomed in your project is a visible “stay away” sign to other people who might otherwise bring equally good contributions with less hassle.

Issue tracker

Issue trackers are two things:

Your project management tool

You use issue tickets to track the work that has been done and that needs doing.

Most issue trackers provide a category/tag/label feature to identify on each ticket what sort of work it is. You can also create labels for priorities, if you want to track how essential or postponable each item is. (Some issue trackers have a separate priority field.)

Have a “help wanted” or “up for grabs” tag you can put on bugs that you don’t want to do yourself, and mention it in your CONTRIBUTING instructions. “help wanted” bugs are the ones you explicitly reserve for new contributors to do. Most should be simple or good introductions to the codebase, but you can also include harder jobs where (for reasons of your own time) you’re willing to accept the patch but not write it yourself.

You may also be able to create milestones for future releases you’re planning, into which you put each ticket to track when that work should be done (or at least landed), and, inversely, what work must be done before a release can ship.

Everyone else’s wish list

You’ll get a lot of bug reports and feature requests. Many of them will be duplicates, which you’ll close with a reference to the original/anointed ticket for the same bug/request/task.

If your project grows large/popular enough, you may choose to lock down the issue tracker so only contributors can add or edit tickets, and then take requests and bug reports instead through a support email address or form. Whoever reads that email then updates tickets as needed and sends ticket links or ticket numbers to support querents.

You will need to say no to some things, and some people will be displeased. You will also need to postpone some things because they aren’t as important or there isn’t a clear path forward (e.g., no steps to reproduce), and some people will be displeased because they want their feature/a fix now. There are no two ways about it; you are going to make some people unhappy. It’s not your fault.

Be polite; be fair; be the better person. Sometimes that still won’t be enough—some people won’t accept anything less than “yes, right away, it’ll be fixed in the next ten minutes”. And that sucks. But it’s not your fault.

Code review

Code review is where one or more contributors (and/or the maintainer) look at a proposed (or even already committed) change, looking for errors and potential improvements.

Some guidelines:

  • Review the patch, not the person. Don’t call the contributor an idiot or accuse them of wasting their time. Be gentle; be constructive. Yes, even if the patch is total trash—make it a teachable moment. Recognize language barriers and early learners. (But also don’t waste your time excessively—sometimes you will have to give up on someone who is a time sink. Even then, be nice.)
  • Prefer questions to statements. Be open-minded, not reactionary. Be willing to accept that an approach that isn’t what you would have done may be better. At the very least, be willing to accept it if it isn’t worse.
  • Praise good ideas, novel (but not overly clever) approaches, attention to performance, reliability, and ease-of-use, and hard work. Code review isn’t just a place to point out what they did wrong—it’s also a place to appreciate, explicitly, what they did right.

The simplest form is to look at the diff (the proposed change) in each merge request. You can comment on the merge request as a whole, and, on most services, on individual lines within the diff. Use these comments to ask for clarification, ask for documentation/comments, suggest changes, or suggest alternative approaches.

There are dedicated code review tools, such as Phabricator and ReviewBoard. I’ve used Phabricator; it’s good. I haven’t used ReviewBoard.

On a GitHub project, I typically just use the built-in merge request interface.

Package managers

They are many, and which ones you have to choose from will depend on what you’re making. For libraries for Apple platforms, there are CocoaPods and Carthage. For tools for macOS, there are Homebrew, MacPorts, and Fink.

Your README should include information on which package managers you support, and how to obtain your software through them. Expect people to request that you add your software on other package managers, or somebody to add it themselves and other people to subsequently complain to you when it doesn’t work. You decide what you do when these happen.


It should start with your README, but ideally should not end there.

If you’re making a library, have header/API documentation. On Apple platforms, Xcode now has built-in support for this; it’ll display the contents of your documentation comments when you option-click a symbol in C, Objective-C, or Swift code.

Another place to put documentation (and also do broader planning than fits comfortably in an issue ticket) is your project’s wiki.

Here’s how diskutil list describes a CD-ROM I bought at the Big Book Sale in Fort Mason:

/dev/disk14 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:        CD_partition_scheme                        *97.5 MB    disk14
   1:     Apple_partition_scheme                         84.9 MB    disk14s1
   2:        Apple_partition_map                         1.5 KB     disk14s1s1
   3:                        ISO                         46.1 KB    disk14s1s2
   4:                  Apple_HFS Operation Neptune CD    84.5 MB    disk14s1s3

This is an ISO 9660 “hybrid” disc. It presents a Mac volume when mounted on a Mac and a DOS/Windows volume when mounted on a DOS or Windows machine.

The HFS volume here is a fiction; the real ISO 9660 volume (despite its name of “Apple_partition_scheme”) is disk14s1—the first partition.

If you copy this partition, with something like:

sudo cp /dev/disk14s1 Operation_Neptune.iso

You will then have an accurate ISO 9660 disk image that you can mount on your Mac, and thus see the Mac contents, or on your DOS or Windows machine, and see those contents.

man() {
    env \
        LESS_TERMCAP_mb=$(printf "\e[1;31m") \
        LESS_TERMCAP_md=$(printf "\e[1;31m") \
        LESS_TERMCAP_me=$(printf "\e[0m") \
        LESS_TERMCAP_se=$(printf "\e[0m") \
        LESS_TERMCAP_so=$(printf "\e[1;44;33m") \
        LESS_TERMCAP_ue=$(printf "\e[0m") \
        LESS_TERMCAP_us=$(printf "\e[1;32m") \
            man "$@"

Screenshot of Terminal showing the zsh manpage with the above customizations.

Pretty neat, right? Let’s tear it apart, see what it’s doing, and think about how we might customize it to suit ourselves.

Read the rest of this entry »

Back again


2016-08-06 14:48:02 UTC

Sorry for the long period of downtime. It was caused by two things:

  • My previous host, Kaizen Garden, apparently went poof with no warning. (That was why the whole website was down for awhile.)
  • I got most of the site back up on its new home,, but got frustrated when I tried to restore the blog, so I just left it renamed out of sight until I next felt like making a run at it.

That was today. I finally sat down and got it all working, and fully upgraded WordPress while I was at it. The blog is back, everyone! Yay!

You will see some missing images. Apparently the backups I had only covered the WordPress database, not anything I’d uploaded as an attachment—those I only have through 2008. Oops.

Some of them I’ll be able to reconstruct. Fortunately I had good alt text on at least some of them, so I should be able to figure out what was there, and you should be able to make do in the meantime. And some of the images are definitely higher priority than others—the trigonometry figures, for example, will be among the first to come back.

So, please bear with me—the long recovery of this blog isn’t quite done yet. But this is progress.

Unicode date formats, YYYY?!


2015-10-24 08:41:08 UTC

Last year, I tweeted:

This year, I noticed that the problem comes earlier, so I sent out an early reminder:

But exactly what problem am I referring to? Dan Wood wondered exactly what the YYYY issue is and what languages it affects.

So here’s a short explainer, not bound by the constraints of Twitter.

Year for week-of-year

You may have heard of “ISO 8601 format” (2015-01-01), but in fact, that’s only one of three formats that ISO 8601 defines:

  • Calendar format: 2015-01-01
  • Week format: 2015-W01-04
  • Ordinal format: 2015-001

The ordinal format is straightforward: It’s the NNNth day of the calendar year.

But the week format does not work that way. The first week of a year is not even guaranteed to contain January 1st! Rather, -W01-01 (the first day of the first week) is the Monday of the week that contains the year’s first Thursday. (Yes, that is the actual definition from the ISO 8601 standard.)

As such, ISO defines a parallel track of years that have the same year numbers as calendar years, but start and end on different dates (and always start on a Monday). ISO-week-year 2015 starts on the Monday of the week containing 2015’s first Thursday; that Monday is Monday, 2014-12-29 (2015-W01-01). 2015-01-01 is Thursday, 2015-W01-04.

Unicode date formats

YYYY and yyyy are Unicode date format patterns. These offer quite a bit more flexibility than the old str[fp]time(3) formats, particularly in choosing different representations of the same value (e.g., “September” vs “Sep” vs “09” vs “9”).

  • YYYY is defined as the “year for week-of-year”: that is, the year for ISO week dates.
  • yyyy is defined as the calendar year.

Whom this affects

The second part of Dan Wood’s question is what languages this affects.

NSDateFormatter* and CFDateFormatter both accept the Unicode date format syntax.

Contrary to what I’d previously assumed, PHP does not use Unicode date formats. As befits PHP, it uses something that looks the same but works subtly differently: “Y” is always the full calendar year, whereas “y” is a two-digit calendar year. ISO week years are “o”.

I actually don’t know of any others. Feel free to chime in in the comments if you know any other languages or frameworks that include built-in support for Unicode date formats.

* On the Mac, an NSDateFormatter configured for “10.0 behavior” accepts str[fp]time(3) formats; “10.4 behavior” is Unicode date formats. All other current Apple OSs, including iOS, have NSDateFormatters with 10.4 behavior only. CFDateFormatter has never supported str[fp]time(3) formats.

Inspired by my own apartment hunt last year.

In no particular order:

  • Cell reception
  • Hot water
  • Outlets: Are they grounded? Are they ALL grounded? Are they REALLY grounded?
  • Proximity to laundry (in-building? coin-op laundry nearby?)
  • How good said laundry is
  • How expensive said laundry is
  • Window directions (east-facing: warm mornings; west-facing: warm evenings)
  • Can windows be opened?
  • Can windows be blinded?
  • Trash/recycling/compost disposal: Where? How? Capacity/limits?
  • Noise
  • Access to cable TV/internet
  • Access to transit

Alternatives to “guys”


2015-06-19 05:30:36 UTC

When you’re addressing a mixed-gender or unknown-gender group, you should not use the word “guys”.

(Everything in this post also applies to “dudes” and “fellows”, and the singulars of all three. For example, “the IT guy”.)

The word refers to people who are male. It doesn’t matter what you meant by it in a particular instance, or how you as an individual tend to use it: That is what it means. That is what it conveys. That is what people hear when you say it.

As Julia Evans found, different usages vary in how they’re received, and there’s almost always a difference by gender. You’re more likely to think “guys” is gender-neutral if you’re a guy.

When you use it to address people of mixed or unknown gender, you reinforce the idea of male-as-default: This masculine word can refer to anybody! Funny how that doesn’t work for feminine words.

When you use it to address people of mixed or unknown gender, you erase the non-male people in the audience: Everybody here is guys! There’s nobody else here, no non-guys at all, no, sir.

So stop it. Stop saying “guys”.

(Except, of course, when you really do mean a group entirely of guys, like a men’s sport team.)

You may think it’s perfectly normal. It’s common, and that’s different. “Normal” implies healthy, and this isn’t healthy.

If you start paying attention, it won’t sound so “normal” after all, once you start noticing every time somebody refers to people who aren’t all guys as guys.

You might think “OK, I’ll say ‘guys and girls’ or ‘ladies and gentlemen’ instead.” Don’t do that. That does not include everybody: There are more than two genders, and not everybody inhabits any of them.

We can do better than that. We can include everybody.

So, what should you say instead?

These are words and phrases that include rather than exclude. That acknowledge rather than erase.

If you have other alternatives to suggest, please do suggest them in the comments.

My 3D printing setup


2015-01-10 12:03:29 UTC

Here’s what I have today:


Photo of my 3D printer (1), with a glass plate (2) and small piece of blue painter's tape (3) on the print bed, an SD card (4) in its slot, a USB fan (5) outside, a USB strip light (6) inside, and a cuticle nipper (7) outside.

  1. The 3D printer is a PowerSpec 3D Pro from Micro Center. I believe it’s a rebrand of the FlashForge Creator Pro. For $800 (that was on Black Friday sale; it’s normally a kilobuck), you get a decent printer with two extruders and a heated bed. It fared average in Make magazine’s 2014 comparison, and I agreed with their assessment on the whole.

    So far, I’ve only printed PLA, and I’m happy with that. I have no reason at present to switch to ABS.

  2. The glass plate is from a dollar store picture frame. I had a choice between 5×7″ (smaller than the build platform) and 8×10″ (larger); I went smaller, which worked out well. A simple 1 mm shim was all I needed to adjust the platform height to offset the thickness of the plate.

    The printer comes with Kapton tape applied to the print bed, and I have a roll of it from which I’ve replaced the tape once, but now that I’m printing on glass, I don’t think I’ll go back to Kapton. I may change my mind if I start printing ABS.

  3. This is blue painter’s tape, on a corner of the print bed. Overrated, in my experience, but its terribleness at PLA adhesion is what makes it great for this specific purpose: prints I export with Simplify3D (more on that below) start with a glob of plastic in this corner, and having that land on painter’s tape makes it easy to remove whenever I want.

  4. The SD card came with the printer. I’ve never connected the printer to my computer; I always run it autonomously, using the controls on the front.

  5. I turn on this USB fan (Walgreens seasonal item) after a print to cool off the print and print bed. Once they’ve cooled enough, the part stops sticking to the glass and I can just pick it up—no pulling or prying required. This is the major advantage of glass.

  6. Hanging down into the printer is a wonderful little USB gooseneck strip light. The printer has its own lighting, but it’s top down, so the area under the extruders is in shadow. Lighting from the side gives me a better view of the print action.

  7. The cuticle nipper is among the tools I use to refine finished prints. They’re great for clipping off tiny burrs on edges and corners. I also have a nail file (they come in four-packs at the dollar store, and I don’t need that many nail files for my hands) that I use for similar purposes, including cleaning up where the cuticle nipper left off. Filing/sanding is one area where I feel my toolset is incomplete.

Not shown:

  • Two rolls of PLA. On the spindles are one “clear” (more like translucent) and one white. The white currently isn’t even loaded into the printer; I could swap in another spool at any time.
  • Other rolls of PLA. I have more white, some “natural” that I suspect may be equivalent to the “clear”, at least one spool of black, and half a kg of red (I want to make a pommel for Ikea’s red wind-up flashlight, and I want the colors to match).
  • A roll of PVA. I haven’t used it yet, but its use in 3D printing is as a support material in PLA parts. You can use PVA to support bridges and overhangs, then dunk the part in water to dissolve the PLA away.
  • The remaining Kapton tape.
  • Two spatulas. One is just a normal metal spatula from Daiso. The other is an extra-wide “fish” spatula from Target’s summer section, bought on clearance after summer ended. I’ve only used that a couple of times, and I basically haven’t touched either since switching from Kapton to glass.
  • Long cross tweezers, for extracting the odd bit of scrap plastic from the printer while the part is printing, or from the hot end while it’s still hot.
  • 15 cm ruler, and a digital caliper from Harbor Freight
  • Duster, for sweeping dust and bits of plastic off the print bed.
  • The USB charger that the USB hub is plugged into. (The fan and strip light are both plugged into the hub.) The charger is the one that came with the fan.

Several of the things I’m making are meant to be stuck to a magnetic whiteboard, so I’ve got stuff for that:

  • Magnets, obviously. I have strong permanent magnets—strong enough that the protective packaging is more protecting everyone and everything outside the package than protecting the magnets. A millimeter of plastic and a layer of silicone is enough distance to water them down to fridge-magnet pull.
  • Super Glue, of the brush-on type.
  • Disposable gloves, for handling the glue (“WARNING: BONDS SKIN INSTANTLY”) safely.
  • GE “100% silicone”, for added grip. (I’ve had mixed success with this so far. I may need to lay it on thicker than I’ve been doing.)
  • Plastic putty knives for applying the silicone to the parts.
  • Metal putty knives for removing the silicone from the plastic putty knives.

Software I use

I use OpenSCAD to design models—programmers will love it—and Simplify3D to slice and export the model for the printer. (Simplify3D exports G-Code; for a printer like mine, you’ll need GPX to convert it to an x3g file.)

UPDATE 2016-09-09: The version of Simplify3D I have now successfully exports x3g files on its own.

OpenSCAD is different from most 3D modeling software: It’s text-based. You describe your model in code, mainly using shape primitives and set operations (intersection, difference, and union), and then hit render to see what it looks like. When you’re done iterating, you do a final (longer-running) render, then export STL.

Simplify3D is a $140 slicing and printer control program. It’s both the best one out currently and ugly in a lot of places (especially the installer, which is a Windows-style “setup wizard”). It offers you a lot of control, which is both a blessing and a curse—but it means I can do certain things that I want that MakerWare wouldn’t let me, like crank the printer’s base print speed up to 125 mm/s (the default is 90).

So I write a model in OpenSCAD, export it to STL, bring that STL file into Simplify3D, export G-Code, and use gpx to convert the G-Code to x3g. I then put that x3g file onto the SD card to put into the printer.

Software I’ve tried and abandoned, or not tried at all

I’ve tried Cheetah3D, 123D Design, and Inventor Fusion. I found them all limiting in various ways; I frequently run into “I know what I want but either don’t have a tool that does that or the tool doesn’t want to let me do that” situations. OpenSCAD is bare-bones, but expressive.

I have not tried the successor to Inventor Fusion (which requires an internet connection, which makes no fucking sense for 3D modeling software), nor have I tried Blender.

I originally used MakerWare, and it was OK, but I find it hard to give up some of S3D’s more advanced features, like the speed control. I did have to export one part from MakerWare because Simplify3D seemed not to notice a long, very thin cylinder that was part of the model—but that’s the only problem I’ve had with S3D so far.

I’ll likely go back to MakerWare, at least initially, when I do my first dual-material (PLA+PVA) print. Simplify3D’s UI does not give me lots of confidence that it will handle that correctly without my needing to explain it some things.

I have tried Slic3r. Here’s a picture of me using it:

I have no idea what I'm doing.

I haven’t tried the newer “MakerBot Desktop” (successor to MakerWare), nor ReplicatorG, nor any of the other, older slicers.

I really want someone to come out with the iWork of slicers. Or modelers, but I’m happy enough with OpenSCAD that I’m likely not to want to put in the time to learn another GUI modeler, unless it’s a graphical editor for OpenSCAD files. But a truly nice slicer, with Simplify3D’s capabilities but much more refined and easy-to-use UI, would be great.

The to-do graph


2014-12-21 15:35:00 UTC

Earlier this year, I started practicing GTD.

I’m not very good at it yet. But I’ve learned some things.

And I’ve proven that lists suck.

A list is a single, flat, ordered collection of items. In GTD, you’ll have one list per project, and each item is an action.

This makes sense if you consider the list to be a record of everything you did toward that project, in order, written before instead of after.

But who does that?

Who micromanages the order of things they’re going to do before they do it?

Who has such perfect foresight?

Who has that kind of time?

Moreover, the order of a list is implicitly transitive: Every item in the list must come after every item before it and before every item after it.

That isn’t true: Some things can be done at the same time, or in either order. For example, you can work on assets while you install Xcode, and then you can work on assets before code or code before assets.

A list is a serial queue. No work can proceed until the work before it is finished.

The alternative to that is to throw out the ordering altogether: Put items in in the order you think of/receive them, and then every time you want to start one, scan through the whole list until you find something that you haven’t done and can do.

It’s a choice between false information—order relationships that don’t really exist—and no information.

The latter seems worse: Some of the orders are true, and therefore valuable, so why throw them all out?

How can we avoid that?

What makes the true orders true? Why do those actions have to be done before those other actions?


This action must be done before that other action because the other action depends on it.

Some actions depend on other actions. Some actions depend on multiple other actions.

This is a graph.

That’s what I’ve switched to. I still use OmniFocus (version 1), but only as an inbox; I migrate those items to my to-do graph, which I keep in OmniGraffle.

Example graph of two projects, “Build new app” and “Work on existing app”, with actions such as “Create Xcode project”, “Fix bug in frobulator”, and “Add BSP reticulation”.
You can tell this is a made-up example because some of these actions are not concrete enough to be proper GTD.

The graph enables me to express dependencies without making up false orderings. Items that can be done in parallel are in parallel.

I mainly edit the outline, rather than the boxes on the graph directly. You could use something like OmniOutliner or TaskPaper, but those can’t visualize the graph. OmniGraffle has an “auto layout” (no relation to the Cocoa feature) option that automatically creates and arranges boxes in the graph corresponding to items in the outline.

The top-level items in the outline, the roots of the graph, are goals. I typically write these as high-level imperative sentences such as “build initial version of app”.

All, or occasionally nearly all, of the other nodes are indivisible actions. Each is a single concrete step toward the goal.

The leaf nodes are “next actions”: At any time, I should be able to pick a next action as the next thing I’m going to do.

I also create nodes for other people’s actions that I’m waiting on. These nodes look like “So-and-so: Do such-and-such”. When that happens, I take it off; its parent—if it has no other dependencies—then becomes a next action.

I set OmniGraffle to lay the graph out as an upward tree, so that each project actually does look tree-like, with the “root” at the bottom.

To mark an action as done, I have two choices: I can set the node’s font to strike-through, or just delete it. I typically strike through my own completed actions, and delete obviated actions, completed actions by others, and completed goals.

You’ve gathered by now that OmniGraffle lacks some things for this.

  • It wasn’t designed to be used as a to-do list, so it lacks a concept of “done”. Instead of a checkbox, I have the Font Panel.
  • Similarly, there are no priority or due-date options. I generally don’t use these, but some projects do, in fact, have a due date, or greater or lesser priority than other projects, and it’d be helpful to track that.
  • The outline editor, which superficially looks like a mini OmniOutliner, lacks or changes about half of OmniOutliner’s keyboard commands. I really wish that if the keyboard focus is on the outline, that it would just respond exactly as OmniOutliner would to every possible keypress.
  • The option to have a node pinned to the far (top) row of the tree is a per-node option, so I can’t have it automatically lay out all next actions in the same row.
  • The outline structure, like OmniOutliner’s, means I cannot have multiple nodes depend on the same action—which they very well could in reality.

I have two points:

  • A graph is a much better way to express to-dos than a flat list.
  • There currently isn’t a Mac app ideally suited to this. OmniGraffle is a great graph editor, but I’m using it for a purpose it wasn’t designed for. I’d pay good money for an app of OmniGraffle’s quality and basic nature, but optimized for to-do keeping.

G4 Cube mods


2014-11-02 20:17:43 UTC

As some of you are aware, I own a Power Mac G4 Cube.

The G4 Cube was an impressive little machine from 2001. It was a Power Mac G4, minus any PCI slots, packed into an 8-inch by 8-inch by 8-inch (plus a few inches’ clearance underneath) cube. And it had no fan—it was cooled entirely by convection through the mostly-empty center column.

It’s also really fun to upgrade.

I’ve upgraded my Cube in three ways:


One of the old stand-bys, along with upgrading the processor and video card (both of which remain stock in my Cube).

RAM for a Cube is dirt cheap now, so I bought 1 GB. The theoretical maximum is 1.5 GB, but I’m only running Mac OS 9 on my Cube (all my personal OS X usage happens on my MacBook Air), so 1 GB should already be overkill.


The Cube, of course, came with a spinning-disk drive (a.k.a. “hard disk drive” or HDD), connected via ATA.

Replacing an HDD with an SSD is straightforward in most newer computers, but the Cube presents special challenges.

For one thing, it’s a desktop computer with a 3.5-inch drive bay, and SSDs are typically 2.5-inch (the “laptop” form factor). This would not be a problem if it were the only one, because adapter brackets exist, but it’s not the only problem.

Problem #2 is that the Cube uses ATA (now known as “parallel ATA” or PATA), whereas SSDs use serial ATA (a.k.a. SATA). Again, adapters exist, but that brings us to problem #3:


Not disk space, but physical space.

As I mentioned, the Cube is a lot of electronics packed into a small volume. The drive bay does not have free space on any side of it; it is exactly as big as needed to fit a 3.5-inch ATA hard disk drive.

This makes it difficult to impossible to fit a 2.5-inch drive, a PATA-to-SATA adapter, and an adapter bracket.

OWC sells SSDs with integrated adapters for pretty much exactly this purpose, but I cheaped out and went the DIY route.

  • I bought an 80 GB SSD off Woot.
  • I bought an adapter board at Fry’s. I think it was this one, but it was months ago and I’m not about to open up my Cube again to find out.
  • I bought an adapter bracket, I think from Amazon, but didn’t end up using it because of the aforementioned space constraints.

With a HDD, leaving everything flopping around inside the computer would be just asking for a problem, because the HDD has a motor, which will cause it and everything connected to it to vibrate. Sooner or later, the HDD could come unplugged (especially if it’s a 2.5-inch HDD), and then you just have bits pouring out all over whatever the Cube is sitting on.

But this isn’t an HDD; it’s an SSD. A Solid-State Drive.

It has no moving parts.

That’s what’s cool about having an SSD in a Cube:

No moving parts at all.

The Cube has no fan. The video card has no fan. The SSD has no motor. Thus, the entire set-up is completely silent.

The one downside is that since this drive is so large (by 2001 standards), the Mac takes awhile to validate that it is actually properly formatted. It actually shows the blinking question mark for a minute or two before it finally boots.


The stock video card in my Cube is a Rage 128 with ADC and VGA outputs.

I used to use my Cube on a contemporary Apple Studio Display that I could plug into the ADC port, but I don’t want to set up a second monitor specifically for that computer.

For sound, the Cube didn’t have a built-in speaker (no space) or audio jacks (presumably no space even for that). Instead, it came with a custom Apple speaker set-up consisting of a central DAC box with hard-wired USB and speaker connections on one side and a headphone jack on the other.

Mine’s in somewhat shabby shape, and I don’t want to use it anyway.

I have a Yamaha AV receiver, Monoprice 5.1 speakers, and an Optoma 1080p projector. The receiver and the projector both support HDMI. What I really want is to be able to route the Cube’s audio and video together into one of the receiver’s HDMI ports, so that the Cube can be alongside my PS3, my iPad, and my MacBook Air as possible external sources to be presented through the receiver’s speakers and the projector.

And that’s what I have.

This adapter takes video input over VGA and audio input over USB, and outputs HDMI.

It’s an HDMI port for the G4 Cube.

Yes, the ideal solution would use digital video from the ADC port, but nobody’s going to make such an adapter for ADC today. A DVI one could exist, but would probably be way more expensive, and require also purchasing an ADC-to-DVI adapter cable.

The VGA output looks fine. The Cube can output up to 1600×1200, and it looks great on my wall.

The only real drawback is that Mac OS 9 (or maybe the video card) never heard of 1920×1080, so I can’t actually output the native resolution of my projector.

My wonderful Cube

My G4 Cube has 1 GB of RAM, an SSD with more free space than I know what to do with, and an HDMI port, to which I’ve connected a 1080p projector and 5.1 speakers.

And it’s completely silent. (Although admittedly the projector ruins that.)

It’s a cool little machine.



2014-10-25 09:50:47 UTC

The blog’s back up. It’s been down most of the year, as rather a lot of you noticed.

Thank you, everyone who told me. Every time you told me my blog was down, you were also telling me that you missed it, or at least you needed it for something. You’re part of why I kept meaning to bring it back, and why I eventually did.

I work for Apple now.

I’m on the Foundation and Core Foundation team, which is part of Cocoa. Part of my job is reading the Radars you file about those two frameworks and making sure they go to the right people.

I live in San Francisco now.

I moved early in the year, not long after I had to change hosting providers after TextDrive breathed its last (that was why the blog went down in the first place) and shortly before I started at my job.

I moved for the job; I work in Infinite Loop.

(I also moved because I love San Francisco. I’ve been here a couple of times before, and fell in love with it when I first stepped out of Civic Center BART onto Market Street.)

I probably won’t write as much here anymore.

A big part of that is time constraints: Subtract the job, the commute, three square meals, and sleep, and I don’t have a lot of time in a day to pound out a blog post.

Then, of course, there’s the nature of the job: Being at Apple means I know some things that aren’t public. Not a lot, but enough. Better to be careful than accidentally say something here that I’m not supposed to.

The same goes for my being active on Stack Overflow.

You’re welcome to ask a question and send me the link, but somebody else will probably get to it before I will.

And, of course, MacTech. See above. (If you have a subscription, you might have noticed this already—my last article ran in August, I think.)

I won’t be at MacTech Conference this year, either. This is the first time in the conference’s history that I won’t be at it. But plenty of other fine folks will who are worth listening to and who are good company.

That’s all I have to say for now. For those of you who use Twitter, I’m still there.

Until next time.

Simple starter Cocoa app ideas


2013-12-11 13:46:20 UTC

Inspired partly by tonight’s Hour of Code, here are some index-card-sized outlines of some simple app projects you can make as someone new to Cocoa.

Text editor/word processor

  • Document-based Mac app
  • In document window: NSTextView
  • Use NSAttributedString to read/write document data
  • Document types:
    • public.plain-text
    • public.rtf
  • Extra credit:
    • Add a ruler (NSRulerView)

Picture viewer

  • Document-based Mac app
  • In document window: IKImageView
  • Use CGImageSource to read image (picture) & its properties
  • Document types:
    • public.png
    • public.jpeg
  • Extra credit:
    • Floating inspector panel showing the properties in an NSTableView
    • Color-correction panel (IKImageEditPanel)
    • Support folders (public.folder): display images from folder in IKImageBrowserView

PDF viewer

  • Document-based Mac app
  • In document window: PDFView
  • Use PDFDocument to read from .pdf file
  • Document types:
    • com.adobe.pdf
  • Extra credit:
    • Toolbar with zoom in/out buttons, zoom % field, page number field