Thursday, March 24, 2011

How Do I Print [this web page]!?

TL;DR:

Press "ctrl-p" (in every browser ever made).

But But But...

Where's my "print" link? Print links are about a million years old in Internet years. They were needed back in the day when technology couldn't easily produce "printer-friendly versions" of pages without doing server-side voodoo magic. Things have been different for years, though, and separate print pages are no longer necessary. 

But I still want one!

No.

But this other, cooler site has one!

Odds are, their "print" button just calls "window.print()" which is just short hand code for, "you're an idiot and shouldn't be trusted with electricity".
Hey, don't get upset with me, I'm just translating.

Alternate Methods

Internet Explorer

or

Chrome:

or

Firefox

Wednesday, March 16, 2011

Feature Complete vs. Complete Features

I used to use a Windows Mobile 6 phone. It was very expensive and had every bell and whistle there was. Unfortunately, it was a terrible, horrible phone. Why? Because it was awful at everything/good at nothing.

On paper, it was pretty sweet—feature complete—but in reality it could barely make phone calls.

In contrast, the iPhone was a less capable device on paper, but a far superior choice in reality.

As a business software developer, I see how this can happen. When a project is under strain, there’s pressure to implement the bare minimum to meet the feature’s requirements and put off less tangible things like a good user experience for the next version.

But of course that next version has its own pressure. If you don’t constantly apply pressure to improve usability—a difficult to measure, but critical feature—your product will falter. That is, you can increase a product’s feature set by throwing more and more into it to make it look better on matrix comparisons, but this will come at the expense of the actual product as a whole.

