September 3, 2010

And here’s the Gaby Sanchez clothesline tackle on Nyjer Morgan

July 29, 2010

Are URL Shorteners Bad for the Web?

It never occurred to me that there could be anything negative about short URLs until I read this piece in GigaOM. The most prominent voice raising concerns about URL shorteners is DeWitt Clinton who is, surprisingly, not the former mayor of New York City, but an engineer on the Google Buzz team. Clinton says,

Deployments of a large-scale URL rewriting proxies impact that ecosystem at the most fundamental level, making it more difficult for users and machines alike to predict what happens when a link is followed.”

But what if you could have a visible shortened URL, but when you hovered over it, you would see the long URL from which it was derived? Then users would have a better chance at being able to predict what happens when they follow the link.


I made a simple example at http://tinpanvalley.com/bitly. When you hover over the short url, it uses the bit.ly API to fetch the long URL, then it puts the long URL into the title attribute of the <a> tag, so that when you hover over the short URL, you see the long URL.

It would be cool if this feature were built into browsers in the future. There would be some hurdles like determining if the url shortener eve has an API that allows you to look up the long URL. Maybe this phenomenon will make its way into the specification for a future version of HTML.

Until then, I’m thinking of making this into a browser add-on that you can download so the hover capability always works on your browser. Stay tuned.

Update: with a little searching, looks like other people have done this with greasemonkey scripts, etc.

July 25, 2010

Using Foursquare for Guerilla Recruiting

I’m not a recruiter, but I work with recruiters and I am contacted by recruiters on a daily basis. Sometimes I’m stunned at how many recruiters there are. How can the economy support so many recruiters? I don’t understand it, but I know there are some who make a pretty good living from their commissions. Imagine how much more they could make if they had a little bit of creativity.

If I were a tech recruiter, here’s what I would do. I’d go to the vicinity of companies that employ people that I want to place and I’d check in there. Here’s an example: you can stand on the corner of 9th Avenue and 16th St. in Manhattan and with foursquare, you can check in to Google NYC. Then you can see all the other people who have checked in to Google NYC and you can request to be their friend on foursquare. Now instead of the enormous pool of people who happen to have uploaded their resume to Dice or Monster, you have a very concentrated pool of Googlers and prospective Googlers (and maybe a few phonies, but I think the number of fake check-ins is low; fauxsquare is not yet a common practice).

July 11, 2010

More on .NET

Here’s a more concise way of framing the question of why startups don’t use .NET. Whenever you type runat=”server” in .NET you are ceding control of the web presentation layer to .NET. If .NET (or your .NET widget library) wants to puke out 32 nested tables and 200 lines of lousy-browser-performance javascript, then you’re stuck with that.

July 11, 2010

Why Startups Don’t Use .NET

Recently a blogger named Aaron wrote a thought-provoking post called .NET Culture Shock: Why .NET Adoption Lags Among Startups. Aaron elucidates the problem insightfully, determining that .NET is well established among enterprise developers whose chief concern is supporting systems, whereas startup developers worry primarily about supporting products. Aaron concludes that there is nothing inherent in .NET that precludes its use among startups; it is simply limited by culture differences between enterprise developers and startup developers.

Aaron claims that objections against .NET in the startup world such as platform lock-in and licensing costs  do not “pass the objective reality test”, but he doesn’t provide an objective reality test to back up these claims. Here’s an objective reality test. My cash-strapped startup needs an IDE. Will I choose Microsoft Visual Studio Ultimate for $11,899 or Aptana Studio for free?

However, there is a simpler and more compelling reason why startups do not use .NET (.NET boosters will be quick to point out that developers can get Microsoft Visual Studio Express for free). Startups preach the use of web standards, semantic HTML, and css-driven layouts.  Here’s a snippet from a job description posted by Ze Frank (and re-tweeted by startup leaders such as Jonah Peretti, founder of Huffington Post and Buzzfeed), “You should have sent at least one email to someone you have never met telling them that they should stop using tables.” Keep that “stop using tables” thought in mind. It’s going to come back up in a moment.

I recently had the opportunity to work on my first .NET project. It’s a large, established enterprise web application and I’m implementing a number of UI enhancements. The project uses .NET UI widgets made by DevExpress, a very popular commercial UI widget library for .NET.

One of my first assignments was to create a form that included a simple dropdown list with three items. As a proponent of web standards and semantic HTML, I would normally code this dropdown list as such:

<select name=”Selection”>

<option value=”Single”>Single</option>

<option value=”Multiple”>Multiple</option>

<option value=”CheckColumn”>CheckColumn</option>

</select>

However, the technical lead on the project directed me to use the DevExpress dropdown control so that he could easily tie it into the back-end code. So, here is the HTML and javascript generated by DevExpress to create the same dropdown list that I have coded above (if you don’t believe me, you can see this code for yourself; just view source on this page at DevExpress):

