We should probably replace the minimum wage with a wage subsidy.

With the recent discussions of hiking the federal minimum wage, I came across a plan that might solve three MW-related problems:

  1. The MW is rarely enough to get by on.
  2. The MW eliminates (from the regulated market at least) all positions that create less value than the MW. Do you have a great idea for a job that someone might happily do for $7.00/hour? Sorry, that job can’t exist legally.
  3. Inexperienced workers or those with criminal records present more risks to employers, and the MW makes it impossible to offset that risk by reducing the starting wage a bit. This makes it hard for these folks to get a foot in the door.

Because of problem 1 (and because we make a value judgment on the individual and project that value onto our expectations of wages), we tend to only push the MW up, which just exacerbates problems 2 and 3. Then we paper over those failures by paying the unemployed to remain idle, which is bad for their health, their skills, and their community’s productivity. So if there never were a MW, it would sure seem like a bad idea compared to Morgan Warstler’s plan of just having the government pay the difference between the market wage and what society feels individuals need to get by on ($280/wk in his outline).

A particular flavor of wage subsidy, this plan would set up a second labor market where qualifying employers (almost any small business) would have access to workers for as low as $40/wk—low enough to create almost infinite demand for labor—but these employees would take home at least $280/wk (the “Guaranteed Income”), with the government picking up the difference.

The exciting thing here is this could instantly produce almost full employment, giving workers lots of choice of jobs and forcing employers to compete for even low-wage workers in pay and work conditions. The evidence seems to suggest that Germany’s wage subsidies (in the form of shorter work weeks) allowed Germany to have one of the lowest unemployment rates of the OECD countries during the recession and it probably cost less than the equivalent unemployment benefits, too. It certainly reduced the extremely damaging effects that unemployment has on individuals and families.

Warstler also suggests having employees and employers use an eBay-like ratings platform to improve information flow (the value of employees, the conditions/benefits of jobs, bad behavior of parties) within the market. This seems like a good idea, and sites like Glassdoor show there’s demand for it at the higher end of the payscale, but I have some doubts that it will make such a huge difference; I think it will still be weird and a bit dangerous to your working relationship to publicly rate your boss. Anyway, I don’t see why we can’t roll this out independently of GI.

Ultimately I think this plan—and all the other wage subsidy schemes—sound much better for workers than the current “if-you-can-find-work-at” minimum wage system, which seems as hopelessly flawed as every other attempt to artificially dictate prices.

A few other concerns with the plan:

  • Not all employers qualify for GI workers and I think the question of which can/can’t will be difficult to pin down. E.g. If I hire my neighbor to do all my chores and vice versa, we each end up pocketing $240/wk in subsidies. Rooting out these schemes would be tough. Warstler seems to think we don’t necessarily need to and that we might get valuable information from seeing how these pan out.
  • GI employers get workers for significantly less than non-GI employers, and I wonder what kind of market distortions that would create. The answer may be none.
  • The transition into GI could be chaotic, as overnight there’d be countless jobs to choose from and non-GI employers would have to react to this serious competition. We just have no idea what kind of jobs people will come up with, but every additional job would seem to improve the situation for workers.
  • How do GI workers get stable healthcare? Do they get access to a group plan? This could cause problems for workers wishing to move between the GI/non-GI markets.

If we’re stuck with a minimum wage, it would seem best to keep it as low as possible and boost/widen availability of tax credits like the EITC. Essentially this also works as a wage subsidy if by another name.

And can we just get rid of the awful “tipping” system/reduced wage for food workers, as if they’re for some reason especially deserving of having every night’s pay be at the whim of customers and dozens of other elements out of their control.

Git: Finish features before merging them.

There’s no perfect way to develop software and use source control because projects, teams, and work environments can vary so much; what works for a small office of employees might not for a loose group of part-time contributors spread across many timezones, as many open source projects are.

Jade Rubick is not a fan of long-running feature branches in git and—if I’m reading this right—argues for merging into master frequently, not waiting for an entire feature to be implemented. This is supposed to force the team to be aware of all code changes occurring.

While lack of communication about features in development can certainly be problematic, I think this is a sledgehammer of a solution. Taking this approach to its extreme, it might make sense to have all developers work huddled together so they can say what they’re working on in real-time, or all work on one workstation. My point is that using a workflow with high costs to address a communication deficit is not so great an idea.