Think back to the original iPhone. Apple introduced it’s first phone into a stable market owned by big names like Windows, Palm and RIM/Blackberry. This first iPhone lacked a lot of features I bet most would have considered show stoppers:

  • Copy/paste
  • Old network technology (Edge vs. 3g)
  • Poor battery life; non-replaceable battery
  • And plenty of other significant problems:

  • No keypad
  • Very expensive ($400-$600+)
  • Legendarily poor call quality
  • Weak specs (processor/memory/camera)
  • Rather than cobble together crappy solutions to these limitations, Apple focused on nailing its key features: a killer UI and a full blown web browser. People went crazy for it and they kept coming back year after year:

    image

    (I know they sell other stuff, too)

    Apple captured the market with a holistically better device and waited to release non-core functionality like copy-paste until they could give it the attention it needed. With the possible exception of call quality, they have since addressed all the issues I listed above and brought awesome new things to the mobile world like the highly lucrative AppStore.

    I’ve come to develop a lot of respect for companies/projects/people that show restraint when building things instead of adding whatever random people ask for or what looks neat. This is why I now realize how important mission statements are—not just for a business but for a product. You need something to guide your decisions when relentless uncertainty arises.

    At a recent internal product launch at Rovisys I was quoted in a presentation as having said “you can do anything with software.” I insisted that the slide be revised to include the rest of my sentence:

    “You can do anything with software but that doesn’t mean you should.”

    Truncating the log of a previously replicated database

    (The following is specific to SQL Server 2000 and might not apply to more recent versions.)

    I occasionally restore production databases to a test system. Normally I just flip the recovery model from full and simple and I’m good to go. Unfortunately, if the database was being replicated it’s not so easy.

    Even if you restore the database without “KEEP REPLICATION”, which would imply all the replication bits would be cleaned up for you, the transaction log will still have a replication marker that prevents it from being truncated.  This means the log file, even in “simple” mode, will grow unbounded (not good!).

    I’m always reminded of this when I try to clean up an ever-growing log with this command:

    BACKUP LOG yourdb WITH TRUNCATE_ONLY

    and I get this error:

    The log was not truncated because records at the beginning of the log are pending replication. Ensure the Log Reader Agent is running or use sp_repldone to mark transactions as distributed

    Not one to ignore the advice of error messages, I then try running the following commands:

    -- see what's going on
    DBCC OPENTRAN
    
    -- not too much? just clear the replication marker
    EXEC sp_repldone @xactid = NULL, 
                     @xact_seqno = NULL, 
                     @numtrans = 0, 
                     @time = 0, 
                     @reset = 1

    Unfortunately, this fails with the following error:

    The database is not published.

    OK, so part of SQL Server knows it’s not being replicated, I guess that’s good. A lot of sites suggest physically removing the log file by detaching the database, renaming or deleting the log file, and reattaching the database. There’s a much simpler, gentler way:

    -- publish database (this doesn't actually create 
    -- a snapshot--it only takes a cople seconds)
    sp_replicationdboption 'yourdb','publish','true'
    
    -- clear that replicaton marker (yourdb should be selected)
    EXEC sp_repldone @xactid = NULL, @xact_seqno = NULL, @numtrans = 0, @time = 0, @reset = 1
    
    -- unpublish database
    sp_replicationdboption 'yourdb','publish','false'

    Yes, you simply enable replication long enough to clear the marker. This only takes a few seconds as it doesn’t actually generate a new snapshot or anything expensive like that. Now you’re free to truncate the log!

    Tuesday, March 15, 2011

    How Not to Cross the Border, Or “Please Proceed to Immigration”

    I travel a fair bit for my job and it occasionally takes me up north to America Junior. I’ve been to Ontario dozens of times and before Sunday never once been hassled for more than five minutes. I carefully go through the motions of avoiding the dangerous “w” word and normally cruise right through.

    Before Sunday, I’ve been redirected to immigration twice. The first time, a very unhappy agent gave me a six month work visa without even telling me. It wasn’t until he cleared me and I was walking away that I noticed the stamp on my passport. Thanks, random disgruntled agent!

    The second time I just answered a few questions and was on my way.

    348516764_f4eb021893_b

    Sunday was a different story. I was making fantastic time when I crossed the Ambassador bridge. The booth agent didn’t much care for my song and dance around the “w” word and sent me to immigration. The guy there wasn’t too happy to see me either. He asked for my documentation—letter of attestation, college diploma, resume and customer contract—and was disappointed that I wasn’t sure what he was talking about and couldn’t provide any of it.

    I admitted that I had no idea what to do as I’d never provided anything before and asked for suggestions. He thought it’d be wise to call human resources and get a letter that shows that "there's no one else in Canada that can do what [I] do to work here as a non-Canadian."

    This was at 10pm on Sunday so that wasn’t going to happen (also, that was impossible—I’m awesome at what I do but not 100% unique, even in Canada). I asked if I was being turned away or if I could figure something out. He replied, “I’m legally required to give you a chance to produce documentation before I turn you away.” Challenge accepted.

    I grabbed my laptop and tethered it to the crappiest, weakest, most pathetic signal my phone as ever intermittently clung to. I then impressed myself by leveraging my scan-and-organize-everything compulsion by obtaining the following documents:

    I also wrote a letter of attestation according to the NAFTA documents the agent gave me. Yeah, NAFTA, as in the treaty. I asked the guy if I could write this letter myself, seeing as how no one would be present at my office. He was surprised and said no one had ever done it themselves on the spot before. He couldn’t see why not so that’s what I did.

    NAFTA explained that as a professional, I could enter the country as a business visitor without proving that I’m 100% unique. It was weird writing a letter by, about, and for myself. Considering my battery had started to flash when I started, I think I did pretty good:

    (downloaded letterhead)
    Michael Haren

    March 13, 2011

    Dear Canada,

    This letter serves to identify Michael Haren as a senior engineer at The Rovisys Company. Michael is working closely with (redacted) for a project of international scope, based in (redacted), United States. His brief presence is required in meetings with (redacted) IT department to support this effort.

    As proof of his professional status, I have attached his diploma and resume. As further evidence, he has been employed by Rovisys for more than five years.

    Thank you,
    Michael Haren

    I ran into a problem. I had gathered everything I needed but not in hard copy. As my lappy was dying I desperately tried to use an internet fax tool to deliver everything to them but I was really struggling with my podunk connection. In the last few moments, I transferred all the files to my phone and from there sent the files to Wife as a backup.

    Oh, and I put them on a flash drive for the next step.

    I went up to the counter and pulled out the drive. I was greeted by a new face. Apparently I had arrived at shift change and they previous guy that was helping me was gone. I had to start over but I was optimistic (my situation had a lot of room to improve, but it couldn’t get much worse).

    I explained that I had found everything they needed and it was all on the flash drive. Before new-face could object, I acknowledged that I knew there was no way they could plug in a random USB drive into their computers and explained that I was trying to reach someone with a fax machine.

    She asked me a bunch of new questions and genuinely tried to understand exactly what I do for a living. She summed it up nicely, actually, “so you work on a mainframe in the US and some people in Canada dial in to it over the phone to do stuff?”

    “Yes, exactly!” (if we were in the 1980s, at least, but the broad strokes were close enough).

    And then my big break, “OK, Mr. Haren, I’m going to give you the benefit of the doubt here and allow you to enter. Just next time please print the documents before you arrive.”

    Apparently she didn’t realize I had just gathered/written them minutes before. I was on my way at last! I hopped in my car and sped off, a couple of hours behind schedule. I happily looked up and saw this:

    Oh that’s weird, I thought. Then, quite suddenly, I realized this meant I was headed back into the United States and shouted a four letter word. I had a decision to make. I could go through customs two more times (and pay the bridge toll twice again, too), or do something very dumb. I was tired and irritable so I did the latter.

    I pulled a u-ey on the bridge. Even in my tiny car it was a three-point turn but I was quick and there wasn’t any traffic. I pulled up to the Canada-booth again and whimpered, “you’re not going to believe this but I was just cleared through immigration and I made a wrong turn.” He glanced at his computer and waved me through (phew!). I quickly got onto the highway (the right one) and eventually arrived (very late) to my hotel.

    Morals of this story:

    • Don’t go to Canada
    • If you must, print out your documents first
    • The internet is awesome, as is my phone (DINC) for connecting me to it

    Thursday, March 10, 2011

    The Curious Behavior of HTML Image Inputs, Or Why "&x=0&y=0" Is Showing Up Uninvited

    While working on an internal tool I noticed that the search form was producing unexpected get requests. Here’s the form:

    <form action="/Search" method="get">
      <input id="s" name="s" type="text" value="" />
      <input type="image" src="search.png" value="Search" />
    </form>

    I expected this to create requests like

    /Search?s=blah

    but instead I got this:

    /Search?s=blah&x=0&y=0

    Hmm. Initially I thought this was some sort of ASP.NET trick to remember scroll position. But I’m using MVC, which has a lot less unexpected magic in it so I quickly concluded it must be something else. I thought about those image maps that used to be all the rage back in 1999 and determined that my image input was causing the problem.

    This was easily confirmed by actually clicking on the magnifying glass on my page and seeing requests like this:

    /Search?s=blah&x=5&y=3

    Ah, so yes, it is recording where I click. While I’m sure that’s really great in some situations, it’s not what I want now. Interestingly, the solution to this problem wasn’t so simple. The cleanest workaround seems to be disabling the image input when the form is submitted. Since the browser won’t send the value of disabled inputs upon submission this solves the problem.

    Here’s a tiny line of jQuery which solved the problem for me:

    // disable the image submit buttons so the browser doesn't add &x=&y= to the qs
    $('form.strip-img-inputs-on-submit').submit(function (e) {
        $(this).find('input[type=image]').attr('disabled', true);
    });

    Essentially all this does is find all forms with a certain class and disable image inputs when submitted.

    Wednesday, March 9, 2011

    Dear NASA, I Officially Request One Space Shuttle

    Public Communications Office
    NASA Headquarters
    Suite 5K39
    Washington, DC 20546-0001
    public-inquiries@hq.nasa.gov

    Dear NASA,

    On my way into work today I heard that you’re looking for a new home for the newly retired space shuttles. It seems that a lot of prestigious museums are getting in on the action and I thought, why not me?

    Sure, I’ve never really been into NASA, space, shuttles, or even airplanes but I have a few reasons why I’m the best candidate:

    • Growing up watching contestants on Saturday morning kids shows go to space camp every week, I’ve heard a lot about space camp and that bouncy thing looks fun
    • I already have the coolest name: Blasty
    • I’ve watched dozens of those vomit comet videos on YouTube
    • I went to my daughter’s career day last week as a lame computer engineer. Next year? Space shuttle owner. They’re three years old so I think they’ll just assume I’m an astronaut
    • Imagine all the jokes I’ll get to make about the price of fuel—I bet Blasty holds a lot, and nothing but primo for my baby!
    • I like Star Wars, Battlestar Galactica, and Firefly an age-appropriate amount
    • I will apply at most one bumper sticker to Blasty and one to my car

    I realize this is just a formality but in keeping with the rules I should mention the following regarding the application requirements:

    • I have the facilities to store Blasty indoors. In the summer we can use my two-car garage. In the winter (when it’s too damn cold and I want my car in the garage) I’ll keep her at the nearby mulch company—they have a lot of experience winterizing RVs and boats so they should be able to do the job
    • I have as much experience caring for space shuttles as most people and I promise to read the manual
    • I can’t exactly cover the $28,800,000 it’ll cost to prepare and transport Blasty but I have that all figured out if we act quickly. It looks like you’re scheduled to land in about two hours. The local university has an airstrip two miles from my house—just land there!

    I look forward to your favorable decision.

    Thanks,
    Michael Haren

    Saturday, March 5, 2011

    Project Noodle: Terminated

    It is with surprisingly little regret that I announce the termination of Project Noodle. Those not directly involved can stop reading now as this is completely unrelated to anything I’ve written about recently.

    Project Noodle was conceived with the goal of improving the recruitment process at my company. We don’t have trouble getting candidates but we don’t have easy access to data on how successful interviewers are—that’s what I wanted to fix.

    After working through some mockups and trying to define how we might measure a successful interviewer, I came to three conclusions:

    • HR already collects a lot of information about candidates and interviews in a set of spreadsheets
    • We don’t have (and can’t collect) enough data to tell who is good or bad at interviewing
    • But even if we could, it’d take years and probably couldn’t be shared with us anyway

    The whole point of Project Noodle was to collect data with the goal of giving interviewers (e.g. me) feedback on how we’re doing. Since I can’t do that, I’ve decided to drop the project.

    As I just wrote, knowing when to do this is important but difficult.

    Code Isn’t Always the Best Tool

    One of my favorite, routine questions I ask in interviews comes from Steve Yegge’s post on phone screening:

    Many C/C++/Java candidates, even some with 10+ years of experience, would happily spend a week writing a 2,500-line program to do something you could do in 30 seconds with a simple Unix command.

    …Last year my team had to remove all the phone numbers from 50,000 Amazon web page templates, since many of the numbers were no longer in service, and we also wanted to route all customer contacts through a single page.

    Let's say you're on my team, and we have to identify the pages having probable U.S. phone numbers in them. To simplify the problem slightly, assume we have 50,000 HTML files in a Unix directory tree, under a directory called "/website". We have 2 days to get a list of file paths to the editorial staff. You need to give me a list of the .html files in this directory tree that appear to contain phone numbers in the following two formats: (xxx) xxx-xxxx and xxx-xxx-xxxx.

    How would you solve this problem? Keep in mind our team is on a short (2-day) timeline.

    As Steve goes on to explain, the wrong answer to this question is to write a bunch of code. Instead, you should leverage other tools. For example, the following tools are on the laptop I type this from right now and are capable of solving this problem in seconds: Grep, Visual Studio, Notepad++, and Eclipse. Tools like these are on all development machines and you’d be expected to be familiar with them.

    As a software engineer, I have an awesome toolbox loaded up with great technology to help me build neat stuff. However, as in the case above, my favorite tool (code) isn’t always appropriate.

    I offer my own Project Noodle as another example. Project Noodle was my software idea to track candidates through the interview process. My goal was to improve recruiting through analysis of better-captured data. After reviewing my project ideas with the actual people who would use this system, they were all very excited. They showed me how they track things now and what data they are looking to track in the future.

    DK_HammerIt eventually became evident to me that the perfect tool already exists in Microsoft Excel. It turned out that the people I was designing a tool for were already using it very effectively. I could certainly improve things a bit and make the process a little smoother and prettier, but it simply isn’t worth it when a suitable tool is already in place.

    I think choosing not to write a program in cases like this is obvious to non-programmers, but not for us software people. For us it’s a difficult realization. In the case of Project Noodle, I’ve invested considerable effort designing it already, but I must admit that it’s not the best solution for the problem. Luckily, I came to this awareness early in the process, saving me countless hours of wasted effort.

    Sometimes our favorite tool isn’t the best tool.

    I offer just one counterexample: educational coding. It’s absolutely ok to develop something that otherwise shouldn’t be written if the purpose in doing so is self-development.

    (This should not be used as an argument against building new software—there’s a delicate balance between using off-the-shelf products and rolling your own.)

    Wednesday, March 2, 2011

    How Much Does an Apple Addiction Cost?

    Apple’s iPad2 will be released on March 11. It looks awesome, no doubt—just like the first one, released only 11 months ago. That got me thinking: how much would it really cost to feed an Apple addiction?

    Before you label me a fan boy, let me offer the following facts in my defense:

    • I don’t have a mac (Wife has a two or three year old MacBook)
    • I have a pretty dated 30gb iPod (pre-Touch days)
    • My love of Apple is actually much bigger than Apple—I love all technology

    Moving on. For this calculation, I’ve made the following assumptions:

    The addicted user will buy the following products:

    • A Mac every two years
    • A major non-laptop purchase every year
    • A “minor” purchase every year

    The calculation will be run for the following user profiles:

    • The poser who buys the cheapest option of whatever new crap Steve presents
    • The functional elitist who buys mid-grade all the way because they actually use it (this would be me)
    • The hardcore fan boy who goes top of the top of the line every time

    The numbers*:

    In summary, an Apple addiction costs a surprisingly little $89-198 per month. Maybe it’s just me but that’s much less than I’d have guessed it would cost to be swimming in shiny new Apple gear all the time. Hmmmm…

    *Numbers do not include potentially substantial things like taxes, monthly cell charges, App Store purchases, the shakes, etc.