<td>
                <table cellspacing=”1” cellpadding=”0” border=”0” style=”border-collapse: separate;” id=”ctl00_phContent_lbSelectionMode” class=”dxeButtonEdit_Aqua  “>
            <tbody><tr>
                <td style=”display: none;”><input type=”hidden” name=”ctl00_phContent_lbSelectionMode_VI” id=”ctl00_phContent_lbSelectionMode_VI” value=”2”></td><td style=”width: 100%;” onmousedown=”return aspxDDDropDown(‘ctl00_phContent_lbSelectionMode’, event)” class=”dxic”><input type=”text” style=”border-width: 0px; width: 100%; padding: 0px; margin: 1px 1px 2px; cursor: default;” readonly=”readonly” onchange=”aspxETextChanged(‘ctl00_phContent_lbSelectionMode’)” onfocus=”aspxEGotFocus(‘ctl00_phContent_lbSelectionMode’)” onblur=”aspxELostFocus(‘ctl00_phContent_lbSelectionMode’)” id=”ctl00_phContent_lbSelectionMode_I” value=”CheckColumn” name=”ctl00$phContent$lbSelectionMode” class=”dxeEditArea_Aqua  ” autocomplete=”off”></td><td style=”-moz-user-select: none;” onmousedown=”return aspxDDDropDown(‘ctl00_phContent_lbSelectionMode’, event)” class=”dxeButtonEditButton_Aqua” id=”ctl00_phContent_lbSelectionMode_B-1”><table cellspacing=”0” cellpadding=”0” border=”0” style=”border-collapse: separate;” class=”dxbebt”>
                    <tbody><tr>
                        <td class=”dx”><img style=”border-width: 0px;” alt=”v” src=”/ASPxEditorsDemos/DXR.axd?r=1_3” class=”dxEditors_edtDropDown_Aqua” id=”ctl00_phContent_lbSelectionMode_B-1Img”></td>
                    </tr>
                </tbody></table></td>
            </tr>
        </tbody></table><input type=”hidden” value=”0:0:12000:395:120:0:-10000:-10000” name=”ctl00_phContent_lbSelectionMode_DDDWS” id=”ctl00_phContent_lbSelectionMode_DDDWS”>
        <div style=”position: absolute; left: 395px; top: 120px; z-index: 12000; height: 69px; width: 170px; overflow: visible; visibility: hidden; display: none;” id=”ctl00_phContent_lbSelectionMode_DDD_PW-1”>
            <table cellspacing=”0” cellpadding=”0” border=”0” style=”border-collapse: separate; position: relative; left: 0px; top: 0px;” id=”ctl00_phContent_lbSelectionMode_DDD_PWST-1”>
                <tbody><tr>
                    <td style=”width: 168px; cursor: default; height: 0px;” onmousedown=”aspxPWMDown(event,’ctl00_phContent_lbSelectionMode_DDD’,-1,false)”><table cellspacing=”0” cellpadding=”0” border=”0” style=”width: 168px; border-collapse: separate; height: 67px;” id=”ctl00_phContent_lbSelectionMode_DDD_CLW-1”>
                        <tbody><tr>
                            <td style=”height: 100%;” id=”ctl00_phContent_lbSelectionMode_DDD_PWC-1”><table cellspacing=”0” cellpadding=”0” border=”0” style=”border-collapse: separate; height: 0px; width: 170px;” id=”ctl00_phContent_lbSelectionMode_DDD_L” class=”dxeListBox_Aqua”>
                                <tbody><tr>
                                    <td valign=”top”><div style=”width: 168px; overflow: hidden; height: 66px; padding-right: 0px;” class=”dxlbd” id=”ctl00_phContent_lbSelectionMode_DDD_L_D”>
                                        <input type=”hidden” name=”ctl00$phContent$lbSelectionMode$DDD$L” id=”ctl00_phContent_lbSelectionMode_DDD_L_VI” value=”2”><table cellspacing=”0” cellpadding=”0” border=”0” style=”width: 100%; border-collapse: separate;” id=”ctl00_phContent_lbSelectionMode_DDD_L_LBT”>
                                            <tbody><tr class=”dxeListBoxItemRow_Aqua”>
                                                <td class=”dxeListBoxItem_Aqua” id=”ctl00_phContent_lbSelectionMode_DDD_L_LBI0T0”>Single</td>
                                            </tr><tr class=”dxeListBoxItemRow_Aqua”>
                                                <td class=”dxeListBoxItem_Aqua” id=”ctl00_phContent_lbSelectionMode_DDD_L_LBI1T0”>Multiple</td>
                                            </tr><tr class=”dxeListBoxItemRow_Aqua”>
                                                <td class=”dxeListBoxItem_Aqua dxeListBoxItemSelected_Aqua” id=”ctl00_phContent_lbSelectionMode_DDD_L_LBI2T0”>CheckColumn</td>
                                            </tr>
                                        </tbody></table>
                                    </div></td>
                                </tr>
                            </tbody></table><script type=”text/javascript” id=”dxss_1162343191”>
