Justin Duke

Ten arguments

I just finished 300 Arguments, a series of aphorisms, vignettes, and truisms.

I recommend it: it’s not perfect, and a lot of the observations tend towards the vacuous, but the process of reading it is so quick and frictionless that it’s worth wading through the banality – like watching an okay movie that has a couple transcendent scenes.

My favorite ten “arguments”:

I don’t miss the city. I miss the place it was in the nineties, when everyone else also was twenty-two and broke.

Only a fire can teach you what survives a fire. No, it teaches you what can survive that fire.

I fret about my lost scarf. Then I miss my flight.

I’ve written whole books in order to avoid writing other books.

The true nobility put their inferiors at ease—by being kind to them? No, by dismantling the system for a moment.

The first beautiful songs you hear tend to stay beautiful because better than beauty, which is everywhere, is the memory of first discovering beauty.

With great and solemn portent, my teacher announced she would tell us something that her teacher had told her, and that her teacher’s teacher had told him, and so on, back to Yeats: The thing to remember is that no one ever finds out that you don’t know what you’re doing.

Bad art is from no one to no one.

Biographies should also contain the events that failed to foreshadow.

Every case is orthogonal to all the others. That’s the entire problem.

Permalink

Django vs. Flask

A great, thorough writeup on Django vs. Flask has been floating around the past few days. It’s a great technical breakdown, and I agree with the conclusion:

There’s an informal perception that Batteries included may mean a growing list of ill-maintained API’s that get hooked into every request. In the case of Django, everything works across the board. When an internal Django API changes, Django’s testsuites to break and the appropriate changes are made. So stuff integrates. This is something that’s harder to do when there’s a lot of packages from different authors who have to wait for fixes to be released in Flask’s ecosystem.

However, it also glosses over what is probably the strongest weapon in Django’s arsenal: Django Rest Framework. At this point, I essentially consider DRF a first-party package: it is so completely essential to my Python web development toolbox I can’t imagine working without it.

Having such a powerful, extensible approach to REST (and everything that entails: serialization, permissions, filtering…) is invaluable. Flask is great for toy projects, but for a modern application DRF is unreplaceable, and thus so is Django.

(Another important thing that Django does: it forces a certain level of structure and organization to your application. I used to think this was either unnecessarily or actively harmful: now, having seen my fair share of eldritch Python codebases, I know better.)

Permalink

Globally accessible Vue properties

So, Buttondown uses django-js-reverse, which is a fantastic way to handle naming URLs and consolidate routing logic. It means that if I’ve got a bunch of views registered in Django like this…

urls = [
    url(r'^export_data/', miscellany.export, name='export-data'),
    url(r'^resend-confirmation-email', miscellany.resend_confirmation_email, name='resend-confirmation-email'),
    url(r'^confirm-registration/(?P<confirmation_id>.+)', miscellany.confirm_registration, name='confirm-registration'),
    # And so on.
 ]

I can access those in a globally scoped object on the frontend, where keys are the URL names and the values are their corresponding endpoints:

> Urls.export_data()
"/api/emails/export_data/"

This is great for utility methods and such, but Vue’s single file components don’t have access to global variables (or, rather, variables declared on window.) This is for good reason — explicit rather than implicit! — but still means if I want to reference this object in the template code itself:I have to expose it as a computed property:

computed: {
    Urls() { return Urls; }
}

Sure, that’s only three lines, but it’s a pain in the ass feels unnecessarily repetitive. Thankfully, Vue offers a better way, which they refer to as instance properties:

There may be data/utilities you’d like to use in many components, but you don’t want to pollute the global scope. In these cases, you can make them available to each Vue instance by defining them on the prototype.

All you have to do is add Urls (or your object of choice) to Vue’s prototype method:

Vue.config.productionTip = false;
Vue.prototype.Urls = Urls;

// Do the rest of your setup.
new Vue({
  el: '#app',
  router,
  store,
});

And ta-da! All components now have access to Urls, so you can access it like so:

<a :href="Urls.export_data()">Export data</a>

Permalink

Side Projects: June 2017

