Friday, June 14, 2019

The Scenic Route To Go Interfaces

Go is an awesome language and interfaces are one of its most powerful features. They allow for decoupling pieces of code cleanly to help make components like database implementations interchangeable. They're the primary mechanism for dependency injection without requiring a DI framework.

Newcomers are often mystified by them but I think they're less confusing if you get to them via the scenic route. Let's look at creating our own types in Go. Along the way we'll find parallels that help make interfaces more clear.

Sidebar: Java Interfaces

If you're not experienced with Java, move on to the next section. Nothing to see here.

If you're experienced with Java, Go interfaces will be pretty familiar and comfortable. The key difference is that a class in Java must explicitly implement a predefined interface. In Go, any type that has the proper method signatures implements an interface, even interfaces created after the type. In Go, implementing an interface is implicit.

Custom Primitive Types

Go emphasizes simple, clear types. You can define your own to help model your problem space. Here I might want to capture a set of boolean flags in one variable:

type BitFlags int32
  • I'm defining my own type
  • I'm giving it the name BitFlags
  • It represents an int32
Why not just use int32 if that's what I want?

One reason is methods. I can attach methods to a type I've defined to give my type additional behavior. Perhaps I define a bunch of constants to represent individual flags and I provide methods like IsSet(BitFlag) bool and Set(BitFlag).

Another reason is explicit type conversion. In other languages it's valid to assign a 64 bit integer variable to a 32 bit integer variable. They're both integers so it's logical to do so. However, you're possibly losing the high 32 bits of the source value. There's an implicit type conversion happening that is often silent and often surprising.

Go doesn't allow implicit type conversions:

i32 := int32(17)
var bf BitFlags
bf = i32 // not allowed
bf = BitFlags(i32) // just fine

This is done to eliminate surprises. The compiler isn't silently setting a type conversion that can change your data without your knowledge. It requires that you state that you want the conversion. This makes it harder for users of the BitFlags type to accidentally provide a numeric value that shouldn't be interpreted as flags.

Custom Struct Types