My big fear of this workflow is that it eases the flow of incorrect/unwise code into production. Who reviews this code? What if it takes the whole codebase in a bad direction, but no one at the moment has time to realize that? I think the benefits of feature branches/pull requests are just huge:

  1. A branch frees the developer to experiment big and take chances without forcing the rest of the team down their path. The value in some big ideas will not be apparent looking at them piecemeal. Some of this work will lead to great things, some will be tossed away, all of it will be good learning.
  2. Likewise, the PR process can catch incorrect/unwise solutions before they’re merged into the product. This is huge. Some ideas sound great but you only realize 80% into the work that they’re unwise. If that work is sitting in a PR, you just close it and it can live on as a reminder to future devs who get the same idea. If not, you now have the job of shoehorning that code out. On the codebases I work on so many features have been improved/overhauled/abandoned by the review/feedback loop that it seems absolutely crazy to bypass this process. In an async distributed team, I think the PR is basically the perfect code review tool.
  3. PRs provide a great historical and educational record of what changes are involved in providing a certain feature, what all files are involved, etc. I’ve found that reading pull requests and merge diffs to be just as illustrative as reading source code. If a feature required changes in dozens of files over three weeks, how will I ever piece together the 6 commits out of 100 that were important?
  4. Feature branches make it a lot easier to revert a feature or apply it to another branch. For life on the edge I’ve built upon versions of frameworks with experimental branches merged in. If I regret this I can always generate a revert commit to sync back up with a stable branch.

All workflows have costs/benefits, I just think that the benefits of not merging feature branches until they’re really ready are huge compared with the costs Jade described.

My hunch is there must be better ways to keep a team aware of other work being done on feature branches. E.g. Make pull requests as soon as the feature branch is created and push to it as you work. That way team members can set aside time to check in on pull requests in progress and provide feedback.

I agree with Jade that feature flags can be a great idea, but that’s mostly orthogonal to source control workflow.

 

Capitalism has failed as a brand

The word needs to be retired. It gets evoked by some to mean a type of dog eat dog libertarianism and by others as a shorthand for the abuses of corporations and unjust outcomes of markets.

I see the idea as the simple preference that people be free to participate in voluntary markets, not be forced into labor, and be allowed to own property and build wealth. This is real basic stuff that almost everyone agrees on because history showed all the competing ideas led to mass poverty and starvation.

The real important questions of today are how a government deals with the fact that people don’t live in bubbles, they don’t agree on things, they can become physically or mentally ill, they can misbehave under the influence of substances, they can make poor decisions and have bad luck, they take advantage of others, they can use their wealth to buy advantages and monopolies, and they can be born into bad situations by no fault of their own.

JSMin’s classic delimma: division or RegExp literal

JSMin uses a pretty crude tokenizer-like algorithm based on assumptions of what kind of characters can precede/follow others. In the PHP port I maintain I’ve made numerous fixes to handle most syntax in the wild, but I see no fix for this:

Here’s a very boiled down version of a statement created by another minifier:

if(a)/b/.test(c)?d():e();

Since (a) follows if, we know it’s a condition, and, if truthy, the statement /b/.test(c)?d():e() will be executed.

However, JSMin has no parser and therefore no concept that (a) is an if condition; it just sees an expression. Since lots of scripts in the wild have expressions like (expression) / divisor, we’ve told JSMin to see that as division. So when JSMin arrives at )/, it incorrectly assumes / is the division operator, then incorrectly treats the following / as the beginning of a RegExp literal.

Lessons: Don’t run minified code through JSMin*, and don’t use it at all if you have access to a JavaScript/Java runtime.

*Minify already knows to skip JSMin for files ending in -min.js or .min.js.

Destroying the Venezuelan Economy

It’s sad to watch Venezuela’s economy being crushed by its president, Nicolás Maduro. Venezuela’s real inflation is 280% a year, but the government is trying to deny that by imposing price ceilings and artificially limiting access to foreign currency. The result is massive shortages made even worse by the fact that it’s more profitable to smuggle the rationed goods back out of the country.

But the scariest is that Maduro recently ordered a military-backed looting of one of its big box chains. Those stores certainly won’t be able to re-stock at the government-set prices, so basically Maduro just directly destroyed that business, and all other retailers know they could be next.

Normally this inflation would make Venezuela’s products and labor force more competitive and spur foreign investment to stabilize the economy, but the Venezuelan government can no longer be trusted. If Maduro is re-elected, Venezuela will continue sinking towards a completely government-controlled state, like Cuba. But at least it will be easier to escape from.

Using BINARY in a MySQL IN Expression

With the default collations in MySQL (e.g. utf8_general_ci), strings will be matched case-insensitively:

WHERE col IN ('IT', 'Ruby') will match “it” and “ruby”.

For case-sensitive matches, each string must be preceded by the keyword BINARY:

WHERE col IN (BINARY 'IT', BINARY 'Ruby')

Caveat: I would guess that BINARY affects the matching of strings with combining characters (same character, different byte representation).

When Reasonable, Return Early

When you have a function or piece of code that must handle several different cases, I find it much better to eliminate special cases using return or throw at the beginning. (“returning early”).

if (!input.isValid()) {
    throw new InvalidInputException();
}

// handle input (20 lines)

