03 December 2018

03 September 2018


Harriet Alexander learns a lesson about software instruction on site in Antarctica:
The second day was Python, which we typically teach by introducing some packages using the Conda packaging system. Anaconda is about 300 megabytes. That doesn’t sound like much — but when you’re in Antarctica, where the Internet is very slow, it’s huge. I ended up downloading Miniconda, a stripped-down version of 35 megabytes, and it took me probably 2.5 days. But I forgot that Miniconda has to download other stuff, so there was no way it was going to work.

Bottom line: if you’re going to be teaching somewhere remote, download what you need before you get there.

19 August 2018

Forget it, Jake

I've been posting links and interesting bits of code here for more than ten years, and I've never mentioned MUMPS? Well, Remy Porter can help me rectify that oversight.
...the developer replied with a one line code fix:
 i $$zRunAsBkgUser(desc_$H,"runReportBkg^KHUTILLOCMAP",$na(%ZeData)) d
 . w !,"Search has been started in the background."
 e  w !,"Search failed to start in the background."
Alex tested it, and… it didn’t work.

07 July 2018

Your (bullet) journal should not look perfect

I find myself bemused by the phenomenon of bullet journals. There are some aspects to this approach to planning that I can get behind—use the system as a motivator, express your creativity, just jump in and do it— but nevertheless, bullet journaling seems to me to be more about making the journal, and making it pretty, than it is about getting things done.

I've been using a pre-printed planner for years (I got hooked when a former employer provided them as regular office supplies), and I've learned a few things.

18 September 2017

A good journal/planner should look a little messy, maybe a lot.

Nearly printed boxes for days and hours shorten the time to set up my planner for the coming month (it takes me about five minutes), but I still need to do some customizing. Specifically, I need more space for to-dos on the weekends than Day-Timers provides. And tasks will spill out of the neat little boxes, as new information trickles in and new obligations come up.

And that's a good thing. If your week is too tidy, with everything cleanly ticked off, you're not planning to accomplish enough. Whereas in my case, there's almost always too much to do in a week. The wall of to-dos on Saturday is telling me that I'm overcommitted and need to start saying no to things.

Heck, I started making the notes for this blog post last September, and am just now getting something down in digital ink.

Do not hold up looking for the perfect writing instrument to update your planner. Pick up whatever you have on the desk on in your pocket and scribble away. Now, I have started experimenting with color and highlighters to flag important tasks that I've been procrastinating about. But there's no system to my colors—I just grab the first highlighter on my desk that hasn't dried out. (I came by a box of half-used office supplies that I've been using up, but that's a story for a different day.) And if you've got a big, gnarly project that you've just finished, one that's been hanging over your head for a while, go grab a Sharpie and give yourself a plus-size checkmark.

I use my paper planner for the tactical job of getting through the day, getting through the week.

October 2017

And I have a paper two-page calendar for the month that likewise tells me whether I've got too much planned for the month—or whether I'm going to have a schedule conflict. Sometimes I'll tape a souvenir to the month calendar. Sticky notes help manage a tentative date that I might need to reschedule.

For longer term planning, I made the transition to digital tools some time ago. Transitions plural: I'm now dependent on Trello, with some help from Toodledo for keeping track of recurring tasks.

Actually, when you read to the end of many of the posts about bullet journals, the pragmatic advice comes through: Do what works for you; don't overthink it; all you need is a notebook and a pen to get started.

24 June 2018


The Antikythera Mechanism finds its way into the newest iPhone.


A new journal has been launched, to serve as a repository of open source research software, as the Journal of Open Source Software (JOSS). Daniel S. Katz et al. have the details.

24 April 2018

Links roundup: 6

12 April 2018

A Portable Cosmos

Solving the puzzles posed by a broken, corroded mechanical gizmo found by sponge divers in the waters off a small Greek island might seem, at first thought, unrelated to the problems of debugging a software service or improving the user experience of a new mobile app. But, as Alexander Jones in A Portable Cosmos (Oxford University Press, 2017) recounts the researches into what is now called the Antikythera Mechanism, discovered in 1900 as part of the cargo of a shipwreck, some surprising parallels with current software development practices come into view.