type Foo struct {
A string
B int
  • I'm defining my own type
  • I'm giving it the name Foo
  • It contains the following data
Structs allow you to bundle pieces of data together into a single item. That item can be passed around as a unit. Like custom primitive types, custom struct types can have methods attached.

Also like custom primitive types you can assign one to the other if they are equivalent using an explicit type cast:

type Foo struct {
A string
B int

type Bar struct {
A string
B int

func main() {
f := Foo{A: "foo", B: 3}
var b Bar
b = f // invalid
b = Bar(f) // just fine

Custom Interface Types

An interface type specifies requirements for behavior. Methods are behavior which is why we tend to name them with verbs or action phrases. In go, any type that has those exact method signatures satisfies the interface's requirements.

type Storage interface {
Create(key string, o Object) error
Read(key string) (Object, error)
Update(key string, o Object) error
Delete(key string) error

  • I'm defining my own type
  • I'm giving it the name Storage
  • Anything with these methods qualifies as this type

Using interfaces I can define requirements for a storage system for my application to use. My application needs something through which I can create, read, update, and delete objects associated with a given key.

func GeneratePDFReport(output io.Writer, storage Storage) error {
// ...

My application isn't concerned with how those operations are actually performed. The underlying storage could be an SQL database, S3 bucket, local files, Mongo, Redis, or anything that can be adapted to do those four things. Perhaps the report generator supports many storage mechanisms and when the application starts it decides which storage to use based on a config file or flags. It also means that when I need to write tests for my report generator I don't need to have an actual SQL database or write files to disk; I can create an implementation of Storage that only works with test data and behaves in an entirely predictable way.

Interface nil and Type Assertions

For all variables of interface types the runtime keeps track of two things: the underlying value and that value's type. This leads to two different ways an interface variable can be nil. First, the interface value itself can be nil. In this case there's no type information, no underlying value; nothing to talk about. This is very common with the error interface. In the case of no error the interface variable itself is nil because there's no error to be communicated.

In the second case there's type information but the underlying value is nil. A comparison like myInt == nil returns false because the interface value exists and points to type information. Ideally in this case nil is useful for that type as in the final example in Dave Cheney's zero post.

If needed you can get at the underlying value inside an interface variable.

io.Writer is a commonly-used interface. It has only one method: Write([]byte) (int, error). If I have a variable out of type io.Writer the only operation I can perform on it is Write. What if I want to Close it? Ideally if you have Close as an requirement you should make Close part of the interface type of your variable (or use io.WriteCloser instead of io.Writer).

For the purposes of illustration you can do a type assertion. This asks that the runtime verify that the underlying thing in your variable is of a certain type:

if c, ok := out.(io.WriteCloser); ok {
err := c.Close()
// handle error
} else {
// not an io.WriteCloser!

In the above example, if out happens to be an io.WriteCloser then ok will be true and c will be out as type io.WriteCloser. If out doesn't happen to be an io.WriteCloser, ok is false and c is zero for io.WriteCloser which is nil.

Anonymous Struct Types

Given a preexisting struct type I can create a value of that with data in one statement:

f := Foo{
A: "foo",
B: 17,
  • I'm creating a variable f
  • It is of type Foo
  • It contains these values

In the above struct examples each of the types I defined have a name; this isn't always necessary providing I'm creating the struct on the spot and assigning it somewhere.

ff := struct {
A string
B int
A: "foo",
B: 17,

  • I'm creating a variable ff

  • It is of this type

  • It contains these values

  • Like the named struct types above I can do an assignment with an explicit type conversion:

    f = ff // invalid
    f = Foo(ff) // totally fine

    This sort of anonymous struct type is common in table driven tests. It's also not uncommon in defining nested structs as mholt's JSON to Go converter does.

    You'll also sometimes see this:

    stringSet := map[string]struct{}{}

  • I'm creating a variable stringSet

  • It is of this type

  • It contains these values

  • The last part looks a little strange. It's a map with strings for keys but what are the values? The values are empty structs: they contain nothing and therefore take up no memory. What good is that? It's a map that only tracks the presence of keys which functions as a logical set. The final magenta curly braces define the initial contents of the map; it's empty.

    Anonymous Interfaces

    Just like you can have anonymous struct types you can have anonymous interface types. The following are equivalent:

    var foo io.Reader

    var foo interface{
    Read([]byte) (int, error)

    In either case I can assign anything with a Read([]byte) (int, error) method to foo.

    We're near the end of our journey which brings us to the enigmatic interface{}:

    foo := interface{}{}
    var foo interface{} = nil
    • I'm defining a variable
    • I'm giving it the name foo
    • Anything with these methods qualifies as this type
    • The contents are explicitly zero
    interface{} is an anonymous interface type. It has no requirements so any value is suitable. I can pass around a value of type interface{} but I can't do anything with it without using a type assertion or the reflect package.

    In this way the empty interface is different than other interface types in that it doesn't specify required behavior. It sidesteps the type system and turns what could be compile-time errors into run-time errors. When writing code that uses the empty interface use great care.

    Saturday, June 8, 2019

    Wednesday, March 6, 2019

    3D Printer Filament Cheap Vacuum Desiccation

    Lots of 3D printer filaments are hygroscopic; they absorb water from the atmosphere. This is problematic for filaments because during printing they are subject to a sudden, dramatic jump in temperature. This causes the absorbed water to explode potentially making detrimental changes to the material properties of the filament. For filaments like PETG and Nylon this makes for a rougher surface and anomalies in the finished part.

    The standard mechanism for drying filament is to put it in the oven for a while. I started getting strange results with my PETG because I got lazy and left it out between prints. I wanted to fix the issue but wasn't keen about putting plastics in my oven. I wondered about other methods and the silica gel packets came to mind. Those are the little packets that come with shoes and other things and say DO NOT EAT. I was skeptical about the power of these to reverse the absorption that had already taken place, at least not in a timely fashion. Also, I like to tinker and wanted to experiment with weird ideas.

    I like to sous vide and had recently gotten a food vacuum sealer with an attachment for sucking the air out of wine bottles. I could seal the filament spools in a vacuum bag with some desiccant but I felt like it would work better if I could get closer to a proper vacuum. I didn't want to invest in a high-grade vacuum chamber and pump for an experiment. I started looking around and found the FoodSaver Quick Marinator; a rigid container with a valve for the hose that connected the vacuum sealer to attachments.

    Here's my setup:

    • Off-brand food vacuum sealer
    • The FoodSaver Quick Marinator
    • The vacuum sealer attachment hose
    • Coffee Filters
    • Flower desiccant powder
    The flower desiccant powder is the same material as the silica gel packets you can get but it's very fine, providing a higher surface area, and they're trivial to renew.

    I put 5 (arbitrary) tablespoons of desiccant powder into a coffee filter, fold it up, and tape it closed so the powder can't easily escape.

    I put my filament spool into the marinator, drop my desiccant pack on top and put the lid on the with tabs on the same side.

    Then, suck the air out. I run the pump until it shuts off. Wait a few seconds, and repeat. I go through about three cycles of this. After the pump has shut off, ensure the pump isn't warm; you don't want to ruin your pump by overheating it.

    Finally I ensure the valve is closed before removing the hose.

    Surprisingly, this worked. My next round of PETG printing produced a nice, smooth finish. I've taken to storing the spools with one of my homemade desiccant packets in a small Space Saver bag and vacuum the air out. It doesn't look like they sell just the small bags and the medium and larger are grossly too large for a filament spool.

    It's important to note that so far I've only done this desiccating process on Dremel filament spools which are 0.5kg. As you can see in the picture above these spools just fit in the quick marinator. Larger spools probably won't fit, loose filament can depending on how much you want to stuff in there. When I get larger spools I'll probably have to come up with another mechanism.

    Thursday, January 10, 2019

    New 3D Printer: Dremel 3D45


    For a while I had a 3D printer. Specifically a Printrbot Simple Metal. When it worked, it was a lot of fun. I could start with an idea and turn it into a real physical object without the need for a big workshop, huge mess, or personal injury. When it worked, it was great! But the process of getting it to work and keeping it working took all the joy out of the prospect of desktop fabrication.

    Three years later I found myself thinking about getting another 3D printer, hoping that the reliability had improved. I started looking at what was on the market with an emphasis on reliability: I didn't want to tinker with the printer, I just wanted to turn designs into objects. Dremel seemed to have some reliable offerings though a little pricey. I pulled the trigger on the 3D45 and so far I'm very pleased.


    I should be getting compensated for this review. My printer came with a small flyer that said if I post a review of the printer on my blog I would receive two spools of PLA for free. The flyer didn't provide direction on what the review should say.

    Initial Impressions

    I pulled the printer out of the box and had it set up in about 20 minutes. I was able to start a job for a frog figure from the internal storage. It came out almost perfect with a couple of misaligned layers and some poor adhesion ("springing") at the top.

    Overall though I had good luck with the printer initially. I would sometimes have trouble with first layer adhesion which is the most common problem printing. Trying different things to correct it I found that washing the build plate, perform bed leveling, and reapplying glue would almost always correct the issue.

    The Good, the Bad, and the Ugly


    It just works. I've used an entire spool of ECO-ABS with an overwhelmingly positive success to failure ratio. I've printed in PETG and Nylon as well with no failures there. Nylon is notoriously annoying to print with and it worked on my first try. Note; The ECO-ABS is a proprietary formulation of PLA.

    It looks nice. While I don't actually care how it looks, the fact that it's fully self-contained means that the cat, the dog, dust, Dorito crumbs, ejected shell casings, etc won't put my prints a risk.

    It has almost all the bells and whistles. As stated, it's fully-enclosed to help keep it work inside and reduce warping. It has a heated bed to help with the same. The build plate is tempered glass in an easy to remove and handle frame. I'm really pleased with how easy it is to work with the build plate. It's got a touch screen that provides helpful information and allows you to perform basic operations and start/pause/cancel prints from onboard storage or a USB drive. It prints "ECO-ABS", PLA, PETG, and Nylon. It has an integrated web cam, runout sensor, yadda-yadda-yadda.

    The filament seems really good. The color and performance are consistent throughout the spool. I don't really have problems with first-layer or intra-layer adhesion. The Dremel filament spools have an embedded RFID tag that the printer reads and use to automatically set the temperature for the extruder and bed.


    It's expensive. The printer retails for $1800. I got mine for $1400 on Amazon black Friday. That's fine as a reliable device that lasts years is worth investing in. The filament, however, is also expensive. Common, non-funky filaments run between $15-30 per kg. Dremel filament runs $30-40 per .5kg. This is tempered somewhat by the fact that between the quality of the printer and their filament my prints succeed more so I waste less (save my own design mistakes).

    It's something of a walled garden. There's not a lot of room to tinker with the printer. I don't want to tinker with the printer... I don't want to have to. However, should it be necessary it would be nice. I can't complain too much as I made a conscious decision to sacrifice hackability for reliability.

    The network features are weak. You can manage and monitor print jobs through their cloud service but you can't do so over the LAN. The frame rate for the video in their cloud service is like 0.1fps. It's difficult to actually understand what's happening.


    The cloud slicer is garbage. You can upload an STL to the cloud service and have it do the slicing for you. It was easy! I never got a successful print from the cloud slider. Usually there would be a loss of inter-layer adhesion leaving me with a slinky vaguely in the shape of my print. Using the Dremel Cura desktop slicer works extremely well and when I upload the gcode it produces to the cloud service the results are great. Unfortunately they kind of tout the cloud service and using only the cloud service brought me nothing but failure. Luckily I have some printing experience and knew how to troubleshoot this.

    "Filament DRM". They strongly encourage you to print using only Dremel filament. It seems to be high quality and the RFID identification feature is definitely neat. However, the state that using non-Dremel filament will void your warranty. This seems insane to me. I get that they wouldn't want to support issues people have using janky filament. I would totally accept that if I use 3rd party filament and my house burns down they shouldn't be held liable. But to say that they are unwilling to support me for using less expensive filament leaves a bad taste.

    And the filament cost. I would feel a lot less annoyed about the quasi-restriction of using only Dremel filament if it weren't 2-4 times the cost of other filaments. It is good but the difference in cost is kind of crazy. To some extent they market this product line for education; schools can't afford this. Also, they should encourage other filament vendors to use the same RFID spec. It's a cool feature. Overall, they should make the filament significantly cheaper or penalize their customers less for using third-party filaments.

    I'm really disappointed that I can't really use the built-in camera decently. I get that they wouldn't want to stream 720p over the Internet to everyone; they aren't trying to be a video streaming service. There should be a way for me to watch it in full quality over my home network.

    Trouble Strikes!

    Eventually I had a serious issue that wash/level/glue wouldn't resolve. I wasn't getting a first layer. The extruder would travel around the surface of the bed and yell CLICK CLICK CLICK CLICK as though some gears were slipping, like something was stuck. Thinking I had a clog I looked in the manual for their clearing process. The troubleshooting matrix says that if have a clog to contact support. Simultaneously the manual has instructions for clearing a clog. I went through the clog clearing process and found that the extruder could push filament out fine. Attempting another print I got the same symptom. It seemed that the tip of the nozzle was flush with the bed and it was clogged because there was no place to extrude filament to.

    I call customer support but it was a Friday afternoon. Wonderfully, they have US-based support. Unfortunately for me they're in Central Time, I'm in Pacific Time and they were already closed. I used their email contact form and received an automated response saying I'd hear back from them in two business days. This being Friday I shouldn't hear back from them until Tuesday or Wednesday. On Monday I got a response with corrective instructions that fixed the issue in a few minutes. It sucks that I was "out of commission" for several days. It's awesome that I had access to people whose job it was to help me. Free input on 3D printing issues will vary far and wide on the nature of your problem and remediation.


    I think my money on this printer was well-spent. I've been really enjoying it. I feel like I got the reliability I was looking for. The filament is really expensive which makes me hesitant to experiment.

    Saturday, March 3, 2018

    Impossible Burger

    I just ate an Impossible Burger at Fatburger. If you hadn't told me what I was eating I would have told you I was eating a good but not great beef hamburger. The fact that it was entirely plant-based is impressive. It was savory, the texture was well within expectations for a beef hamburger.

    Kelly tells me it nutritionally matches beef so it's not necessarily healthier. There's still the reduced environmental impact over beef. I could even see versions that compromise: including perhaps 10% beef for the extra flavor.

    It was expensive though. Our two single-patty burgers with fries and drink was $31. I'd like this to become more popular so the price can go down. I would happily pay a dollar extra per patty for this as an substitution option at fast food places.

    I'm really impressed by this as a first product and look forward to where this is going.

    Friday, January 5, 2018

    Black Mirror - S4E1: Roko's Basilisk

    The first episode of Black Mirror season 4 is quite good. It brought to mind Roko's Basilisk. Go read about the silly thing human brain's get up to. I'll be here when you get back.

    Tuesday, January 2, 2018

    FPS: Wolfenstein II: The New Colossus - More BJ For Frau Engel

    Steam Sale, Wolfenstein II. Yes.

    I can reasonably say I've been playing Wolfenstein as long as there's been Wolfenstein. I even played the MS-DOS port of the original 8-bit game a few times. I played Spear of Destiny, Blake Stone, etc. Wolfenstein: The New Order is almost flawless.

    The New Colossus is a solidly decent game. There's more of the unexpectedly good story and character development from the previous game. This is definitely not the fungible, faceless protagonist of previous entries in the series, or even most FPS in general. Your character has thoughts, emotions, demons, loves, etc. The supporting cast of characters are dynamic and lifelike and it's definitely worth getting through the game just to see how the events played out. The ending actually felt fulfilling; moreso than in The New Order in my opinion.

    About halfway through though the story jumps the shark in spectacular fashion. In the first half the protagonist is put at a significant disadvantage and you're made to wonder how it might be overcome. The way in which it is overcome is completely absurd and thankfully it is quickly put behind you. When you get to the shark jumping, groan your way through it and press on.

    Combat is mostly satisfying. You get the same optional dual-wield mechanic as in The New Order though in this instance it's rare that not dual-wielding is the way to go. The way you choose which weapons are in which hands is unnecessarily clumsy on PC; I suspect it's made for console controller. As you explore you can find hidden weapon upgrade kits that allow you choose from three upgrades per weapon that are not mutually exclusive. Each weapon has an upgrade that can be toggled. For example, the machinepistol upgrade makes your rounds incendiary while dramatically reducing the rate of fire. Incendiary MP is magical against the panzerhunden but much less effective against human targets. I found triple-shot shotgun in the left hand and single-shot assault rifle in the right to be a great combination allowing effective firepower against both close and far targets.

    In principle The New Colossus allows you to choose stealth over bravado the same way The New Order did. In practice you can stealthily take out the first 2-6 enemies in a stage before things go sideways, more or less regardless of your execution. If a guard finds the body of a fallen enemy they go into a heightened state, which is fantastic for gameplay. Unfortunately, you have no mechanism for moving or hiding those bodies, even given ample time. This can be quite frustrating. Doom (2016) also gave you no reliable means for stealth combat, or even space to conduct ambushes but in Doom the whole flow of the game is in high-velocity, run and gun combat. The New Colossus holds stealth combat out and then snatches it away, just when you think you've got it.

    Run and gun works well and as mentioned you're mostly forced down this path. That said, most enemies have no special tactical weaknesses (less armor on the back) so few fights benefit from flanking. The super soldiers are weak in the back but it's easy to bait them into charging past you for easy back shots. Overall most fights I ended up just finding the most advantageous ambush point and waiting for the enemies to come to me. And they did... I would really like an FPS developer add an "I see the bodies of my comrades piled in this door way so maybe I should take a different route" mechanic to enemy AI. Which is a shame because many of the combat spaces are huge with multiple tiers, multiple places for cover, resupply, etc. Usually though I couldn't be bothered and just explored the space at my leisure after dispatching the majority of my foes with the stupidest possible ambush. Eventually though I decided to not pick up heavy weapons, to not ambush as much, just to keep the combat more dynamic, even on a higher difficulty setting.

    After you've hit the game's shark-hurdling portion you get to choose a "contraption" that gives you a special ability. As the game progresses you get to pick up the other two. The difference between these choices basically boils down to, "to get into the next room do I crawl under, climb over, or smash through?". Regardless of your choice you still end up in the same room so the choice is somewhat illusory. It's mostly a question of what kind of entrance do you want to make to the party.

    Criticisms aside, it's quite a fun game and worth a playthrough. Grab it on sale and rock out!

    Monday, January 1, 2018

    Cards Against Humanity Enhancements

    One of my friend groups plays a fair amount of Cards Against Humanity. I've come up with some enhancements.
    1. Use a shoebox, game box top, or some other box for white card discard. It's much neater than discard piles.
    2. Use a hat or something similar to collect white card submissions. It genuinely speeds things up.
    3. Provide multiple stacks of white and black cards respectively for people to pull from. It makes it much easier for people to get their next cards and keeps the game moving.
    4. If the black card with three blanks is in your deck, pull it out permanently.
    5. When a black card with two blanks comes up, the judge draws a white card to fill in one of the blanks of their choosing. Everyone submitting two white cards slows the game down. Filling in one of the blanks with a random white card means the black cards with two blanks become unique every time they appear, rather than tedious.
    6. During the initial deal-in for each player, give them three extra white cards. Each player discards three before the game begins. This provides a funnier set of initial cards for everyone.
    7. Draw two, keep one. After each player submits their white card they must draw a replacement white card. Instead, each player should draw two white cards and discard one of the two they just drew, their choice. This reduces the accumulation of bad white cards.

    Monday, September 4, 2017

    Fighting Acute Depression

    My only reliable strategy for fighting acute depression:
    • Identify something simple (simple does not equal easy) that I don't want to do but will feel good having made progress on. Dishes is a good one for me. Laundry is another.
    • Identify the smallest thing that constitutes progress. Washing one dish, putting away one piece of clothing.
    • Focus on the fact that doing that smallest thing represents progress. If I get more done, great! If not, I made progress when feeling overwhelmed.
    • Go do that smallest thing. Chances are more will get done since starting is the hardest part. If not, I don't beat myself up. I made progress and the next progress will be easier.
    • It doesn't always work and that's okay too. When getting started is the hardest part, trying is a small amount of success which fuels further success.

    Friday, January 27, 2017

    Vault: Error checking seal status: ... Forbidden

    $ vault status
    Error checking seal status: Get https://vault.internal-domain:8200/v1/sys/seal-status: Forbidden
    There was this issue suggesting it was a problem with the storage backend. In my case it was having HTTP_PROXY set in the environment and the proxy won't allow the connection. unset HTTP_PROXY fixed the issue.

    Thursday, January 5, 2017

    Golang Install: Uanapproved caller. SecurityAgent may only be invoked by Apple software.

    Trying to install golang 1.7.4 on Mac OS X I got the following error:

    Uanapproved caller.

    SecurityAgent may only be invoked by Apple software.

    Friday, June 17, 2016


    Since Dayna passed away I've felt strange in that I haven't felt guilty. I took responsibility for her care and have maintained that for years so ostensibly I bear some responsibility for her passing. I've worried that my lack of guilt indicated that there was something wrong with me.

    I've begun to accept that I did everything I could. Everything I could was limited by my capacity. I was also in a very difficult situation and my failures and missed opportunities were expressions of that. She was the only one who could save her but she was stuck, trapped by her illness and the habits it had instilled in her.

    I made mistakes but I never intentionally acted against her. Were there a solution available to me I would have acted on it. No one can know if there was a solution available to her. That weight was only hers to carry and she couldn't bear it. Many of us reached out to her because we felt responsible for helping her but we could to nothing to fix her. Sometimes that's just how things work out.

    Monday, April 4, 2016

    Dayna Gordetsky

    On Friday the 1st of April I learned that Dayna had passed away, having taken her own life. She had suffered a great deal both physically and emotionally. I don't think any of us will ever really understand what she was going through but we're coming together as a family to work on accepting it. If you're in the San Diego area and would like to attend the funeral, contact me privately for information.

    Saturday, February 13, 2016

    How I Became a Monster, Part I

    I don't really know how it happened and that's part of the problem. It's been like boiling a frog; the changes have been so slow it was hard to see the change happening. I'm writing this via stream-of-consciousness so it's not going to flow well.

    Dayna and I have been friends since 2000, and partners since 2002. I'll skip the love story and get to the plot. I've been abusive, neglectful, unsupportive, unsympathetic, and deceptive to her.

    I'm compelled to clarify abusive: I've never been directly physically abusive toward her. I've never struck her or anything like that. It would have easily been the last thing I ever did, plus it's just not my way. My sister and I were disciplined with spanking as children up until the point where my father left a bruise on my sister. He never spanked us again and after that he was able to bluff his way through spanking situations. That's how I remember it, anyway. I've never felt physically abused and actually respect my parents' approach to spanking.

    I've been an angry, anxious, depressed person for a long time. I took a lot of that out on Dayna. The rest I habitually keep inside until it boils over to take out on Dayna. It's taken me years to recognize the smallest part of this and I know I still don't see all of it. It's hard to know where to start as this has been ongoing for over a decade as part of everyday life.

    The first thing to know is that I have a grossly overdeveloped sense of responsibility. I cannot overstate this enough. If I can take care of something I will probably take responsibility for it. I can't possibly do everything so I fail to deliver on most things. Luckily for me this failure is silent. Few if any people know I've taken responsibility for this or that so I can feel inwardly guilty and unconfident but look capable and hard-working and dependable on the outside. I exist in a continuous state of being overwhelmed by my (notional) responsibilities and undermined by my (notional) failures. Saying out it out loud hasn't done much to reign this in.

    When Dayna and I really started getting to know each other she told me about a number of mental disorders she suffered from. Growing up I saw my mother as constantly under great stress from her work and my father doing everything he could to make things easier for her. Being a kid I could have been way off but I internalized what I thought I saw. So I took responsibility for making her life better. Had this been something I said out loud I'm sure Dayna would have said this was ludicrous. One person can't fix another, they can just be accepting and supportive. I was pretty accepting and supportive in the beginning but eventually this was overridden by my own shortcomings and misguided ideas how on people help each other.

    Things have gotten particularly bad between us over the last few months. Long-standing injuries to Dayna's spine have been getting worse, putting her consistently in a great deal of pain. The pain has made her irritable and my inability to really help her has been triggering my need to fix things. I haven't been fixing her so my mind has been bouncing between "I'm failing" and "There's nothing I can do". I've been physically supportive by way of getting her things, trying to make her comfortable, etc, but I've been almost completely emotionally detached and unwilling to accept that it's not for me to fix. This detachment made me completely emotionally unsupportive. My lack of sympathy and support causes her stress and anxiety which increases her pain and irritability which in turn causes me to be stressed, anxious, angry, and unsupportive. I've been there for her in ways that are completely superficial and rarely in ways that were genuinely meaningful.

    To be continued...

    Friday, August 21, 2015

    Phone Interv(iew|ention)

    I participate in the hiring process at work through phone and onsite interviews. The phone interviews are initial screenings for candidates intended to determine who we want to bring in for the onsite interview gauntlet. Our process has me doing Q&A with the candidate then I write up details of the interview and my recommendations. Then, one or more people higher up the chain make decisions about how to proceed.

    For both types of interviews there's a fixed time slot. Sometimes during a phone interview I'm confident within the first 10-20 minutes that the candidate isn't qualified. Often in these situations I like the candidate and would happily hang out with them over drinks and geekery but I wouldn't want my project to depend on them.

    I come to the conclusion that the candidate won't fit usually after I've given them a few extra meters of rope to climb up with and they just hang themselves more. If it seems unlikely that more rope is going to rescue them my standard bailout is "Those were all the questions I had for today. Do you have any questions for me?" It's polite but dodgy and it seems unlikely to me that the candidate doesn't realize that this is a signal that they've bombed.

    On at least one occasion the "questions for me" portion developed into a friendly conversation about skill development and I was able to provide a book recommendation that flowed naturally with that conversation. What I'd really like to do is just cut the interview, be forthcoming, say "the higher-ups may disagree but I think you still need to develop for a position like this", and then provide guidance about what the candidate can learn and practice to up their game.

    I see a few potential risks here. First, it's sufficiently out of normal (impersonal) interview protocol as to feel vaguely unprofessional. That said, is it really important to stay 100% professional (impersonal) when I can actually help someone? It's not just me though, I'm also representing my company.

    Second, I'm essentially cutting out the higher ups here and decisions about a candidate's progress through the hiring pipeline are under their purview. But, they make those decisions based on my view of the candidate so if I'm confident the candidate isn't a good fit it would be exceedingly unlikely for them to disregard that.

    Third, there's the risk that I might come across as providing a prescription for getting the job in the future. I can mitigate that to some extent by being as forthcoming about my intent as possible. Still, there will always be a candidate who gets the wrong idea despite my best efforts. If I've done my best I guess I can just let it be "their problem" but that feels kind of irresponsible.

    The easiest thing to do is just get out of the call and forget about them and that's mostly what I've been doing so far. I was asked recently by a candidate if I share my knowledge publicly and it surprised me to say "no". I used to but I haven't been recently and I feel that's kind of a loss. I should be teaching more.

    Monday, June 8, 2015

    Le Diet

    I've been dieting for a couple of months now. I'm down about 9.5 pounds which isn't huge, but it's progress and it's been with minimal suffering. Here's what I've been doing:
    • Drink lots of water. I don't enjoy drinking water but it's a lot more palatable when it's ice cold. I also like adding a bit of lemon juice. There are "flavor drops" you can buy for the same purpose.
    • I gave up soft drinks and artificial sweetener. There's no scientific reason for this. Logically speaking the artificial things aren't needed in our diet. They may or may not be harmless. More than anything I did it to see if I could do it. It took about two weeks for the cravings for soda to go away.
    • I do drink coffee. I'll have a large (16oz) with about a Tbsp of real sugar once or twice a day. This is my flavored drink. Tea would also be fine but I haven't felt like having tea. I don't consider this part of the diet per se, it's just here for completeness.
    • Protein smoothies - this is one of the main facets of my diet. They're high in protein, high in fiber, relatively low in calories, and really tasty and refreshing.
      • A smoothie blender. I have an Oster.
      • A cup or so of frozen fruit. I buy 1-3lb bags at the grocery story and they're usually in the frozen dessert section.
      • 8oz of cold water. This is called for by the protein powder.
      • About 1Tbsp of table sugar. You can use more, less, or artificial to taste.
      • One serving (two scoops) of EAS Lean 15 powder.
      • A generous splash of lemon juice. I love lemon juice.
      • Ice cubes until the fluid is almost at the top.
      • I screw on the bladed cap thingie and shake it until the ice moves around freely (so the blender doesn't jam) and there aren't powder clumps on the wall of the bottle.
      • Blend it until it looks like it's about an even consistency. The fluid should be spinning all the way to the top.
      • This makes a nice fruit lemonade.
      • Instead of lemonade, I also do frozen banana (peel, break in half, stick in sealable bag), cocoa powder, sugar, powder, water, PB2, and ice. Also very tasty.
      • I have 2-3 of these per day. 3 is almost 100% of your daily protein.
    • Chunky soups. Fairly low calorie, filling, vegetables, etc. I get tired of them sometimes but they have the benefit of being trivial to prepare. Any of these with chicken broth benefits from a squirt of sriracha if you're into that sort of thing.
    • Low-calorie frozen entrees. I get the "Eating Right" brand and stick to ones that are under 300 calories.
    • Occasionally, a sandwich. Whole wheat, medium cheddar, turkey breast, chipotle mayo, pickles, peppercinis. These pickles and peppercinis make it for me. This is probably the highest calorie thing I eat.
    • Fresh fruit. Apples and bananas mostly because they're really convenient. When my excess bananas start to turn brown I freeze them as above.
    • Chocolate Mint Builder's Bar. They have other flavors. These are relatively high calorie but sometimes you need a treat. They're tasty, have a satisfying texture, are silly high in protein, low glycemic index, etc. Pairs nicely with a fresh apple. No more than one per day.
    • Gummy multivitamins, just in case.
    • Fish oil pills because my cholesterol is a little high.


    American portions are way too large. We get conditioned to eat an amount of food in one sitting that we can't effectively deal with. Our stomachs become accustomed to getting a lot of food and get pretty large. We get trained to where we don't feel full unless we're stuffed and have had too many calories. The overall goal is to maximize the feeling of fullness while minimizing calories.

    One thing to work on is getting accustomed to being full on less food. This means eating smaller portions. This is tough while you're used to big portions. I think this is the part you just have to tough out. Any time I eat something that has about 300 calories in it, I wait 30 minutes before eating something else. I try to drink 8oz of water or so after I've eaten to increase the feeling of fullness. While I'm working on portion size it doesn't matter how much I eat overall. So if I'm eating every 30 minutes until I'm full, that's basically okay. The key is to get used to eating small amounts. Succeeding here is essential to getting away from poor styles of eating. It took a couple of weeks to adjust to the size of meal. During this phase I found it beneficial to prefer 300 calorie servings that were more food.

    Be ready to fart. A lot. The normal American diet doesn't include nearly this much fiber. We can't digest fiber. The bacteria in our digestive tracts will happily digest the fiber and their waste product is gas. I fart a lot. The way I poop has also changed. Drinking lots of water helps some.

    My weight fluctuates throughout the day and throughout the week. Suddenly weighing one or two more pounds will easily happen as I eat, drink, and eliminate. I can't really judge your progress day to day. Weekly or every two weeks is better; I need to pay attention to the trends and not the day to day weight.

    Sunday, December 28, 2014

    3D Print Host Log Book

    What isn't always clear to the uninitiated is that 3D printing is a hobby of tinkering whether you want it to be or not. The output of a print will vary by:

    • Printer make/model
    • Revision of printer hardware
    • Revision of printer firmware
    • Host software
    • Slicing software
    • Temperature of heating element(s)
    • Speed the print is run at
    • Type of filament (PLA, ABS, nylon, etc)
    • Brand of filament
    • Batch of filament
    • Progress through a single spool of filament
    • Print surface (metal, wood, glass, tape)
    • Condition of print surface (cleanliness, presence/absence of adhesives)
    • Ambient temperature
    • Humidity
    • Nearby airflow
    For better or worse there's also not a single set of conditions/settings that will make your prints successful. You may get very similar results to a given print by increasing print speed if you also increase temperature (or maybe the opposite).

    Lately I've been working quite a bit at dialing in settings that work well for me. The MG Chemicals glow PLA I've been using for my train track project has been giving me no end of grief. In my setup it's all I can do to get it to adhere well enough to the print surface, let alone reduce corner warping enough to get usable output. Two different spools of Shaxon (natural, blue) work great, a spool of glow green I got from is also great. With the MG Chem I'll print a part and get good results, then print the same thing again and it will be a disaster. I've basically given up on it and switched to the filamentsupply glow green.

    As an aside, my process now that's working pretty well is:
    1. Preheat the extruder to working temp +5C and let it sit so other surfaces can heat and expand.
    2. Adjust surface tape as needed. So far if I wipe with alcohol I get so much adhesion that it's difficult to sand the tape off the part.
    3. Set the slicer to run at 30% speed for the first layer.
    4. Set the slicer to produce a 3mm brim.
    5. Set the slicer to not engage the fan for the first 3 layers.
    6. Because I have my printer basically in a hallway, I make sure that there are no nearby doors open that will permit a draft.
    7. Take my heat gun and heat the surface until it registers around 110F with my IR temp gun.
    8. Start the print and watch it until the first two layers are complete. If I get there, it's like 95% success chance.
    I've started keeping a log of my prep steps, settings, and materials and then recording notes on the results for the output. I expect this to be a handy troubleshooting tool.

    Given that this is an inherently tinkering hobby, the host software should have this built in. When I go to do a print, it should record everything it knows. Printer settings (temp, etc), slicer settings, any calculated output the slicer provides (bounding volume, footprint, estimated volume of material, estimated print time), and actual print time. Having integrated cameras to take high-res photos every so often during the print would be amazing. It should of course provide an interface for notes so I can record anything the software doesn't, particularly observations of the output.

    Sunday, December 14, 2014

    Dreidel, dreidel, dreidel, I Made It Out of Polylactic Acid Plastic

    3D printed dreidel body and separate handle lying on newsprint. The handle is painted with white nail polish, the body is unpainted.
    3D printed in PLA with handle painted.
    That's how the song goes, right? Well, in spirit at least.

    We're a multi-cultural household and I have a 3D printer I'll continually need to justify buying. So, I decided to print a dreidel and see how I could do finishing it.

    I'm working with 1.75mm Shaxon PLA in "natural" tone which is vaguely clear-ish. I'm using a Printrbot Simple Metal at .2mm for all layers using Reptier-Host Mac and the newest stable Slic3r.

    Right off the printer it was smooth and solid. The handle did not fit into the socket on the top of the body so I first tried sanding the star of the handle. This did not progress quickly so I stepped up to small hand files. This was faster, but still pretty tedious so I pulled out the dremel. This! Was! Fast! I still had to finish with the files as even at low speed the dremel melts the plastic as much as it sands it. Some quick filing and the burrs were off and it had a nice fit that was tight enough to stay together through friction. It spins well too!

    A youtube video I saw suggested nail varnish (nail polish here in The States) for finishing prints. The idea is that it's viscous enough to fill in the ridges between layers. Also, it's intended to provide a durable finish. I thought it would be a good way to test out finishing without buying a lot of painting tools. As an aside, some of this was $2 for 0.5fl oz, some was $10.50 for 0.5fl oz. This should be considered an elicit substance!

    Dreidel on newsprint, glyphs are painted with white overflowing the shape of the glyph.
    Glyphs painted in white.
    For bulk-coating it works pretty well. For getting into detailed spaces it's not so great, at least not with the included brush. I already planned to overflow the glyphs and sand off the overflow.

    This did not work as expected. The paint really does seep into the ridges which meant sanding off all the overflow would require completely sanding down the surface of the body, at least around the glyphs. Oh well, it's white paint so adding color over it should be just fine.

    Dreidel lying on newsprint, glyph painted with white paint. Some of the paint is sanded off but ridges on the surface filled with white paint are still visible.
    Sanded the overflow, kind of.
    It didn't quite. My blue paint was kind of a blue tint with fairly subtle sparkles. The white showed through easily but the sparkles were nice. This is where I see that this is intended to be going over nails and being translucent can make for a cool effect. In this case it is still kind of a cool effect because it smooths out the layering ridges while leaving them visible. This might be really neat for some projects.

    Even though the handle stays in easily through friction alone, I figure at some point I'm going to drop it, it will bang on something, and the handle will go shooting off, only to be found next time I move to a new home.

    dreidel is lying on newsprint with the tip pointing up and the handle separate. The surface is a shiny translucent blue.
    First coat of blue.. with sparkles!
    Ultimately I'm pretty pleased with the results. I'm kind of clumsy doing fine painting but I have virtual no practice and absolutely none recently.

    Dreidel is sitting tip down in a soda bottle cap. It is a much deeper blue. The handle is lying beside it.
    A couple of coats in, looking snazzy!
    Finished dreidel sitting tip down in a soda bottle cap. It's a shiny deep blue with white glyphs. The handle is attached and a hot glue gun is visible beside it.
    All done!

    Thursday, October 24, 2013

    Golang, cgo, and XCode 5

    TL;DR: Don't. Stick with XCode 4 for now.

    I don't know much about developing on Mac. I may also be a moron. I'm a Linux guy and can at least make the claim that I'm a programmer. I'm definitely comfortable with command line tools and relatively uncomfortable with IDEs.

    I've been working on a video game project on Mac in go, using go-gl. The go-gl suite is a set of thin wrappers around C opengl libraries. As such, it depends on local C compilers and the cgo compiler. My libraries are installed via MacPorts which required installing XCode and its command line tools. Those command line tools also provide tools and headers that will be used by cgo to compile go code and C code that are linked together.

    When XCode 5 came out it showed up as a regular upgrade which I followed. I dutifully installed the new command line tools. I later found that I could no longer compile my game code. Any code that didn't require go-gl was working fine.

    Eventually I found that the issue was that XCode 5 no longer includes GCC. I eventually figured out that if I install gcc47 from MacPorts, prefixed builds with CC="gcc-mp-4.7", built go from source, then prefixed all my go get and go run commands wit the above CC envvar I could get it to work. However, it would no longer produce static libraries for the opengl wrappers and my compiles that were previously instantaneous where now taking on the order of 10 seconds.

    I upgraded to Mavericks today and my XCode along with it. It didn't help. Being frustrated I did more digging and found that if I went back to XCode 4 things should be fine again. I ripped out XCode 5, navigated the Apple Web Maze to find XCode 4, download it, grab the command line tools, etc. Seems to work now the way it used to.

    Except, MacPorts is broken. Mavericks doesn't have /usr/bin/gnutar so I have to ininstall MacPorts. There's no binary package for Mavericks so I have to do a source install. That was at least painless. This gripe has nothing to do with go, of course.

    Friday, October 18, 2013

    Be Careful With Your Brain Drugs pt II

    At a friend's suggestion I tried setting an alarm for a couple hours before I intend to get up and when it goes off I take my Cymbalta and go back to sleep. The idea is that after a couple hours of absorption the "upper" effect of the medication will be there and it will be easier to hop out of bed and be an obnoxious morning person.

    Instead I had incredibly bizarre dreams. I normally have weird dreams but this was on another level. While they had what passes for dream continuity, I can only recall fragments and I won't try to reproduce them here.

    The really strange thing was after I got up and into the shower. I found myself experiencing real paranoia. I wondered if someone had installed a camera in my bathroom. I wondered if someone else was in the room. I wondered if my girlfriend was going to ambush me when I reentered the bedroom.

    For each of these thoughts it only took me a second to realize that it was unfounded, but when the thought occurred it felt plausible for an instant. Very strange.

    I'm going to keep trying this for a couple days to see if it persists, settles down, or was just a fluke and additionally to see if it provides actual benefit. So far I don't feel particularly more alert but having taken the meds early they should diminish early and I will hopefully find it easier to get to sleep early.