Note Yeah, this is on here now. I decided having a separate site for Village Blacksmith's posts was dumb, and am now migrating everything over here. Graphs and such are missing for now, but I'll backfill them soon.

Victories

  1. Switching App Store ads back on for Barback was the correct move. Yay for repeatable, scalable (well, to a certain point) marketing loops.

  2. Even if I didn’t hit all my engagement targets for Buttondown, it’s in an infinitely better (read: it is actually stable now) place tech-wise.

Setbacks

  1. Wasn’t as aggressive about marketing Buttondown as I should have been. I have a public launch (aka submitting to Product Hunt and Hacker News and seeing what happens) in the calendar, though!

What’s Next

  1. Consolidating my web presence! I’ve given this site a facelift, am in the process of migrating Village Blacksmith posts to it, and then will clean that up so it’s more of a straightforward marketing page.

  2. Launching Very Cute, my silly React Native app for viewing cute pictures of animals. This is like 80% done and I just need to commit to getting it across the finish line.

Read more →

Agility

Jasdev had a great post on moving too fast:

But, Agile almost entirely misses the other side of the coin: regimented rest. We can’t expect teams to knock out a monotonically increasing amount of story points, sprint after sprint. Sometimes, you have to move slower now to move faster later.

Somewhat adjacent to this is the best advice I’ve ever received as a developer:

Focus on being the highest order derivative you can be.

As an entry-level developer, you’re a simple function: you take time as an input and produce business value as an output. 1

Then as you mature as a developer, your work doesn’t directly produce business value: it produces an increase at the rate at which others can produce business value. Suddenly, you’re a first-order derivative.

And then you go further than that, becoming a second-order derivative: transcending from velocity to acceleration. Your work helps others increase the rate of change.

And so on and so forth.

I think this trajectory of increasing abstraction — stretching out your objectives over a longer and longer timespan — is natural, and good. Don’t worry about how to accomplish this week’s work; worry about how to accomplish this year’s work. Decoupling yourself from short-term inputs, like speed and time, is good: it’s a sign that your concerns are larger than the day-to-day.

Put more succinctly: agility isn’t about distance — it’s about nimbleness.

Or, to quote Murakami in What I Talk About When I Talk About Running:

Sometimes taking time is actually a shortcut.


  1. Of course, there are other factors: your team, your codebase, your goals. But all of those are, at least starting out, constants. [return]
Permalink

Hugo's internal templates, demystified

In my effort to throw a new coat of paint on this site, I was diving into Hugo’s internal templates to see how to improve their builtin pagination. It was invoked by calling _internal/pagination.html, so I assumed the template was something along the lines of pagination.html.

Turns out all the internal templates are hard-coded in the Hugo library itself, in a file named template_embedded.go. Rather than filing a snarky comment on the wisdom of this approach, I thought it might be helpful to list them out, as it’s definitely annoying to read in the source file.

Read more →

iPad Things

As is tradition, it’s the time of year where folks have hot takes on iPads and the ~ future of computing ~. Here’s one from Joshua Topolsky:

This year’s spin on the age-old debate comes from iOS 11’s heavy emphasis on iPads and productivity. Most of the changes in iOS 11 seem great; none of them seem to address the existential issues that most folks talk about when they talk about the issues of productive work on the iPad.

I wrote about my experience with the iPad Pro last year, and I mostly stand by my conclusions. In particular, this passage rings truer than ever:

Still, though, I feel good using the iPad. “Delight” is the buzzword of the day when it comes to technology, and the iPad Pro doesn’t quite delight me: but sitting in a coffeeshop and using it to read or write gives me a vital sense of clarity and focus. This is important: as we drown ourselves in apps, in engagements, in vertices of various graphs, feelings of clarity and focus are rarer and more fleeting than ever before.

Using the iPad (or, perhaps more accurately, using iOS) feels absolutely frictionless. The iPad Pro, which I now use for reading, writing, and emails, albeit rarely, never confuses or surprises or angers me. It performs exactly as expected, unlike my MacBook Pro (which, despite its power and complexity, will randomly behave in bizarre and unexpected ways.)

Moreover, I think I’m just kinda bored of the narrative that the iPad has to replace the laptop or else it’s a failure. My iPad does iPad things really well! I love using it!