Ever since the bronze fragments of the Mechanism were brought to the surface, archeologists and other technologists have trained increasingly sophisticated tools on it, from detailed drawings, to progressively more detailed photographs, to (from 1988) radiological focal plane tomography (to look inside it, non-destructively), to reflectance transformation imaging (a super-contrast way of reading the inscriptions on the front and back of the device). This is reverse engineering on a millennial scale.

Our current understanding is that the Antikythera Mechanism was made in the first century BCE. About the size of a shoebox standing on end, it housed an intricate assemblage of gears, driven by a hand crank on the side of its enclosure. On what we call the front, a miniature solar system of Moon, Sun, Mercury, Venus, Mars, Jupiter, and Saturn revolved within two bezels marked with the constellations of the Zodiac and the months of the Egyptian calendar. On the back, pointers moving across two spiral dials (and three smaller dials) displayed celestial events in 19- and 76-year cycles. Bronze plates covering the front and back explained its operation and provided additional astronomical information.

So what does sussing out this—let me write it—analog dingus have to do with current technology practice? A few points:

Switching contexts to gain understanding: Or what I might call inference feedback loops. One of the back dials (one of the few that were completely preserved) is inscribed with the names of various athletic events that recur in four-year cycles, from the best-known Olympics to the rather obscure Naa and Halieia games. The Halieia festival took place in Rhodes; Rhodes was the home of the highly influential astronomer Hipparchus; and writings by Cicero refer to a celestial machine made there. Hence, it is likely that the Antikythera Mechanism was built in Rhodes (p. 94). Elsewhere, Jones accumulates information that points to the intended destination of the device: Epirus, in the far west of the Greek peninsula. Thus, we can connect the dots that a wrecked cargo ship traveling between these two points would be found someone between them—off the island of Aigila (also called Antikythera).

Similarly, Jones examines the orientation of the back dials and their pointers (p. 159). An arrangement that puts the pointers at the top pointing straight down and the pointers at the bottom parallel to one another corresponds to a zero point, or calendrical epoch, of 25 August 205 BCE. This date is not too far in the past for a device built in about 60 BCE.

The arithmetic of the gears: Some of the gears are sufficiently intact that we can count the number of teeth; others are just stuck together with 2000 years of gunk. But we can infer the missing gear trains. Since we know the patterns and cycles that each dial pointer would have had to trace, we can calculate the gear ratios necessary to produce the required movement. For instance, to account for a Moon pointer:

The pointer has to revolve 254 times clockwise around the dial in the same time as [main gear] b1 rotates 19 times; hence the desired ratio of periods is 19:254. A gear with 254 teeth would probably have been considered undesirably large... The prime factors of 254 are 2 and 127, so a gear with 127 teeth was unavoidable as the driving gear in an engaged pair. A gear with 19 or a small multiple of 19 will be necessary as a driven gear; since 19 is an uncomfortably small number of teeth for a gear, we can tentatively chose 38 as the smallest viable multiple. If we just had a gear pair with tooth counts 38 and 127, the resulting ratio would be four times what we want, so additional gears must be provided that collectively amount to a ratio of 1:4. (pp. 210-211)

Designed vs. actual use: For twelve decades, various purposes have been proposed for the whatsit. Early researchers reasoned that, since it was on a ship, it was an astrolabe or other navigational device. Later, as more details became available, it became clear that the machine could be used to predict eclipses and compute horoscopes. Jones argues, however, that while the mechanism could do these things, it was much better suited as a portable planetarium—a teaching device. And indeed, a student watching the planets in motion, with their anomalies and retrogrades, would have been much more engaged than the same student studying two-dimensional static diagrams—like the (very well done) diagrams in Jones's book. In today's world, consider the three-dimensional ball-and-stick model of biological molecules like DNA as compared to the same information rendered on paper.

