21 Feb 2018 c.e.
Moon Clock, An Update

Wherein we announce the launch of moon.supply

I've been working slowly, but steadily on getting the Moon Clock project ready for Kickstarter primetime. It still feels a long way off, but we're getting there.

Since I last wrote in early January, I've built a two more moon clocks and ordered the parts for another few, found an informal circuitry advisor (hi Yuanyu), realized I know a lot more about hardware hacking than I thought, ordered (and am extremely excited about receiving) my first benchtop power supply[0], bought the wrong parts[1] on Digikey, found a friend with a 3D printer and some CAD exp (thanks Eric), talked my partner (<3) into dusting off his electronics 101 skills, found a designer for the KickStarter (hi Paul), and made some LEDs blink.

Oh, and I've ported the moon clock code over from some Golang/Python hybrid to pure Go and put an API where you can get the current moon image for any lat/lon[2].

Ya'll, I'm making a thing!

Here's some notes and impressions on the work I've been doing.

Wherein you realize you're almost but not quite in over your head

I could build a bunch of Moon Clocks using the same hardware I used for the prototypes, but there's a lot of problems with the current set up. First off, the parts for a Moon Clock, just off the shelf, are really expensive. The full version of a Raspberry Pi costs $30, plus the Adafruit HAT piece I'm using to wire the LED to the Pi is another $20. That's $50 right there just for the brains of it.

Secondly, the chips don't really fit in the frames I'm using. I might be able to find something a bit deeper, but designing my own board will let me get something that fits nicely into the existing frame. Further, the boards require a decent amount of soldering and setup. Having a customized chip with all the parts already soldered on will make assembly a lot faster.

On the face of it, designing a PCB from scratch is pretty daunting but, I'll let you in on a little secret. All that a PCB does is connect the differrent parts together. Most of which pins connect to what is specified by the datasheets (or open source library you're using to drive the display). You literally just connect the pluses to the pluses and the grounds to ground. Ok, maybe it's not that simple for every circuit, but the Moon Clock wiring really isn't that complicated! Winning!

The most electronics I've done is getting some Raspberry Pis to work, and hacking together a pretty complicated light switch a few years back.[3]

Suffice it to say, I know just enough about how circuits work to be extremely dangerous.

First steps towards a PCB

The first step toward making your own circuit is to figure out what you need. I'm at this stage right now, more or less.

Figuring out what you need is a lot harder than it sounds.

For starters, I know I needed a 'microcontroller' of some sort, the word 'microcontroller' being about the extent of what I knew about them. Luckily, The Prepared had sent out this really wonderful guide to sub-$1 microcontrollers. I passed the article to a friend of mine, who in return sent me back the page for the STM 32.

There's a lot of options for microcontrollers, mostly because there's a lot of different things that you can use a microcontroller for. Solar panel rigs, car interiors, low-power sensors, networked devices, outdoor LED panel displays, etc. Different applications need different things in a chip, hence a plethora of options.

I ended up buying a couple of devboards to try out; here's the criteria I used to help me figure out what to get:

  • Clock speed. Adafruit claims you need 16Mhz+ to run the LED panel without too much flickering. The slowest chip I got runs at 48Mhz (the F0 series), the fastest is up to 72Mhz (F3). Raspberry Pi's, for comparison, run at about 1Ghz.
  • RAM. This is how much you can hold in memory at once. For the LED display, we theoretically need to be able to hold a 32 x 32 x 8 x 3 byte image, which is about 24K. That's not counting the program that's running. I accidentally got one dev board that only has 20k of RAM; the beefiest board I've got has 128k (?).
  • Flash Memory. This is where the program we write will get stored. I'm not too worried about how big this needs to be but bigger is probably better.

There were a few things that I have come to realize might be important, but at the moment don't have any real way of evaluating boards for this:

  • Floating point hardware. The Moon Clock calculations do a lot of floating point math. Supposedly some chips have addons that make this a lot faster. Luckily, the clock face doesn't update that often, so we'll probably be fine.
  • Energy efficiency. Good thing the clock plugs into an outlet.
  • Number and type of pinouts. There's still a few circuitry parts to figure out[4] but I'm pretty lucky that the LED panel I'm driving doesn't have any complicated connector requirements. The STM32 dev boards I ordered ended up having Arduino compatible pin configuartions, which made finding documentation on them pretty straightforward.
  • Dev environments. The nice thing about the STM boards is how straightforward the dev environment is. There's a graphical image of the board! With pinouts that you can configure with a GUI! It generates C code for you! The STM family is known for having a good dev environment though, so I definitely lucked out.

So far, we've wired up one dev board and gotten it to flash an LED. Which feels like a huge success! There's still a lot of work to go in terms of wiring up the LED matrix, but it feels within reach!