&lt;!—

var dxo = new ASPxClientListBox(‘ctl00_phContent_lbSelectionMode_DDD_L’);
window[‘ctl00_phContent_lbSelectionMode_DDD_L’] = dxo;
dxo.uniqueID = ‘ctl00$phContent$lbSelectionMode$DDD$L’;
aspxAddDisabledItems(‘ctl00_phContent_lbSelectionMode_DDD_L’,[[[‘dxeDisabled_Aqua’],[”],[”]]]);
dxo.SelectedIndexChanged.AddHandler(function (s, e) { aspxCBLBSelectedIndexChanged(‘ctl00_phContent_lbSelectionMode’, e); });
dxo.ItemClick.AddHandler(function (s, e) { aspxCBLBItemMouseUp(‘ctl00_phContent_lbSelectionMode’, e); });
dxo.RequireStyleDecoration();
dxo.styleDecoration.AddStyle(‘F’,’dxeFocused_Aqua’,”);
dxo.savedSelectedIndex = 2;
dxo.itemsValue=[‘0’,’1’,’2’];
dxo.isComboBoxList = true;
dxo.hoverClasses=[‘dxeListBoxItemHover_Aqua’];
dxo.selectedClasses=[‘dxeListBoxItemSelected_Aqua’];
dxo.disabledClasses=[‘dxeDisabled_Aqua’];
dxo.InlineInitialize();

//—&gt;
</script>
</td>
                        </tr>
                    </tbody></table></td>
                </tr>
            </tbody></table>
        </div><script type=”text/javascript” id=”dxss_682451067”>
&lt;!—

var dxo = new ASPxClientPopupControl(‘ctl00_phContent_lbSelectionMode_DDD’);
window[‘ctl00_phContent_lbSelectionMode_DDD’] = dxo;
dxo.uniqueID = ‘ctl00$phContent$lbSelectionMode$DDD’;
dxo.Shown.AddHandler(function (s, e) { aspxDDBPCShown(‘ctl00_phContent_lbSelectionMode’, e); });
dxo.adjustInnerControlsSizeOnShow=false;
dxo.closeAction=’CloseButton’;
dxo.popupHorizontalAlign=’LeftSides’;
dxo.popupVerticalAlign=’Below’;
dxo.isPopupPositionCorrectionOn=false;
dxo.shadowVisible=false;
dxo.width=0;
dxo.height=0;
dxo.InlineInitialize();

//—&gt;
</script>
<script type=”text/javascript” id=”dxss_949748170”>
&lt;!—
document.getElementById(“ctl00_phContent_lbSelectionMode_I”).setAttribute(“autocomplete”, “off”);
aspxAddHoverItems(‘ctl00_phContent_lbSelectionMode’,[[[‘dxeButtonEditButtonHover_Aqua’],[”],[‘B-1’]„[[{‘spriteCssClass’:’dxEditors_edtDropDownHover_Aqua’}]],[‘Img’]]]);
aspxAddPressedItems(‘ctl00_phContent_lbSelectionMode’,[[[‘dxeButtonEditButtonPressed_Aqua’],[”],[‘B-1’]„[[{‘spriteCssClass’:’dxEditors_edtDropDownPressed_Aqua’}]],[‘Img’]]]);

var dxo = new ASPxClientComboBox(‘ctl00_phContent_lbSelectionMode’);
window[‘ctl00_phContent_lbSelectionMode’] = dxo;
dxo.autoPostBack = true;
dxo.uniqueID = ‘ctl00$phContent$lbSelectionMode’;
dxo.RequireStyleDecoration();
dxo.styleDecoration.AddStyle(‘F’,’dxeFocused_Aqua’,”);
dxo.InlineInitialize();

//—&gt;
</script>

</td>

Now, if I walked into a startup and presented that 92-line table-based chunk as an example of how to code a HTML dropdown list, I guarantee you that I would not be getting a return call. The code above obviously violates web standards on many levels.

The difference between .NET developers and startup developers goes deeper than just “culture”. Every culture has values. Startup developers (at least web startups) value the web as a native platform with its own technologies (HTML, CSS, Javascript). A lot of .NET web projects, on the other hand, appear to me to be attempts to create 1980’s-era client-server applications and then smush them and squash them until they run inside a web browser. Since many corporations require the use of Internet Explorer, .NET projects are typically only tested on IE. Startups have a more diverse audience and aim for quality across all browsers.