Design for small spaces: The Saros dial on the back is divided into 233 cells. When a pointer points to particular cell, then the positions of Earth, Sun, and Moon are such that a lunar and/or eclipse is likely, and at a certain time. The Mechanism represents these facts with a combination of one-letter initials and two-letter ligatures: 8 characters to compactly represent, say, "Eclipse of the Moon, during hour 5 of the day; Eclipse of the Sun, during hour 12 of the day." An additional letter in the cell indexes to inscriptions on the back face of the machine, describing periodic starry events in greater detail. The index letter is a callout, in other words. (p. 152)

The Antikythera Mechanism is an altogether fascinating contraption, one that still keeps a few secrets to be revealed.

11 April 2018


Gregory Vial surveys the current landscape of database management systems: RDBMS, key-value stores, and systems in between -- for transaction processing and/or analytics. The emphasis is what I might call narrow-attribute storage, as opposed to free text-oriented systems like Elasticsearch.

09 April 2018

Very content

It's been a very slow, soft launch for us on the team building the Content Service, but now we can say that we have a production application powered by our service. The NPR App launched at the beginning of the month on iOS devices. The NPR App is more of a reading experience (either to skim the headlines or to go deep into a story), while the companion NPR One continues as a listening-oriented experience.

More apps and clients to come!

29 January 2018

Fun with Slim

I'm working on a smallish project to build service endpoints using Slim. (We've used other frameworks in the past. I recently converted my model code to a PSR-4 autoloader. The team strongly suggested Slim for this project.)

The Slim documentation makes it abundantly clear that Response objects are immutable: each method that accepts a Response as an argument returns a copy of that object. You can also puzzle out that methods like withHeader() and withStatus() can be chained together. And the docs explain how to use withJson() if you want your endpoint's payload to be JSON and you're content with the default MIME type.

What is not so well explained: that getBody()->write() does not return a Response, so it can't be chained. Nor is it clear how to use these methods when you want to set your own MIME type ("application/hal+json", in my case) or status code. Hence, this example, somewhat simplified.

The GET /short endpoint returns a brief HAL representation of the resource identified by :id.

namespace Demo;

class Controller {
     * GET /short/:id
     * @param \Slim\Http\Request $request
     * @param \Slim\Http\Response $response
     * @param string[] $args
     * @return \Slim\Http\Response
    public function short($request, $response, $args) {
        $id = $args['id'];
        try {
            $guid = ...;  //look up info about $id
            if (empty($guid)) {
                Logger::warning("No info for $id");
                return $response->withStatus(404);
            $doc = ...; // construct a model, using $guid
            $rsp = $response->withAddedHeader('Content-type', 'application/hal+json');
            return $rsp;
        catch (Exception $e) {
            Logger::warning($e->getMessage()." Failed");
            return $response->withStatus(500);

And how do you write a unit test for this endpoint? Likewise, the docs give some strong hints, but leave you to connect the dots. The trick is to use Environment::mock() to get an object that can be passed to a factory method on Request. A simplified version of my happy-path unit test:

class ControllerShortTests extends \PHPUnit_Framework_TestCase
    /** @var \Slim\Http\Request */
    private $request;
    /** @var \Slim\Http\Response */
    private $response;
    /** @var string[] */
    private $args;
    /** @var \Slim\Container */
    private $container;
    /** @var \Demo\Controller */
    private $controller;

    public function setUp()
        $this->request = \Slim\Http\Request::createFromEnvironment(\Slim\Environment::mock());
        $this->response = new \Slim\Http\Response();
        $this->args = [];
        $this->container = new \Slim\Container();
        ... // set up a mock datastore provider
        $this->controller = new \Demo\Controller($this->container);

    public function testExpectSuccess()
        ... // configure the provider
        $this->args['id'] = 987654321;
        $response = $this->controller->short($this->request, $this->response, $this->args);
        $this->assertEquals(200, $response->getStatusCode(), 'Wrong status');
        ... // and more assertions

14 January 2018

Gaming the benchmarks

What's holding us back from exascale computing? According to Katherine Bourzac's report, the simple answer is power.