After the LED driving bits are sorted out, I'll probably need to port the Moon calculating code over to C. That, or figure out if Go will run on a tiny chip. I'm stoked.

Putting up an API

On the software front, I thought it'd be fun to put up an API to let other people use the Moon engine I wrote to get Moon pictures. It's super simple because I was too lazy to add more functionality, but if you give it your latitude and longitude, it'll give you back a base64 encoded 320x320 image of the moon right now at that location.

You can try it for yourself with curl, or by hitting this endpoint in a browser:

curl "https://api.moon.supply/img?lat=37.7272&lon=-77.2918"

I got really lucky because AWS just launched Golang support in Lambda back in January. There's a lot of hacky projects that will let you run Go with a nodejs or python wrapper; but luckily I didn't have to deal with any of that. The moon engine is a really great example of a good use case for Lambdas -- the calculation engine is completely contained and you really only need it when you call it!

I couldn't find an example of how to send back the 'raw' png bytes using the AWS API Gateway event object so I encoded it to base64 to send back. If you know how to make it return an image, I'd be very curious to hear how to do it!

Getting the Moon engine Lambda ready meant re-writing the drawing code from a Python PIL library to using Go's image library. It was a bit easier to do, but required pulling out some trigonometry to get the circle distances correct.

To draw a circle in PIL, the API requires you to provide a bounding box for the circle and an angle which to fill in. Here's an example that returns a semi-circle.

img = Image.new('RGB', (320,320), 'black')  
draw =  ImageDraw.Draw(img)  
draw.pieslice((start,start,diameter+start,diameter+start),-180,0, 'white')

The Go image library is a lot lower level. The example that I based my draw-er off of instead requires that you return the color value for a given pixel coordinate. Basically, writing a function that returns either black or white for a given pixel. It ended up being easier to write than the PIL code, once I figured out how the trig worked.

Here's an example 'draw' function that will get you a white circle; it returns 0 (black) if the pixel point is outside the circle, and 255 (white) if it's inside.