Maybe that’s not reason enough for market analysts, but it’s reason enough for me to continue owning mine.

Permalink

In praise of bloat

Ben Sandofsky, the creator of Halide (and erstwhile lead of Twitter’s iOS/Mac apps) wrote a worthwhile piece about getting his new app’s size to a mere 11MB. 1 There are a bunch of solid, universal pieces of advice (don’t create your own layout engine; compress and catalog assets), some trickier ones (avoid library bloat; eschew analytics), and a questionable kicker:

There really is one weird trick to lose size: focus on your customers.

I am skeptical about this last point in much the same way I am skeptical of folks saying the best way to lose weight is to eat healthy foods: well, sure, but what does that look like in practice?

Obviously focusing on your customers is very good, but I don’t think the truism of customer needs is paramount necessarily translates to slimming down your app is paramount.

This piece reminded me of an experiment Segment did last October, where they bought a random app and experimented with the app size to see how it affected downloads:

The first data point is insignificant (you can’t meaningfully compare download numbers between 2012 and 2016), but the latter three are pretty interesting, and suggest a linear (albeit tenuous) relationship between app size and install rate, to the tune of each megabyte costing the developer 0.45% of conversion rate.

That’s non-trivial! But if you’re an indie developer (or even just a pragmatic one), you have so much on your plate. You’ve got to build out features, you’ve got to iron out bugs, you’ve got to build out a marketing pipeline. All of these things are important, and some of these things might be solveable with a library or framework, which frees up your time to work on (potentially more important) other things.

Let’s take a completely arbitrary and abstract example of what I’m saying.

It’s four weeks before launch and you unexpectedly have a week of slack time. You can do one of these two things with your free time:

  • Removing a 5MB library and replacing it with a home-brew version (bumping up install rate by, according to Segment, ~2.5%)
  • Implementing a feature that bumps up install rate by 5%

The choice should be obvious, right?

Obviously nothing’s this clear cut: you’re never deciding between two things, you’re deciding between twenty things, and the time and value of these tasks are never quite as apparent as you’d like them to be.

But if you’re a small developer, every task you work on is a question of ROI: you only have so many battles you can pick. Sometimes fighting bloat is the right choice (and hey, it lets you write blog posts about how you fought bloat, which always makes for good marketing); sometimes it’s not. 2

I am skeptical that fighting app bloat is always the battle worth picking, but I think we can all agree that it’s at least a battle worth considering.


  1. Halide is great, by the way. I really love the app. [return]
  2. One caveat to this entire thing: I think the drop-off from hitting 100MB is definitely worth fighting for, since after 100MB users can’t download your app over cellular data. [return]
Permalink

What Vue needs next

Note This is gonna sound like a negative essay. Which it kinda is. But it's very much not a condemnation of Vue!

Vue is great. You should try Vue.

If I had written What Vue Doesn't Need it would be an incredibly long post! This is just things I wish were better about it.

I’ve been using Vue a lot recently on a few test projects, and most notably on Buttondown.

Buttondown’s frontend is 100% Vue: around twenty screens (which are themselves components) and around thirty miscellaneous components, tied together with Vuex and Vue-Router.

Overall, Vue is a really great tool, and the first word I’d use to describe it is pragmatic. Almost everything feels and acts sensible; there are tremendously few times that I am confused or surprised by how it works, which is legitimately novel (and wonderous) after the hours and days and weeks I’ve spent pulling my hair out dealing with random React and Webpack arcana.

Still, there are some bugaboos that I think arise from Vue’s current niche as a “lightweight” approach to creating a functional SPA, in much the same way that Flask carved out a niche as being a lightweight alternative to Django.

Read more →

Update: May 2017

Man, the momentum is really sucked out of one of these when the update for April came a mere two weeks ago! Victories Launched Buttondown! There are still things that need to be done: features that need to be written, edges that need to be sanded. But it’s here, and it’s live, and it’s being used. (Not by enough people, but more about that later.) Setbacks Sales.
Read more →
© 2017 Justin Duke • All rights reserved • I hope you have a nice day.