It’s not so much about systems vs. products. It’s about valuing the web as a platform in its own right vs. valuing Microsoft as the platform and considering the web browser as just another delivery mechanism, an afterthought.

When .NET can generate the same kind of clean, semantic HTML, CSS, and Javascript that I can code by hand, then web startups might consider adopting it. Until then, .NET will remain inside the gray cubicle walls of the enterprise.

June 25, 2010

Dear RSA Security

Please add Indiglo to your ubiquitous security token key fob thingies.

June 25, 2010

A Kübler-Ross-like Model for Apple Product Launches

As much as I love The Oatmeal’s “What it’s like to own an Apple product”, I think it’s missing a few key stages in the Apple product launch cycle.

Stage 1. Rumors.

Stage 2. Leaks

Stage 3. The big announcement and demo at WWDC. The ooohs and aaaahs.

Stage 4. The pre-order that crashes all the servers. Panic ensues. I don’t know if Apple really got my pre-order!

Stage 5. The product availability date is announced. Long, long lines start days before the product is available. Reservations, complaints, a media frenzy; Celebrities and politicians wait in line with ordinary, anonymous fanboys and fangirls. Rude, disorganized, and heartless Apple retail employees parrot Kafka-esque “company policies” without context or explanation. If you’re lucky enough to get the product on the first day, there is a surfeit of well-heeled folks flooding the social networks with offers to parachute in and buy yours at multiples of the cost. When the first lucky souls leave the Apple Stores with their gizmos it’s like the Rapture has begun.

Stage 6. The scare. Oh my God, the touch screen is developing dead spots! The batteries are defective! When you make a call, your hand blocks the antenna! There’s no multi-tasking (does anyone remember the original Finder in the original MacOS? Remember how everyone complained that it couldn’t multi-task? Then they came out with the “Multi-Finder”—some things never change).

Stage 7. The I-Told-You-So’s - Ha! Not only did you waste your money, you’re giving up your freedoms. It’s a closed system. It’s got DRM on everything. You got duped by the RDF!

Stage 8. Everybody forgets stages 1-7 and goes back to complaining about how bad AT&T’s network sucks.

April 28, 2010

Emerging Alternative Uses of Foursquare

I wonder if foursquare’s success will be boosted by people who start using foursquare for reasons other than to show off what cool restaurants and sporting events they attend. For example, I checked in at my bank yesterday and took the opportunity to “shout” my dissatisfaction with the bank(the bank is Wachovia, btw and they are a completely hideous institution that I would urge you to avoid and/or divest yourself of). I’m thinking that protest movements could be started by people who show up and check-in at businesses that provide lousy service, rip people off, etc. and shout them out. It could be like a real-time Better Business Bureau complaint.

Of course, foursquare is depending on small businesses for their revenue, so they might frown upon this behavior (although I notice that when foursquare CEO Dennis Crowley doesn’t like a venue, he doesn’t hesitate to check in and say the place is crappy, overpriced, etc.)

April 1, 2010

Foursquare and Viral Marketing Patterns

I was reading The Twitter Highlights of Foursquare CEO’s Where 2.0 Talk and this quote by Dennis Crowley stuck with me: “How can I turn life into a video game?” This quote was apparently the inspiration behind the wildly popular Foursquare.

Today I somehow landed on this page about design patterns in viral marketing which included a fascinating list of 21 patterns that have been successful in viral marketing. They included “animal personification”, “violate a stereotype”, and “Objects doing things they weren’t really made for.” If you think about it, these have a ring of familiarity. We’ve been seeing them in ads and on the Internet for ages. Most of us (or at least me) have never been able to discern a pattern, but a guy named Mike Laurie has.

So, what’s the point? Well, here’s #21 on the list: “Connect video games to real life.” I wonder if Dennis Crowley has seen this list of successful patterns for viral marketing or if it’s coincidence?

March 11, 2010

New Bipartisan Healthcare Reform: Healthcare Slot Machines!

The trends of rapidly growing numbers of slots parlors and rapidly growing numbers of Americans without health insurance are bound to collide sooner or later. There will soon be special slot machines that award the winner with the expensive and necessary healthcare resources they need.

Imagine sitting in a windowless, climate-controlled cavern in, say, Macungie, PA for six hours drinking $4 cokes and pumping quarters into the one-armed bandit when suddenly it’s your lucky day! ***HIP REPLACEMENT***, ***HIP REPLACEMENT***, ***HIP REPLACEMENT***. You’ve just won a HIP REPLACEMENT! Oh, you don’t need a hip replacement? You need a year’s supply of Procardia? Oops. Well here’s a coupon for half off the salad bar. Better luck next time. Keep on scratchin!