func (c *Circle) Brightness(x, y float64) uint8 {  
    var dx, dy float64 = c.X - x, c.Y - y  
    d := math.Sqrt(dx*dx + dy*dy) / c.R  
    if d > 1 {  
        return 0  
    return 255  

Unfortunately, as soon as I put the website (moon.supply) up, I realized how nice it would be to have the API return an SVG formatted moon instead of image pixels, so that I could use it on the site without there being any rastering. I'll add it to the 'to-do' list.

Wrapping Up & Kickstarter Dates

So, things are slowly marching toward a Kickstarter! There's still a lot of work to do, but I'm pretty happy with where we're at right now. I'll keep you posted, but for now look for a launch sometime in mid- to late March! We'll have a few early bird specials, like original Moon Clock prototypes and a bit of a discount for our first handful of backers!

In the meantime, give the Moon API a try and let me know what you think! Or just visit the moon.supply site to see what the moon looks like for where you are now.

[0] A benchtop power supply lets you try out a bunch of different voltages and currents. If you're working with electronic components and aren't sure what the power requirements are yet, a power supply will let you easily fiddle around with different settings. I got this one from Amazon.

[1] https://twitter.com/niftynei/status/961469328297148416

[2] I think the images for the moon at the poles is broken. Sorry.

[3] I built a wireless circuit and Android app to control a power outlet a few years back (which I then wired up to a string of lights). I wrote it up in story form; I wish I had done more of a technical write up -- I learned a lot about wireless routers (specifically XBees) and pinouts with it. God I had no idea what I was doing.

[4] It'd be nice to have a dial to set the latitude and longitude with.

#moon-clock #api #aws #lambda
2 Jan 2018 c.e.
Introducing the Moon Clock, The World's First Wall-Mounted Lunar Timepiece

The Moon Clock Project


I spent the last half of 2017 working on a project that I'm calling a Moon Clock, a physical lunar timepiece that displays what the moon looks like for your current location. Apparently the moon is a trendy thing these days.[0]

I got the idea when decorating a new bedroom; the walls needed something that went with my celestial themed room and I already had a 'normal' clock. Why not make a lunar clock?

Making a Moon Clock

The moon clock is a simple, backlit screen print of the moon, illuminated to show what the moon looks like at your location. It's mounted in a frame and when hung looks like a backlit moon portrait.

I went through a few ideas of using mechanical moving screens to get the moon shadow, but ultimately settled on using an LED display that lights up a printed moon screen.

The prototype I've built uses an LED matrix, a RaspberryPi and the corresponding Adafruit HAT (for driving the LED). You can see how to set up an LED project for yourself via this Adafruit tutorial. Note that the underlying Gihub project that Adafruit uses as a driver is super out of date; the updated version of the original project now includes instructions for how to use it with the Adafruit HAT. I recommend using the updated driver version.

The moon clocks is simply this Adafruit LED project mounted in a shadowbox, with a screen mounted at the front.

Lunar Tracking

Getting the LED set up was fairly trivial; however the astronomical algorithms required to calculate the moon phase given a latitude, longitude and time turned out to be non-trivial. The book Astronomical Algorithms by astronomer Jean Meeus is generally considered to be the gold standard in computational astronomy, but as a layman I found the astronomical jargon to be largely unintelligible.

I spent a good amount of time figuring out exactly what the information was called, and more time yet figuring out how to use the collection of algorithms presented in Meeus' book to compute the values I was looking for.

The problem lay mostly in that the exact information I need (percent illimination and position angle of the bright limb, or in other words, rotation of the moon) is derived from the combination of about 15 or so different computations. Figuring out which equations proved difficult without a solid understanding of astronomical geometry. For this, I found W.M. Smart's Textbook on Spherical Astronomy to be a literal project saver.

Briefly, the phase and angle of rotation of the moon is derived from the position and distance of the sun and moon, in relation to your current position on the Earth. The percent of the moon that is illuminated is a direct result of the angle between these three bodies.[1]

There's a few other things involved with calculating a heavenly body's exact current position: the difference between the "mean" sun time and actual sun time, taking into account the elliptical shape of planet Earth, and adjusting the coordinates from geocentric to your location on the Earth's surface. I'm doing a real disservice by not fully explaining how it works, but it feels outside the scope of this blog post. I'll have to do a follow up post on the basics of spherical astronomy.

Luckily, Meeus' book provides algorithms for all of these things. Meeus doesn't give good test data for the calculation I was doing, so I used CalSky's excellent Moon calculator to verify that my implementation was returning accurate values. You can use it yourself to see what the moon looks like at your location, on your computer screen.


Adafruit's LED samples included an example using Python's Image Library, or PIL. PIL allows you to compose image arrays, which the LED library would then render to the screen. PIL's API allows you to compose your own image; with a few more equations you can get an image of the moon with just two overlapping circle arcs.

I ran into two problems getting the moon rendered correctly.

First, Meeu's algorithms return the percentage of the moon currently illuminated. In order to draw this, I'd need to translate that percentage into a circle arc that could be drawn with PIL. Drawing a moon at 50% illuminated is quite straightforward: you just need a semi-circle. Any illumination above or below this requires knowing the arc and radius of the intersecting circle that draws the shadow across the moon's face.

Using the percent illuminated returned by our astronomy calculations and the radius of the moon (with a 32x32 square, your radius is 16), we can find the area of the illuminated portion with some math[2]. This ended up being less than straightforward to solve for directly, so we approximate within a few decimal places. Since this is a non-trivial computation and since the values are static, I ended up generating a lookup table for these values.

It turns out that rendering arcs at 32x32 pixels is incredibly grainy, or aliased. The resolution was so bad that the moon animation wasn't smooth -- instead of waning steadily the moon clock would appear to jumpily get bigger and smaller. However, reference images I was generating at higher resolutions transitioned smoothly. Since the LED matrix supports a wide gamut of colors, a friend suggested resizing the correct, larger images down to the LED matrix size using a bilinear filter, which smooths out the curves using color interpolation. SciPy provides this functionality for images; the resulting output is what you see on the Moon Clock today.

That about sums up the 'science' behind the Moon Clock, the last bit involved mounting the whole contraption into an Ikea Ribba frame.

LED matrix backing

Nota Bene

There are a few things the Moon Clock doesn't account for:

  • Elevation. Meeus' algorithms ask you to consider the elevation of an observer when calculating the parallax between your position on the Earth's crust and the center of the Earth (where almost all the planet location equations assume you are). In my tests, the difference between sea level and the top of Mount Everest (8,850m) had a negligible impact on the moon's appearance, at least in terms of percent illuminated and rotation; instead it's been pegged to a reference elevation of a few meters above sea level.
  • Whether the Moon is above or below the horizon. The Moon Clock shows what the moon looks like from your position on Earth, more or less assuming a transparent Earth. When the moon is below the horizon, the illumination shown will be accurate; the rotation however is an estimate.
  • Moon libations. Briefly, 'libations' refers to the oscillations the moon experiences as it rotates around the Earth. This oscillation slightly changes what part of the Moon face is illuminated and visible. Since the Moon Clock's moon image is screen printed, it doesn't accurately reflect the markings you'll see on the actual moon. You can read more on moon libations on Wikipedia

Upcoming work:

  • I'd love to get the Moon Clock to be battery powered, but I'm not sure this is possible with the current LED matrix set up I have.
  • I still need to update the matrix driver to the newer mainline version
  • I'd love to figure out how to run the Moon Clock on simpler PCB; the Raspberry Pi feels overfeatured for what I'm using it for.

So what's having a Moon Clock like?

In all honestly, I'm still discovering what it's like to have this background consciousness of the moon. I'm constantly being surprised at how the Moon has (or hasn't!) changed since I last looked. The phases seem to come and go a lot faster than I anticipated. And it's always changing! I'm traveling right now, and I feel a bit disconnected, not knowing what the Moon looks like today. It's weird not knowing.

What's next

I'm planning to Kickstart the Moon Clock some time in 2018. I'll let you know when that happens. Until then, I'm keeping the source code under wraps; I anticipate making it public will be part of the project launch.


This project has a many debts. I owe a big thank you to Karthik Raveendran for his endless support and deep graphics knowledge; Bryan Newbold and Sarah Gonzalez for lending their expertise and time to this project, especially at the early stages. For their true dedication to 'non-invasive living technology', the Moon Clock project is philosophically indebted to Jake Levine, Zoe Salditch and the rest of the Electric Objects team.

Moon Glamour Shot

[0] Charlie Deets just launched a moon app!

[1] Every computer's ability to provide you with UTC time came in handy for astronomical calculations. Before computers, figuring out the real time of your location involved taking the wall clock time, translating that to UTC time, and then recalculating the "actual" sun time for your specific longitude. The reason for this is that wall clock time isn't the actual time at your location -- it's set to a reference longitude which may be off by a few minutes. For our purposes, using your 'timezone time' rather than your actual time probably wouldn't make a noticeable difference, since the resolution of the moon available on a 32x32 LED matrix is fairly low, but for accuracy's sake, using the 'actual' time is preferable.

[2] See Circular Segment. In our case, we know the area and need to solve for the radius R and angle theta.

#moon-clock #projects #lunar-timepiece #astronomy
26 Nov 2017 c.e.
Finding O

I've written before about how I struggle with algorithm problems. I'm finally, eight months after diagnosing the problem, sitting down to figure out what it is about algorithms that I find difficult.

I'm doing two things differently. The first is that I'm using a textbook, specifically Skiena's Algorithm Design Manual. The second is that I'm doing them without time pressure. By comparison, the last time that I sat down to Learn Algorithms, around 5 years ago, it was during my time at the Recurse Center (nee Hacker School). I took an online class from Stanford taught by Tim Roughgarden; assignments were due weekly and the learning material was presented via video lectures.

I'm still going with them with a friend; for the Roughgarden course I found a study buddy among my batchmates. Now, I'm pairing with my sister on them.

I think the biggest thing that's changed is my perspective on programming. The first time around I was in awe of algorithms. They were this thing that separated the Real Programmers from the rest of us that merely toyed around at programming.

This time, I'm less intimidated by the concept, and far more awed by the awesome power of an O(lg n) equation.

I've realized a few things in the few short weeks since I started going thrugh Skiena's very well written book. The first is that, as always, the presentation style matters. Skiena's book is far and away the best work on algorithms for experienced programmers that I've yet encountered. The discussion is accessible, the progression is sensible. All of the homework sections for the chapters are relevant outgrowths of the foregoing discussion. The exercises are hard enough that completing them feels like an accomplishment, but they're not so difficult as to be discouraging. It's definitely not the best book for everyone, but it certainly feels as though I came across it at the right time.

Secondly, Big O thinking is incredibly practical. Writing a naive algorithm in and then tweaking it until it runs is n-something time is both incredibly satisfying as well as useful. Writing inefficient programs is incredibly impractical, both from a machine and energy standpoint as well as a human time cost. With this new lens of practicality, understanding how to evaluate routines seems like a common sense to programming. Why not learn how to make better use of your machine?

Another big realization that Skiena's book helped me with, greatly, is understanding what my role is in the realm of algorithms. It sounds ridiculous, but, at some level, I think that I had this notion that being 'good at algorithms' meant that I'd be expected to produce the next shortest path algorithm, a Neigut's answer to Djikstra if you will. Skiena does a great job of couching algorithmic thinking as a framework for problem solving. Given a problem, what tools in your toolset are the best ones to try and solve the problem.

#algorithms #learning #next
10 Aug 2017 c.e.
Trying to Fit a Tonka in a Minivan

One of my biggest weaknesses in software for a long time was the absolute belief in my ability to shoehorn a Tonka truck into a Minivan object.

In other words, I believed that I could take something that looks nothing like a Minivan, and fudge the data structure just enough to fit a Tonka truck in it.

This causes problems. Always. Usually those problems radiate outwards from the data storage place to all the places that have to come in contact with the data. Suddenly you need functions to know how to tell the difference between a Tonka and a Minivan, since what you're handing them could very easily be either.

You need the ability to tell the difference between a Minivan and a Tonka truck everywhere that that data object ends up. The chance for forgetting to check for Tonka vs Minivan-ism becomes higher the longer it's been since you stuck a Tonka truck in the Minivan parking spot. It also becomes higher the more code that you write that has to deal with that parking spot (so to speak).

I find that this is a problem that tends to crop up in non-typed codebases most of all. Because there's no type checking system to make sure that you've kept the Tonka out of the Minivan object, you just shoehorn it in.

It is possible to shoehorn Tonka trucks into Minivans in typed languages; sometimes they give this ability a special name like 'generics'. In generic land, you're only in marginally better territory than non-typed language territory -- the consequences of having to check the label on the object you get remains valid.

I wouldn't care about this so much if I wasn't currently attempting to get the Tonka truck out of the Minivan parking spot at the moment.

If only everyone learned lessons at the same time that I do.

#refactoring #architecture
11 Jul 2017 c.e.
The Art of Differentiation

tl;dr: one of the skills software development requires can make you into a pedantic asshole

This post fits into the category of 'allegorical comparison piece on an abstract idea about software as a concept'. It won't make you better at writing software, but it might help you better talk about and identify certain aspects of the job that is writing software.

Now that I've done the work of setting expectations, let's talk about expertise.

Expertise, Kinds of

Roughly speaking, there are five types of 'expertise' that a person can develop. These expertises are as follows:

  • physiological: feats of strength. Usain Bolt's speed or Simone Biles' graceful, aerial contortions
  • muscular manipulation: muscle memory type things that require a certain amount of practice and movement, usually only developed through practice. Carpentry, knitting, playing a musical instruments, vocal production and acting
  • memory: learning new languages, rote recitation, math
  • social: I tend to think of Machievellian Frank Underwoods, but there's also your friend that likes organizing parties
  • differentiation: a skill based on your ability to tell things apart; typically built through exposure over time, ie experience

These aren't 'pure' categories; learning a foreign language is part differentiation, part memory and part physical skill (muscluar manipulation). Being adept at math requires knowing what kinds of equations are good for solving a particular problem (differentiation). It's also highly likely that I've left some categories out. If you think of any, I'd love to hear about them.[1]

On Differentiation

Of all these skills, differentiation is the skill of erudition.

Consider the case of a sommelier, a wine expert often hired by restaurants to field questions of wine pairings from patrons and offer suggestions to the less knowledgeable. Becoming a sommelier requires you to gain the skill of differentiation in the domain of wine tasting -- if someone asks you to recommend a wine similar to another one that they like, you'd better know of other kinds of wine that are similar to it. Or at the very least, what won't be similar, lest you recommend the wrong thing.

Writing good software also requires a taste for differentiation. Put another way, a software developer needs to be able to know when a thing is different enough from another. Given another requirement or feature, is it a new case statement, or is it something that you can shoehorn into an existing structure? Or once a bug has been found, what type of a change is required? Do you need a separate class or will just an if statement do? Maybe the bug forces a complete rearchitecting of a given structure.

Unlike wine, however, software lines are more difficult to draw. Wine can be categorized based on growing region, grape type, year of harvest, knowledge of the weather that the the grapes were grown in, how long the wine was casked for, what kind of casking process the wine underwent, who's selling it, etc. You can compare the flavor of a wine just by tasting it -- the set of different categories of wine are set. The only wines that need to be categorized are the ones that have been produced; the boundaries are with what exists, concretely.

Software is arbitrary. The space and delineations of software classes are the made up lines that the creator has seen and defined. Yes, the definitions and categories are sometimes derived from the problem domain in which you're working -- enterprises call this the business logic layer of an application because the domain is defined in part by the business needs. But it's not always clear cut whether you should build a factory factory in order to best iterate through the variable typed list or if there's a better abstraction or generic solution that would more concretely capture the difference between the things. Often times, I've found that the solution is subjective, depending largely on both the preferred tools of the developer and the differentiations that they've discerned.

Good Software Developers, Then

Good software developers then, become excellent at the skill of differentiation.

They also become pedantic assholes who want nothing but to get to the root of how or what exactly is the essence of a thing. Because without that root, there is no way to differentiate, no way to tell, exactly, how this thing that you're talking about is different from the other. Whether it's a new feature or something else entirely.

And that is why all of your software writing friends tend, over time, to converge into pendantic assholery.

[1] I would love to know how to classify writing

#art #apis #skills
29 Apr 2017 c.e.
Women In Tech

tl;dr Women in Tech Are Problem Solvers

I'm at a tech conference for women today, listening to a woman talk about her experience getting a board seat at a Fortune 500 company. It's inspiring; it's also devastating that this is a thing we hold strategy sessions on.

That's right. This whole conference is a strategy session.

I want to let you in on a little secret. Women in tech want to make the industry a better place. When women in the industry get together and talk, we talk about what sucks but we also talk about how we can make it better. Lady back channels are problem solving working groups. We complain, we share, and we strategize.

Women pay money for conference fees out of their already discounted salaries to hear other women talk about how to solve the same disparate problems.

Subtle discrimination and inability to be recognized for contributions at work is a problem that we are trying, desperately, to solve. We're trying to fix our micro environments and the things in them that are holding us back from the recognition and promotions that we get passed over for or overlooked for or where the goalposts keep moving just out of reach. We're trying to be better at our jobs, to have our voices and concerns heard and recognized and considered, not ignored and shrugged off. We're tired of feeling like Cassandra, like Hestor, like Mata Hari.

Women in tech are trying and have been trying and if you think they aren't what do you think women in tech fucking talk about. We are problem solvers by trade, what makes you think we would approach professional problems any different?

The fact that we haven't solved the problem yet says something, I think, about the enormity of the challenge.

We're working to fix it. We've been brainstorming and talking and working to fix it.

Why aren't you?

#women #in #tech
27 Apr 2017 c.e.
Roadblocks on the Way to Refactoring

tl;dr how good is your mental map of the territory?

My three month 'anniversary' at Pluot Communications is quickly approaching. In the time since I've started, I've worked on a dizzying number of projects, most of which has been getting up to speed on how WebRTC and React/Redux works. Recently, a lot of our software contractors rolled off the project (and hopefully onto something else equally squishy). Anyway, with their rolling, I've since more or less acquired responsibility for a large React / Redux project. Part of the work we've been doing at Pluot lately is a big re-skinning job, getting ready for some soon to come feature that I'm not allowed to tell you about yet.

Reskinning is like refactoring the view parts of a website. It seems logical to me then that refactoring the code parts would rightly follow. And they usually do, depending on what, exactly has changed about the spec.

Refactoring a project that is A) large, B) mostly unfamiliar, C) untested, D) written in a dynamic, non-self documenting language (JavaScript) is not one of those things that anyone would largely recommend that you do. I'm here to tell you that you can and you should do it. Here's why.