Several advantages here:

  1. It frees our mind from worrying about those cases as we read the rest of the function. Programmers, as humans, have limited mental stacks, and if we’re reading a function that must handle several cases, each of those cases must be held in our memory until we see the code that handles them.
  2. It simplifies the remaining code, since it’s handling a smaller set of cases.
  3. It compartmentalizes the code into: “handle special cases, then handle the common case.”
  4. It keeps the code that handles special cases close to the checks for those cases.
  5. The primary piece of code stays at the root indent level.
  6. Diff views stay simple when adding/removing special conditions (it does not introduce big indenting changes across many lines).

In fact there’s (what I consider to be) an anti-pattern that involves checking for special cases early, but instead placing the meat of the function in the if block, followed by an else block to handle the special case:

if (input.isValid()) {

    // handle input (20 lines)

} else {
    throw new InvalidInputException();
}

Notice how the handling of the error can now become separated from the cause of the error, and the meat of the code now must be indented. This anti-pattern gets obviously worse the more conditions you must test for:

if (input1.isValid()) {
    if (input2.isValid()) {
        if (input3.isValid()) {
            if (input4.isValid()) {

                // handle input (20 lines)

            } else {
                throw new InvalidInputException('input4 is bad');
            }
        } else {
            throw new InvalidInputException('input3 is bad');
        }
    } else {
        throw new InvalidInputException('input2 is bad');
    }
} else {
    throw new InvalidInputException('input1 is bad');
}

This code is hard to read, hard to edit, and harder to review when changes occur to the conditions:

  1. The invalid handling code appears in the reverse order that the inputs are checked.
  2. The invalid handling code is very far from the conditions (you have to lean on the IDE to see where the braces line up).
  3. The meat of the function starts off 4 indents over.
  4. Adding/removing validity checks is a huge pain that involves re-indenting a bunch of code.
  5. Change diffs can look really messy as indent levels are changed.

Code with a lot of special cases/conditions probably needs to be refactored to separate validation from the processing of the input.

There are certainly situations where returning early is not an obvious win (hence “when reasonable”). This often happens when you have a return value that contains complex state, or some statements must be executed before every return/throw statement.

Apache mod_cache and mod_rewrite: Danger

I solved a very strange bug today where mod_cache kept returning a particular cached file for seemingly every URL on a site.

After using LogLevel debug, I finally realized that mod_cache does not store content by the request URL, but rather by the final URL after RewriteRules have been processed.

This PHP application was using a common RewriteRule to map most requests to a single script, but the full request URL was not being copied into the rewritten URL (the script was just relying on $_SERVER['REQUEST_URI'] to route the request). The result is mod_cache considered all URLs the same, and it was only by some magic of session cache-busting headers that the app managed to function at all. Internally mod_cache was just churning that single cache file over and over.

The simple fix was to make sure the full URL path ended up in the internal URL:

RewriteRule ^(.*)$  index.php/$1 [L,QSA]

Chords: “Taramasalata” by Eggstone

V)
    Em   G#+/B#  C#m    G#m      F#m   A     F    Dm
    2      2     2      2        2     2     2    2

    F#m    B     C#m    A  G#m   C#m   A  B
    2      2     2      1  1     2     1  1

    Em   G#+/B#  C#m    G#m      F#m   A     F    Dm
    2      2     2      2        2     2     2    2

    F#m    B     Dm     C#m      G#m   A  B
    2      2     2      2        2     1  1

    Em   G#+/B#  C#m    G#m      F#m   A     F    Dm    A
    2      2     2      2        2     2     2    2     8

C)  
    E      B/D#   G#m   F#m   G#m   F#m   C    D
    2      2      2     2     2     2     2    2

    E      B/D#   G#m   F#m   G#m   F#m   C    D
    2      2      2     2     2     2     2    2

    E        C#m7     Amaj9    F#m9
    4        4        4        4

    E        C#m7     Amaj9    F#m9
    4        4        4        4

    E        C#m      F#m7     C    D
    4        4        4        2    2

on YouTube.

Character Encoding Bug of the Day

Today I had one of those bugs that starts out looking simple and keeps going deeper and deeper. Video service Kaltura has a plugin for Moodle, that just stopped working one day (no changes on the server).

  • It’s throwing an exception because an expected element isn’t in the page.
  • Oh, the element’s supposed to be delivered by XHR from the plugin.
  • But the plugin’s code is generating correct markup…
  • Why is Moodle’s function to serialize an array into a JS function call returning null for that markup?
  • json_encode is converting the markup string to null?
  • Because json_encode is choking on invalid UTF-8.
  • Because the markup has a right single quotation encoded in Windows-1252 :(
  • And that string is coming from the Kaltura API.

So over 2 years ago someone named a video player Jim’s Test Player and over the weekend Kaltura’s API started returning that single quote in Windows-1252. We removed the quote from the name and the problem disappeared.