If you blog it they will come?

Tuesday, December 30, 2014

Technology as a broken promise

This Louis C.K. clip is often trotted out if/when folks complain about technology and it's got the wrong message:


The gist is, with all the things technology lets us do that we couldn't do otherwise, why do we get so upset when it doesn't work to our liking, instead of amazed at how it works it all? Stop whining, you're spoiled, etc.

Technology is held up to a high standard by spoiled whiners because that's how it's sold to us: that it will make our lives so much easier, and better.

Complaints about it result from a mismatch of expectations (it's less than what was promised and paid for). 

If someone promised to pick you up from the airport, and you paid them for it, and they showed up hours late...it's not much of a consolation to say, "well it's amazing that people can even drive anywhere at all.  And wow, airports are neat." 

Thursday, May 9, 2013

NSURLConnection returns 200 when the connection is closed

Not what I was expecting! Let me show you; here's a testserver.go to hijack and close the connection:

package main

import (
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
}

func main() {
    http.HandleFunc("/", handler)
        http.HandleFunc("/hijack", func(w http.ResponseWriter, r *http.Request) {
        hj, ok := w.(http.Hijacker)
        if !ok {
            http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
            return
        }
        conn, _, _ := hj.Hijack()
        conn.Close()
    })
    http.ListenAndServe(":8080", nil)
}

Here's what it looks like via curl (after running "go run testserver.go")
~  ᐅ curl -v http://localhost:8080/hijack
* About to connect() to localhost port 8080 (#0)
*   Trying 127.0.0.1...
* connected
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /hijack HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
> Host: localhost:8080
> Accept: */*
> 
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server
* Closing connection #0

Now let's see what NSURLConnection's sendAsynchronousRequest completion handler reports:
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8080/hijack"]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    NSLog(@"%d", [(NSHTTPURLResponse *)response statusCode]);
    NSLog(@"%@", error);
 }];

--
2013-05-09 14:41:00.221 testserver[59315:c07] 200
2013-05-09 14:41:00.222 testserver[59315:c07] (null)

There you have it! Connection closed results in a 200 http response code and no error!

Wednesday, December 12, 2012

Tourist

Powell Street is jam packed with tourists getting their first glimpse of San Francisco's cable cars and behemoth retail stores on their way to Union Square. I'm stepping out of the office because I need a break, or better yet, a change in perspective.

I've lived here three years and see the tourists' sights as part of my daily commute. When I witness SLRs snapping family vacation photos with the backdrop of Abercrombie's double doors, judgment creeps in.

But, I didn't take this walk to judge tourists. Instead I attempt to cast myself into their mindset: to have come a long way to arrive in a place that is new and novel, to have arrived somewhere with the intention of marveling at marvels (commonplace now to me).

I imagine that I too am a tourist, and delude myself into thinking I've been traveling for hours and I close then open my eyes, and I as a tourist I think: "I've finally arrived, I'm here! There's so much to see, this amazing city, and it's mine to explore, etc."

"I've finally arrived, I'm here!"

There's instantly a rush of adventure, and wonder again as I gawk at the bustlings and buildings of Market Street.

It's possible to take this a step further.

It's more abstract, but I next imagine myself as a tourist though time AND space, one who has been traveling not for hours, but for years and years. And what a long, strange road it's been to this very precise moment, where I've finally arrived. So much time and effort, but now I can say, "I'm here."

This isn't merely a mental stress ball technique, it's a frame of mind I try to keep and access anywhere, anytime (not easy).

Perspective shifted, earnestness in hand, ready to encounter the next destination on my weird lifelong tour, I will walk around a bit more then return to cranking out code.

Wednesday, November 21, 2012

A lifetime of supporting roles


There are two types of people (for the sake of argument): those who thrust themselves into the spotlight, and those lean away from it.

I'm the latter. Maybe it's timidity, but perhaps not...

In sports, I was usually the defender, because I was better at reading an attack than creating one. But in music, I started off playing guitar, then picked up the bass so I could join a band with a talented singer/songwriter who needed a bass player.

In my work, I started off as a tester. Now I am a feature developer now but my comfort zone is at companies which have recently realized significant success and are building on it. I have not stuck my neck out at early, unproven startups.

Sometimes I want the limelight. I imagine a swift sprint upfield to score, stepping up on the monitors for a facemelting guitar solo, or launching some product in my free time that snowballs into an unprecedented one-man Silicon Valley success story, complete with magazine covers and a feature film.

But sticking to the shadows doesn't mean that you concede the act of creation.

In soccer, stopping an attack means setting the pace and the direction of the counterattack. And bass players know (few others do) that they are the ones really controlling the song  -- the tempo, energy, the complexity and direction.

And the developers who join a company well after its business model is demonstrated must be roadbuilders who not only pour asphalt over dirt roads, but design intersections and plan highways.

The world needs people who sparkle in the spotlight, but to mix metaphors, it's people like myself who may not always blaze the trail, but are ultimately steering the ship.

Thursday, August 9, 2012

jwz quote that's stuck with me

I could have benefitted from internalizing this quote when I was starting out, I was one of the skittish ones.:
"I think that's one thing that's really important is not to be afraid of your own ignorance. If you don't understand how something works, ask someone who does. A lot of people are skittish about that. And that doesn't help anybody.  Not knowing something doesn't mean you're dumb--it means you don't know it yet." --jwz (from Coders At Work)

Friday, June 29, 2012

List of shortcuts to change in XCode

Some shortcuts in XCode don't make sense at all, some are for features I never use, and some are awesome but off by default. I'll update this periodically.

Shortcuts to enable/simplify:

  • Select Word (Selection)
    • This is close the vim-ism "Change Inner Word" (ciw). Saves a lot of cursor hopping.
    • Ctrl+W  
  • Move Focus to Next Area
    • makes it easier to hop between the split panes if you don't want to deal with the Cmd+J navigation view.
    • Cmd+Option+up arrow

Shortcuts everyone should disable:

  • Ctrl+P to print
    • when was the last time you needed to print anything in Xcode?

Shortcuts I have no use for:

  • I never use code folding
    • It's too much manual work to fold and unfold everything
    • If you need code folding, your methods are too long.
    • If you want to find functions quickly, just hit Ctrl+6 and start typing its name

Friday, June 1, 2012

iOS Security Overview

I recently read Apple's iOS security overview which outlines the various security measures present on iOS devices.

It's a fairly short read at under 20 pages and it's great stuff to familiarize yourself with if you're developing on the platform. Here is a summary / some limited thoughts (I don't know much about security):

  • A lot of Apple's security measures are possible due to novel hardware solutions
    • The ARM processor's Execute Never which marks pages as non-executable
    • AES 256 crypto engine and SHA-1 are built into the file system and implemented in hardware, which drastically reduces the overhead of encrypting everything
    • Novel ways of wiping sensitive data that would otherwise linger in flash memory
    • UIDs are not readable by software or firmware, yet still used as input to crypto
A lock inside a lock inside a lock

  • The file system encryption is of an onion nature
    • File metadata is not available all the time. This is to restrict access when the device is locked or interrupted by a phone call, etc. and availability rules are described by a files' class
    • File metadata is encrypted. The file data itself is encrypted too, and that key is only available after decrypting the file metadata (that's right, each file has its own key)
    • Did I mention that the file class which points to the file's metadata is also encrypted? See image above
    • It's fast to remote wipe your device: just destroy the top level keys and nothing else on the filesystem is accessible
  • Every encryption/security algorithm I've heard of is deployed here (ok not ROT13):
    • Address space layout randomization
    • Lots of certificates to authenticate trusted code
    • Asymmetric elliptic curve cryptography (Curve25519)
    • Yarrow
    • PBKDF2
    • SSL, VPN, etc.
    • AES and SHA-1
    • escalating time delays: it'd take years to brute force a short password
  • I don't understand keybags yet
    • My eyes glazed over and it sounds too similar to teabags

Monday, March 26, 2012

"We have a false model of what thinking is"

This is a tasty excerpt from a great interview with David Graeber:

We have a false model of what thinking is. Because you can't really think by yourself, can you? You have to create someone else in your mind to explain things to, and to have an imaginary conversation with. This idea was inspired in part by the philosopher of cybernetics, Andy Clark, who proposed something he calls the extended mind hypothesis. Basically, the argument goes like this: Say you're doing long division on a piece of paper instead of doing it in your head. Clark asks why the piece of paper is not just as much a part of your mind while you're doing that calculation as the part of your brain that's doing the math. He says there's no reason at all.There are a million similar examples that philosophers like to trundle out—you have a bad memory so you write everything down. Is that piece of paper then part of your mind?

"Mind" isn't "brain"— the brain is just an organ; your mind is the dynamic interaction of various moving elements that culminates in thought. Philosophers like Clark are willing to take that argument this far, but the question that never seems to occur to them is this: when you're having a conversation with someone else, is their mind part of your mind? Nowadays, many philosophers of consciousness like to note just how razor-thin this thing we call "consciousness", that self-aware part of our mental operations, really is. The average person can rarely hold a thought for more than three or four seconds, eight at the most, before the mind wanders. It's very unusual to be fully conscious for more than a tiny window of time. That is, unless you're having a conversation with someone else, in which case you can often do it for long periods of time, especially if the conversation is with someone you find particularly interesting. In other words, most of the time we're conscious is when we're talking to someone else, or otherwise interacting intensely; during moments in which when we're not clear whose mind is whose. So consciousness is interactive, it's dyadic or triadic. It's a fallacy to imagine that thinking is something you largely do alone. On some level, of course, we already know that. But I don't think we've even begun to explore the full implications.

Monday, March 12, 2012

error: unknown warning group

I try and write about really frustrating issues that I manage to figure out or interesting problems that I solve in hopes that it will help other poor developer souls who would otherwise be without a guiding light. Here's an Xcode-inspired episode of the former.

I decided to see what would happen if we moved our iOS project to Xcode 4.3 and it nearly went without a hitch except that I spent several hours trying to figure out why our rake scripts weren't working.

...actually let me back up a step and describe a couple of tools we use.

We use Cedar to run automated tests ("Specs" to follow the parlance of rspec), and one Cool Thing is that they can be run in Xcode or from the command line using rake.

Another Cool Thing, or at least a Thing That Used To Be Cool Before Upgrading Xcode, was our use of PivotalCoreKit to make spec writing more convenient.

PivotalCoreKit uses (abuses?) the dynamic-ness of Objective-C categories to override existing class behavior and suppress NSUrl from making an actual network connection, for example. The advent of 4.3 discourages this sort of flippancy and will issue a warning/error by default, which the newest commit of PivotalCoreKit suppresses with pragma preprocessor macros.

Now is where the wonkiness really starts. Running our specs from Xcode went swimmingly after updating PivotalCoreKit, but building the same spec target from the command line would fail with errors such as:


Externals/PivotalCoreKit/SpecHelperLib/Extensions/UIWebView+Spec.m:4:34: error: unknown warning group '-Wobjc-protocol-method-implementation', ignored [-Werror,-Wunknown-pragmas,2]
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"


What the heck??? They are the same target!

But after comparing the build outputs of Xcode 4.3 and the command line spec script, they were drastically different. For one, I could not get the command line to compile with SDK 5.1. Despite my various environment variable tweaks, the -isysroot parameter pointed firmly at yesterday's SDK.

Here's how I (eventually) fixed it:

  • I ran
    xcodebuild -version
    and found out I was *still* on Xcode 4.2 (I had decided not to delete it yet)!

  • I warily installed the latest command line tools (Apple: "The command-line tools are not bundled with Xcode 4.3 by default. Instead, they can be installed optionally using the Components tab of the Downloads preferences panel")

  • After installing the latest command line tools I was still on 4.2. After digging in /usr/bin/ to ensure that xcodebuild had in fact been updated, I serendipitously discovered
    xcode-select
    ...

  • sudo xcode-select -switch /Applications/Xcode.app/

  • xcodebuild -version
    is now 4.3!!

  • All is well is command line specs land



So here I am 4 hours later to administer the following advice:
--Delete old versions of Xcode when installing the latest if possible
--Otherwise, remember always: xcode-select -version

Sunday, February 12, 2012

This weekend was one well spent as I participated in Music Hack Day SF for the first time.

I initially partnered with Kelly Dunn, who has been working on a project to send OSC messages triggered by Sifteo cube user interaction events (more here: Siftosc).

From 2pm on, we toyed with the idea of creating an air drum setup, which treats the cubes as shakers or drum sticks, using Renoise's built-in OSC server. Ultimately this didn't pan out since we weren't able to trigger note events without preprogramming a beat into Renoise, but Kelly did get the shaker implementation working and went on to do a crazy hack where he used the Sifteo cubes to manipulate his monome controller .

I moved on to experimenting with PureData on iOS with libpd a good 3-4 hours later. I got a basic grid-based synth working, but was unhappy with the sound quality on the iPhone simulator, which is a known issue with libpd. I learned a lot about puredata and could have potentially demoed the app despite its annoying distortion issues, but since I didn't have a device to deploy to and it was still before midnight on the first day, I decided to start over with something else.

Looking for examples of manipulating microphone input on iOS, I found aurioTouch, a powerful demo app created by Apple to showcase audio processing with the microphone. I started tinkering with this but was starting to feel fatigued from wrangling libpd and wanted to move on from audio low level synthesis.

I took an hour break and decided to work on a zany, assuredly demo-able project.

Enter sideTrack. It's a Rube Goldberg-esque python script which leverages many different APIs to mutate an initial seed song many times over until it eventually plays a completely unpredictable song, while speaking the nonsensical phrases it uses to perform each search.

Similarly to how one might fall down a wikipedia hole, this python script uses random lyrics, geography, song titles and more to repeatedly mutate different searches into a track with a spotify url, which is finally played via AppleScript after exceeding a depth limit parameter.

It leverages APIs from MusiXMatch, EchoNest, Spotify, and google maps to mutate the songs at each depth level. It worked and the results were always surprising. I was grateful to receive generous prizes from spotify and 3scale.

Here's a screen cap of sideTrack:


Regardless of frustration from my numerous aborted project ideas, music hack day was a ton of fun. I met some very talented and passionate folks, and eagerly await the next music hackathon.

Tuesday, January 31, 2012

brief notes from graeber talk

30% of the world's mined gold exists underground Manhattan, and you can take tours!
"You can tour the trading rooms, the museum and the Fed's vault, which holds 900 tons of gold."

In many ways, war gave rise to capitalism and not vice versa.

Modern coinage and money arose largely out of the enormous challenge of feeding and paying a medieval army.

Kings would print money and distribute it to their populace, then ask for some of it back. Markets arose out of the need to pay this tax, and it benefitted soldiers who had lots of spending power. So it was governments creating the markets, not regulating them once they'd come to fruition.

Additionally, it was unwise to do business with armed passerbys with IOUs, so cash was the logical material of exchange, especially since the soldiers had most likely recently looted some gold/silver/whatever on their way to visit your humble market.

Precise exchange rates were born of violence, for instance to stem a blood feud, exact legal damages were conferred, and substitutions were made when necessary. Otherwise, most trades were conducted with rough equivalency, with shame or death as a possible punishment for underhanded-ness.

Also the anarchism of Barcelona

also the war debt that is circulating from the king of england and the british bank notes that act as IOUs

Friday, December 16, 2011

The power and insanity of C++ templates

exhibit 12941b: analog literals


it is possible for this to compile as valid c++ code:

assert( ( o-------------o
|L \
| L \
| L \
| o-------------o
| ! !
! ! !
o | !
L | !
L | !
L| !
o-------------o ).volume == ( o-------------o
| !
! !
! !
o-------------o ).area * int(I-------------I) );

here's more: analog literals
still more: yep, they're turing complete

why, bjorne, why?

Monday, November 21, 2011

Don't use defaultCStringEncoding

It isn't exactly news that this innocuous-sounding parameter is "considered harmful."
But this fact needs a bit more SEO-juice, so here's another voice speaking out against defaultCStringEncoding:

(from NSString.h):


/* User-dependent encoding who value is derived from user's default language
and potentially other factors. The use of this encoding might sometimes be needed
when interpreting user documents with unknown encodings, in the absence of other hints.
This encoding should be used rarely, if at all. Note that some potential values
here might result in unexpected encoding conversions of even fairly straightforward
NSString content
--- for instance, punctuation characters with a bidirectional encoding.
*/
+ (NSStringEncoding)defaultCStringEncoding; //Should be rarely used

Friday, April 1, 2011

write about a song in 400 words or less

Coast to Coast is the first track on Elliot Smith's final, posthumous album "From a Basement on a Hill," and it sets the tone for the rest of the album: disjointed, dense, fraying and beautiful.


http://www.youtube.com/watch?v=bAvqZsRhjwk&fmt=6

Coast to Coast begins with a portion of the song played in reverse. Enter twin lumbering drum tracks and an out of tune slide guitar lead. I've listened over 50 times and just now realized that Elliot's whistling along with the guitar track. His first line: "Last stop for a resolution."

The lyrics are juvenile, but cognizant and self-examining. Elliot has no new ideas and is therefore useless to those who are expecting more (including you!). Instead of deliberate invention, he takes a "kitchen sink approach," and shovels all of his recording and songwriting reserves into the studio cauldron (did he know beforehand that this would be his final effort?).

This "kitchen-sink" approach explains why there's at least 3 guitar tracks, a piano track, a distorted bass, 2 drum tracks, 3 separate vocal tracks, several additional "background" tracks featuring a lightning-speed poetry reading (and whistling). It's chaotic, but its beauty is evident in the way "Coast to Coast" grows and reveals itself with every subsequent listen.

At any moment, the wheels could detach from the wagon and the barely-together instruments which compose the song could careen into the abyss. Yet "Coast to Coast" marches ahead with minor regard for refrain or repetition, as Elliot bemoans that he's "got no new act to amuse you." Its structure is unconventional, and the rapidity of changes suggests a songwriter who is easily bored, or seeking to outdo himself. The droning piano, which would normally have a centering effect, somehow edges us closer to the brink.

At around the 4 minute mark, the poetry track which was submerged in the mix bubbles up. Is it the outside world leaking in? The spoken words supplant us from a musical trance, especially if we reacted to them by yanking off our headphones.

As the instruments slide into a black hole, these voices take over, and the track ends. We missed the last stop; nothing is resolved.

Tuesday, November 23, 2010

Here's a fun quote about AI

JORDAN POLLACK
Computer Science and Complex Systems Professor at Brandeis University

A persistent belief is that human symbolic intelligence is the highest form of intelligence around. This leads directly to both creationism and good old-fashioned AI which seeks to model cognition using Lisp programs.

Evolution can design machines of such great complexity that the space shuttle with half a million parts looks like a tinker toy construction. In order to explain the design intelligence of evolution, most Republicans are convinced that a superintelligent creator was involved. Developmental intelligence which manufactures machines with 10 billion moving parts without any factory supervisors is another area where nature outstrips the best human performance. Immunological Intelligence, telling self from non-self, is another AI-complete problem. And human intelligence itself is so vastly complex that we've made up stories of conscious symbol processing, like logic and grammar, to try to explain what goes on in our heads.

The mind, like the weather, envelopes the brain like a planet and requires dynamical and integrated explanations rather than just-so stories.


from a fascinating thread over at http://www.edge.org/3rd_culture/thaler10/thaler10_index.html by way of http://www.marginalrevolution.com/marginalrevolution/2010/11/richard-thalers-question.html

Thursday, May 20, 2010

flickr fixr

Flickr is great but I am impatient, and strangely aggrieved that the page reloads on each new photo view. And I don't care about user comments, tags, etc., only looking at pictures.

I also needed an excuse to finally try out greasemonkey and lo and behold, flickr fixr is born. It feels a bit snappier than the current flickr photostream, but otherwise is a pretty modest first script (~6 lines of jQuery).

That's right, I was able to write jQuery thanks to Joan Piedra, which was a huge timesaver.

Anyway, try it out, see the difference: http://www.flickr.com/photos/floridapfe/2211054334/in/photostream/

Sunday, May 16, 2010

My dev environment

I wanted to describe my dev environment and work processes but it wouldn't make sense unless I describe the shape of my work so let me do that first:

Dev Cycle

Our dev cycle is pretty simple: create and checkout a branch associated with a ticket, make changes to that branch, merge it into a master branch, test it on a staging environment, push it live. It's common for a single developer to have several branches in progress at once.

I'm primarily concerned with reading/editing the stack of html/javscript/python/SQL. When I have questions, I lean heavily on log files, ipython, the mysql command line client, git, grep, testify, and a slew of other odds-n-ends. I also run virtual machines, mostly for browser compatibility testing.

In other words there's a set of varied tasks I need to be able to do efficiently and cohesively. Mental "context switching" is expensive so there's value in grouping related work and quarantining anything not immediately relevant. That's the idea, at least, for how I try to manage to complexity of multiple files, branches, documentation, etc. with minimal overhead.

All of this is done using Terminal on a MacBook Pro:



Dev Environment

So the smallest unit is a solitary file, in a lone buffer, in a single tab in vim, .... No file is an island, however, and if I'm doing anything reasonably interesting I'll probably need to view at least 2 files at once.

The next step up then is a vertical split (:vs in vim). If I'm working on a large screen I may split one more time for a grand total of three files sharing the same space. I've got shortcuts mapped in vim so that I can traverse them using Ctrl+H, Ctrl+J, etc.

As I open more files, I start opening tabs (:tabnew). They may stay open, or I may close them again immediately to reduce clutter (I mapped ,tn and ,tc to tab new/close so it's faster to do so).

I may evict existing screen splits and move them into a new tab if it makes life easier. I mapped Ctrl+I and Ctrl+O for navigating through tabs left and right. Again, judicious closing of tabs can make life easier.

Ctags is also useful for navigating, as are other plugins such as NERDTree. I use a few vim plugins; they should be a separate post though.

I am also doing all of this in a screen session. Each branch I'm actively working in will have its own virtual terminal, which I navigate using Ctrl+a. When you return to the original branch you were working in, it'll be just as you left it, and therefore easier to resume.

I'll also use screen to keep separate terminals open for tailing logs, running ipython/bash/sql commands, etc.

Also, all this work is taking place on a remote machine. If I need to work locally or connect to a different machine, I open a new tab in terminal (cmd+T) and proceed from there. I switch terminal tabs using cmd+{ or cmd+}.

The stack tops out with Expose/Spaces. I rarely need to use it extensively but I'll use different spaces for different browsers and running virtual machines. These are navigated using Ctrl+(arrow keys).

Oh, and I also use terminal in transparent mode (the "Pro" color scheme specifically). You can read documentation or examples without turning your head!

Summary

Here's what it looks like in action:



  • 2 files side-by-side

  • 2 other tabs open (the gray tabs on the top)

  • Another active screen session (green bar)

  • Another tab open in Terminal

  • Transparent terminal for readin' docs



the full stack / hotkeys:

vim file < vim split screen < vim tabs < screen vterms < terminal tabs < spaces
n/a < ctrl+h/j/k/l < ctrl + i/o < ctrl+a n/p/# < cmd+{/} < ctrl+(arrow keys)

Thursday, April 22, 2010

Automated tests saved my project from chaos and ruination

File this one under "Obvious" but I wanted to specifically describe how tests made developing against a brand new platform not just easier, but possible.

Over the past few weeks I've been developing against the spanking new Facebook Open Graph API that was released yesterday (the Like button specifically).

Facebook was developing the API at the same time we were. Many things were subject to change, including feature designs, the external API, and our own API wrapper. Chaos may have ensued, but for one rock upon which I clung: the tests I wrote early on (but not first!) for the Like button.

When when things shifted, it was a simple matter of fixing test failures. If the specification changed, I already had a solid test framework that was easy to reuse in order to account for new or different behavior.

It may seem obvious but those tests were worth their (figurative) weight in gold. We had little time and changes came frequently. We couldn't afford to miss the fact that we left something broken. And manually verifying the feature became infeasible and would take precious hours we didn't have.

Best of all, when Facebook flipped the switch and the feature went live following the keynote, I could breathe easily knowing that I had tested the hell out of it before millions of Facebook users would get to do the same. Yet another reason in a sea of reasons why tests are valuable.

Sunday, December 27, 2009

What's wrong with PHP?

Just as it's easy to completely write off a band you don't care for (because they sold out? or their singer meets with world leaders and has a terrible op-ed album in the New York Times), the same often happens with technologies and languages.

For example, there was some point in my life where I told myself I would avoid any project heavily involving PHP.

But why? What's wrong with PHP? Yahoo and Facebook use it...and I haven't used it enough to warrant such strong feelings.

I wanted to explore this (baseless?) apprehension further, and I thought of this characteristically absurd/profound quote from Perl creator Larry Wall:

"Perl is worse than Python because people wanted it [to be] worse."



Larry Wall

The goodness of Perl v. Python is a common religious argument. The above quote squelches the debate once and for all, but begs further questions.

Who is they? Why did they want Perl to be worse? Do the words I added ([to be]) change what Larry actually meant?

Consider this Mind Hacks post about trends and their origins; the concepts extend to any sort of idea that can grow legs. Trends in technology are the same way, and spread because a distant idea reached some critical mass of connectivity and settled in with your own circle of peers.

Developers can vote for or against any technology by speaking for or against it, but their most powerful influence is in choosing which technologies to devote their energies toward learning and improving. Enthusiasm for a project leads to expertise contribution, and contribution leads to enthusiasm.

Conversely, people who have a distaste for a technology will discourage others. They (the technologies) will languish if their community does not grow.

In other words, labeling a technology good or bad is a self-fulfilling prophecy given enough influence and/or critical mass. Soon companies using the "good" technology will flourish with resumes and job postings for "bad" technologies will receive lesser attention, serving only to reinforce existing stereotypes.

I'm largely paraphrasing Paul Graham. He wrote a great essay on this phenomenon, which he calls "The Python Paradox".

I believe this is what Larry was getting at. And it explains my own PHP aversion, as my experiences were underwhelming at worst, but the number of developers I've heard lament PHP convinced me to stay away, as if it's the bad part of town.

Arguing over which language is better or worse is a waste of time; what matters is the consensus of the larger community (see wikiality). Even if it's unjustified. But just like a neighborhood can turn around, opinions change, and that's why phrases like "JavaScript Renaissance" are thrown around. And although I can't shake all the PHP prejudice, I wouldn't make a point of avoiding it (PHP that is), either.

Thursday, December 24, 2009

Easy hexagonal tiles with css

I just started building an online game with appengine as a learning exercise, and I'm attempting to do so without flash, java, or any other plugin.

There's nothing to play yet, but I already have something that is generically useful: a hexagonal tile layout purely in html and css. It's pretty clean too, check it out:

The Django Template:

{% load mod %}

<html>


<head>


<link type="text/css" rel="stylesheet" href="/stylesheets/board.css">


</head>


<body>


<div id="board-container">


{% for i in rows %}


<div class="row {% if i|mod:2 %}offset{% endif %}">


{% for j in rows %}


<span class="hex">


<img src="/img/hexagon.png" />


</span>


{% endfor %}


</div>


{% endfor %}


</div>


</body>


</html>




The mod filter came from here.

All this does is create a grid of hex images (100x100 transparent pngs, edited from this source image). Every other row is "offset" so that the hex pieces nest together.

Here's the css:

#board-container {
border: solid black 5px;
width: 875px;
height: 700px;
}

.row {
/* This has to be .hex width * # of cols */
width: 800px;
}

.hex {
/* The width and height depend on the size of the hex image. */
width: 80px;
height: 65px;
border: none;
float: left;
}
.offset {
position: relative;
/* half of the hex width. */
left: 40px;
}


And the final result for a 10x10 grid:


The next step is to implement the game rules, ajax calls, and draw a sidebar with the playable pieces.