What should Refactoring accomplish?

I'm going to be honest, I don't know why other people re-write things. A lot of times when I've observed teammates embark on refactorings (which honestly never seems to be as often as I feel like I'm hauling off on them, but I digress) sometimes the code comes out cleaner. Most times it comes out far more confusing and complicated and they claim that they've just saved ... something.

I don't buy white knight refactoring. When I refactor shit I'm usually multiplying code. I refactor things so that I can read them, so that the chance of me breaking something in the future in considerably lessened, so that it's easier to make changes to one part of the code without having to necessarily consider other parts. When I 'refactor' I pull out components, try and keep all of the logic for a thing into a single, canonical, topically or functionally organized place.

I try as hard as possible to decouple view code. View code is notorious for being an arena for subtle bugs. You change a padding in one place and it looks good everywhere except the checkout page where it completely hides the Buy button for certain languages. Of course you checked everywhere, except there, and it took an analyst three days of pondering why the sales numbers in Turkey had taken a plunge in order for someone to figure out what had happened.

As far as I know, I've never done anything like this. But that just shows what I know.

You mentioned earlier that refacotring large, unknown, untested, untyped projects is a good idea. Can you expand on this more?

Sure. When you're faced with changing a codebase that you don't understand, the probability for changes you make introducing bugs is very high. There's a whole taxonomy of where bugs originate from that I won't get into right now, but a large, a very large class of them, fall under the category of problems introduced because you did not understand how the code worked. The root of these bugs then is Your incomplete mental model of the codebase.

