For sixty years, we have called the threat of totalitarian surveillance ‘Orwellian’, but the word no longer fits the threat. The better word now may be ‘Californian’. A truly sophisticated system of social control, of the kind being pioneered in China, will not compel obedience, but nudge people towards it. Rather than censoring or punishing those who dissent, it will simply make sure their voices are not heard. It will reward complacent behavior, and sideline troublemakers. It’s even possible that, judiciously wielded, such a system of social control might enjoy wide public support in our own country.
But I hope you will agree with me that such a future would be profoundly un-American.
As all tech industry observers are aware, the twin pillars of a successful startup are cost shifting (i.e. user generated labor) and regulatory arbitrage (i.e. tax avoidance).
For years, Facebook had its users write its content for it, and Amazon has avoided sales tax. Google’s famous “PageRank” algorithm gets every website in the world to do the hard work of ranking links for them, and Apple successfully avoided billions of dollars in taxation at the cost of a few awkward meetings. The greatest unicorns do both, like Uber and AirBnB, which avoid fare taxes and hotel taxes respectively, while pushing the costs and risks of car and property ownership onto their “partners.” YouTube and Instagram have even managed to work around child labor laws by the simple expedient of not paying their content producers. It’s win-win!
Looking at this competitive landscape, it is clear that if The Ethically-Trained Programmer is ever going to “exit”, I need to find a novel tax to scofflaw and a way to force my inventory costs onto my “partners”.
Fresh graduates often push for a rewrite at the first sign of complexity, because they’ve spent the last four years in an environment where codebase lifetimes are measured in weeks. After their first unsuccessful rewrite they will evolve into Junior Engineers, repeating the parable of Chesterton’s Fence and linking to that old Joel Spolsky thunkpiece about Netscape3.
Be careful not to confuse this reactive anti-rewrite sentiment with true objections to your particular rewrite. Remind them that Joel wrote that when source control meant CVS.
3. The real reason Netscape failed is they wrote a dreadful browser, then spent three years writing a second dreadful browser. The fourth rewrite (Firefox) briefly had a chance at being the most popular browser, until Google’s rewrite of Konqueror took the lead. The moral of this story: rewrites are a good idea if the new version will be better.
The Joel article bugs me for a number of reasons, and the fact that his core example is totally demonstrably historically wrong is one of them.
Rewriting software is something you should only do if you can answer the question, “Why will it be better this time?”
New programmers to a code base think the answer is “because the last people working on this were idiots.” Sometimes that’s true! If you’re inheriting, e.g., some PHP code written by people who weren’t really web developers but just learned by copy-pasting, you might be smarter-enough to have a rewrite work. However, that’s the exception, and typically, you’re not any smarter than the people who wrote the code in the first place, so you’re not going to do any better.
Another answer that’s possible but unlikely to be correct is “they made bad technology choices.” Yes, some technology choices really are so bad that correcting them can make a difference, but moving, e.g., from Rails+MySQL to Node+Mongo is unlikely to make things better.
A good answer is “the business requirements they built this product for no longer apply.” For example, Microsoft Office vs. Google Docs or iTunes vs. Spotify. The former product in both cases is more robust, more complete, technically capable of doing it all, but the latter product by virtue of not having to do things that are no longer necessary can be radically simplified.
Anyway, John Millikin is correct: no haunted forests!
Way back in 2013, I wrote Google Go: The Good, the Bad, and the Meh, which means I now have more than the job-recruiting-required “at least five years of experience” using Go. But I don’t want to write about that. I want to write a little about a baker’s dozen of the many small tools I’ve written in Go to scratch personal itches since then.
Most of these programs were the result of some passing enthusiasm, now mostly forgotten. They tend to be work-adjacent but not actually part of my direct job responsibilities. (That is to say, I was never asked to write any of these by a boss, and probably my bosses would see them as a waste of time if they knew about them.) Some of them I use a lot, and others I wrote and then forgot about completely. Mostly though, they’re just fun to write and satisfying to look back on.
Note: At my old job, I helped write up our Git standards, but I lost access to that document when I changed jobs. To keep track of my thoughts on Git in perpetuity, I am posting them publicly here.
Git is the democracy of programming: it is the worst tool for version control, except all those other tools that have been tried from time to time. Among other problems, Git’s command names are obtuse (what is a “rebase”?) and non-orthogonal (how is “resetting” different than “checking out”?), and Git generally impedes the creation of an accurate mental model, but without understanding its underlying directed acyclic graph, one can’t move from beginner to intermediate user. Still, it is a necessary tool in every developer’s toolbox, and following good Git practices leads to smoother, more productive development. This guide assumes you already know how to use Git and discusses some of the higher level issues around standards for collaboration.
My friend and former colleague Jason Goldstein has a great article up about the problems with Python’s asyncio framework.
For what it’s worth, when I was at PBS, a different coworker and I tried to do a test project to learn how to write asynchronous code. We wrote scripts in both Python 3 and Go that would go onto Github, get a list of users on our project, and download their personal repo information concurrently. When we finished, we compared the apps to see the strengths and weakness of the languages.
Both apps ended up working (although the Python app cheated in a few ways, for example by ignoring paginated responses), but I found the Go app to be easier to write than the Python app, even though it was significantly more verbose. One of the biggest problems for the Python app was just finding documentation that I could understand and apply. In Go, the main problem was that you’re writing the concurrency scaffolding yourself, so it’s easy to write a spaghetti mess if you let yourself. In Python you more often run into the problem that doing something concurrently is a pain, so you do it in a blocking manner even when you shouldn’t. For example, really you should be collecting links asynchronously and adding new links to a queue as you go, but it turns out to be easier to do things one at time, even if that’s less efficient.
Update: This post is obsolete as of Hugo 0.43. See Regis Philbert’s great summary of best practices instead.
Hugo is a great static site generator written in Go. I use it for this blog. Its advantages are that it’s very fast, very easy to set up, and very flexible, but its disadvantage is that it doesn’t have the mature community support that Jekyll has. One example of that is that Hugo has no particular recommended route for managing a static asset pipeline. In this post, I’d like to explain how my personal pipeline works to see if it can help other Hugo users.
At its Worldwide Developers Conference on June 5, Apple announced that one of the tentpole features of macOS High Sierra will be anti-ad tracking technology:
Intelligent Tracking Prevention in Safari uses machine learning to identify and remove the tracking data that advertisers employ to follow users’ web activity.
At first glance, this may seem to be bad for Google and other online advertisers. However, that perception is mistaken.
Camille Fournier has a great article on How do Individual Contributors Get Stuck?, but I’d like to focus today on the opposite question: How do programmers get into flow?
My theory is that there are three different idealized programmer personality types, each with its own strengths and weaknesses. Before you can get into flow, you have to know what kind of programmer you are, so that you know what kinds of things put you into the flow. Not everyone has the same strengths, and that’s okay. In fact, for a good team the more diverse your strengths the better! If everyone on the team has the same strengths, that means they have the same weaknesses and the company may have major blindspots as a result. So what are some strengths and weakness of different kinds of programmers?
Programmers who just want to get things done
Some programmers are happiest when they can see concrete results of their work. Sure, the code they end up producing has some rough edges, but they made something you can see and touch today. These programmers get frustrated when their work has no visible output and seems like it’s just rearranging code that already works.
- Pros: Work fast
- Cons: Work can be sloppy and hard to extend
- Bored when: Refactoring or stuck on a hard problem
- Best use: Getting the prototype 90% done in one week (the other 90% will take a team of a dozen six months)
Programmers who just want to solve hard problems
For some programmers, the harder the problem is, the harder it is to resist. Sure, they were supposed to change all the borders from light grey to dark grey two weeks ago, but they got a little distracted by implementing a ground up rewrite of the rendering engine in OCaml and assembly language, so that will have to wait.
- Pros: Will solve a problem you never thought possible to solve
- Cons: What they produce can be hard for anyone else to grok
- Bored when: Tediously gluing bits of code together
- Best use: Creating the core algorithm that no one else on the team understands but gives your company the edge
- Spirit Languages: Haskell, Clojure
Programmers who just want to create the perfect thing
Some programmers are obsessed with beautiful code. They can’t believe that the code base uses CamelCase and snake_case in the same project. They’re personally offended that a method call runs in O(N2) time instead of O(N log N). They’ve started a secret branch of the repo to fix all the whitespace problems and rewrite the API, but they have to do it on their lunch break because the client just wants to ship a new feature.
- Pros: Create maintainable, performant code
- Cons: Prone to bikeshedding and wheelspinning redesigns; suffer from fear of a blank canvas
- Bored when: The inherited codebase is ugly but there’s no time to fix it
- Best use: Refactoring work done by the other kinds of programmers; bug hunts
- Spirit Languages: Python, Go
Of course, in reality, no one is really just one kind of programmer. We all mix and match different personality elements on different days. But it could be helpful to know yourself and know what kind of programmer you tend to be the closest to in order to utilize your talents best.
So… what kind of programmer are you?
go generate command was added in Go 1.4, “to automate the running of tools to generate source code before compilation.”