So how do you pre-emptively fix this class of bugs, bugs caused because there are incorrect assumptions that you have drawn about how the code works? It may seem obvious, but the easiest way to not make bugs based on bad assumptions is to not hold bad assumptions. How do you know what quality of assumptions you hold? Like any good scientist does, by testing them.

How do you test assumptions about code? There are two ways. One is by closely reading the source document. This is a bit of a pro-level move. The other is by changing things and seeing what breaks and how.

Sometimes I rename variables just so I can see where all it's used. That way I have to touch every single last place that that particular variable appears. It also makes grep a viable tool to help you check when you're finished with a particular task -- when all mentions of the old variable are gone you're done. Grep is a particularly important tool for non-static or non-compiled languages. Back in the day when I did Java codes, IntelliJ or Eclipse would automatically reneame a variable with a few strums of the keyboard. Without that compiler guarantee, it's basically up to you to manually check that every instance of a variable has been updated or changed or whatever. Grep's a good tool for this. If you're new to the grep game, check out git grep -- it only parses files that are checked into git. The only flag I really use for grep is the occasional -n which shows the line number that a particular match was found at. Between grep and vim, I can crank through a number of renamings pretty quickly.

What's the use of knowing every place that a variable is used? It gives you an idea of the scope of that object. If you know every place that a variable is used, your assumptions about that variable are probably more accurate, which reduces the chance of introducing bugs. More than anything, you'll find out really quickly how good your naming scheme is. If you're having trouble figuring out which 'versions' of a variable name are related to each other, maybe you should use more explicit or unique names for things. Asking someone to use a project unique name for every variable is a bit of a tall order, but hey no harm in considering it. After all, you are programming in a language with a shitty toolset -- hacks are expected.

When to Refactor?

You should refactor any time that you encounter code that you do not understand and the person who wrote the code is no longer available to explain it to you. The goal of the refactoring should be simple -- to make it such that you do understand the code.

What if you break the code and can't get it work the way that it originally did?

Let's go back to assumptions. If you're unable to re-write code such that A) you understand it and B) it functions as it previously did, then clearly you don't understand what that code is doing.

In this situation, my advice is to either A) start over or B) give up. If you give up, you better not change anything else related to how that code works as you've just irrevocably proven that you have no idea how it works. Clearly the person who wrote it is a madman who sucks at programming and you should celebrate your defeat by posting the offending code-bit to the code shaming website of your choice. I recommend StackOverflow.

What if you need to make a change to that code but you don't understand how it works?

I'm sorry to say it, but your odds don't look very good here. Making changes to code you don't understand is not something I'd put money on. You really shouldn't either, but this all depends on what you consider an acceptable level of risk.

Have you tried asking for help? I hear StackOverflow is a good place for that.

What does Refactoring accomplish?

Ok so you've totally refactored large swaths of your project and managed to wrangle the three-way merge hell into a single large commit.

Congratulations! You are now the only person who, supposedly, understands how the code works. As the only person who understands how the new code works, you have implicitly become its maintainer into perpetuity.

Isn't that exciting?

#refactoring #maps #wtf
26 March 2017 c.e.
Bugs of Projects Past

tl;dr: there is no such thing as a 'worst' bug

A question was put to me last week that I didn't have a ready answer for: what's been the worst bug you've encountered?

I've enocuntered plenty of bugs in 7 years of software development, but when asked directly have trouble bringing a memorable one to mind. Once they're solved they're hard to remember as being difficult. Or maybe I'm too used to things crashing, or to dealing with those once in a Samsung release kinds of problems, that none of it seems re-telling. You deal with Android long enough and crashes on specific systems due to differences of opinion on how an API should be implemented and function become mundane. Once you have an explanation for a bug it seems far less mysterious or interesting. And the tenth time you're blaming Samsung, the previous nine bugs are marginally less memorable.

International Incidents

That being said, I do have a story that, with much prompting, I'll often drag out. It comes from the Android eco-system, from a logging framework that I wrote as one of my first projects as a Professional Developer.

In the first version of the library, I sent back logs with localized datetime strings. This works really well in every language that I tested it in; it works less well in Arabic, whose alphabet uses its own number glyphs. The Arabic number timestamps were incomprehensible by our log ingestor, which meant every Arabic language Android phone was successfully avoiding our attempts to log information about their system.

Arabic numbers are quite beautiful. For a while thereafter, Arabic became my go to language for testing RTL layouts (right to left), even after I discovered there was a debug RTL language setting that was in English but backwards. Dear lord, I even made sure that the Electric Objects app looked decent RTL. I'm a sucker for weird corner case testing.

You can also ask me anything about that one time that I spent a weekend hacking a currency selector into the Etsy Android app and introduced a bug that crashed the app on open for users on phones that had a non-existent locale set as default. Lucky for me this wasn't a lot of users, but coding around it was hard as heck -- deciding on a fallback locale felt fraught with hegemonic implications.

Much later, a co-worker re-wrote one of our navigation drawers in such a way that made it blank for users with their language settings set to Persian. His mistake made me feel a bit better about my own international failures.

A fascination for corner cases would explain my strange fetish for internationalization. While working on the currency selector, I spent a lot of time on the formatting function for prices. There are a lot fun, semi-arcane things to know about price formatting. For example, in some countries (like Sweden) you put the monetary symbol after the price. In America we write $10; in Sweden they'd write it as 10$. A lot of currencies have their own symbol for currency, like the pound or euro sign. In other currencies they use the same symbol as the US, the $, but annotate after the amount to denote which version of dollars they're talking about. A Hong Kong price would be $10HK[1]. Japanese don't use decimals for their prices, you just truncate it at the whole yen. The Swiss franc doesn't have a currency symbol, it's usually only annotated with the letters CHF after the value.

If you really want to get trippy, decimal annotation changes between languages too. Canadian French put spaces between their thousands and use the "," as a decimal separator (1 000 000,34), whereas English Canadians do it like the Brits do (1,000,000.34). Colonialism lives on.[2]

The Java libraries on Android had a fairly complete API for figuring out how many decimal places to show, and what punctuation marks to use, but the before and after split for prices wasn't exactly correct or necessarily nice to look at. Not to mention that the code itself was rather verbose. Of course, after I had figured most of this out, someone on the team (most likely my engineering lead) mentioned that it's best to let the server have all the logic for what to show people instead of embedding it in the client as it's easier to track down and fix bugs that originate with the server. Which would have been all well and good if the server's price formatting logic had been anywhere near as complete as the Java + custom logic we wrote for the app. One nice thing about phones is that they provide a locale and language preference for a user, which you can use to figure out whether to display fonts in British or French Canadian. The server side location preferences were good but not French vs British Canadian good.

Time Bugs

Timing errors led to some pretty memorable bugs. One of the first ones I ran into was while I was at Etsy, working on developing a feature using an emulator. For those of you unfamiliar with mobile development, an emulator is like having a fake phone that you run inside of your computer. It's basically a virtual machine that runs all the same code that runs on a cell phone. The only difference (in theory) is that you don't need the phone hardware. And you can load up & run programs on the same machine you're developing them on.

The old school Android emulators were slow, especially when compared to the Apple iPhone simulators. Simulators use the host computer's chip architecture and do a rough approximation of the same program on top of a different instruction set; emulators have virtual chips that they run the actual program against. Emulators run hella slow because there's more layers of software involved, but in theory are more accurate as far as exposing bugs. Once you started up an emulator, you tended to keep it up as they often took 3-4 minutes to launch.

Anyway, I was working on a new feature for the Etsy Android app, and kept running into a problem with the API requests I was making. The errors didn't make much sense though -- they seemed to indicate that there was something wrong with the certificate on my app, which had nothing to do with what I had changed or was building.

I didn't have a very good understanding of how network security worked at the time -- I knew how to set up a proxy with a man in the middle to read my network traffic (/me pours one out for Charles) but that was just me following a very simple wiki page. It turned out that something about ssl and/or our pinned certificate could only work if the server time was within 2 hours of the phone's clock time. Which is all well and good on a normal cellphone that gets its time from cell phone towers on the regular. However, the emulator that I had been working on, while it had started off with a clocktime that matched that of my laptop, when I suspended my computer overnight the emulator was also suspended. The difference being that it didn't have a separate battery to keep track of the time like my laptop does (more about these later). The clock fell behind by exactly the number of minutes the laptop slept for. Which meant that network requests were failing because the SSL handshake timestamps fell outside of the 2 hour window. Once I knew the problem it was easy to just restart the emulator. I had to start restarting the emulator on the regular and eventually ended up just using real devices for testing because it was faster and easier than dealing with the slow pile of morass that was the Android emulator situation in 2013.

Timing issues came back for some fun when I worked at another job, where we were building proprietary Android devices. Basically someone forgot to put batteries on the bill of materials for parts that we'd need for manufacturing. You need batteries to keep the clocks in sync while the unit is powered off. Most electronics have a battery powering the clock, round the clock. One of our engineering leads had to go find a couple hundred batteries in Arizona while they were attempting to get the devices manufactured the first time around. I believed they got them all in before they were shipped, thank goodness.

One of the hardest bugs I ever had to track down was a race condition (time again!) over a super slow, very spotty network. The problem was in the OAuth renegotiation from a client to a server. Normally OAuth tokens expire after a few hours and the application asks the server for a new one but there were a bunch of reasons why this check would sometimes randomly fail in my app, most of which could be traced to a lack of good locks around the refresh token sequence in the client app.

I did a lot of work to lock the refresh token down to a single thread and moved our network requests to a queue rather than the firehose structure they had been using before, thereby completely erasing the race, but we still would get reports from the field of devices that were randomly logging themselves out due to an expired token. Finally, I managed to replicate a condition where a device on a bad network could send off a request to the server, successfully generate a new token server side (thus invalidating the current token), and then never actually receive the packet with the new token on the client side. At this point your client application is basically hosed -- there's no way to recover without the user logging in again since as far as the server knows it sent you good information. We knew that a surprisingly large majority of devices we had manufactured had less than stellar wifi chips in them so we did what any self respecting software engineering team would do and gave up.

This problem, unique as it is, does highlight an interesting property of network requests -- that they're largely assumed to be successful. I've worked with a lot of server teams, but i've never heard of anyone writing rollback protocols that are triggered by failed TCP deliveries. If you know of one, I'd love to hear about it.

Send Me Your Bugs

I also love hearing about bugs. I also love helping solve bugs, though I'm not great at it. If you've got a particularly juicy one that you'd like to tell me about, tweet it over to me @basicbitchsoftw.

[1] Big thanks to my Canadian co-worker for writing this into our library, I wouldn't have known about it otherwise.

[2] Another front of formatting differences between languages: quotation marks. I've never seen a library that accurately translates quotation marks between languages. I feel like I've seen Google Translate do this elegantly, but a quick check shows that to be mistaken.

#bugs #reflections #race-conditions #internationalization