How to get an iPhone 5

Originally published on Sat, 10/06/2012

Here’s how I’m doing it, not that I recommend this to anyone else.

  1. Pre-order online, on the first day. Get informed that you will need to wait 2-3 weeks.
  2. 3 weeks and 1 day later, get a call from Apple saying the order has been put on hold by Sprint.
  3. Call Sprint, wait on hold for 5 minutes. Tell them the name of your first pet.
  4. Get told warmly that they cannot help you– as much as she wants to– because the order was made through a third party (Apple) and Apple must call Sprint’s National Sales Support Desk. They will only talk to third party retailers, “I can’t even talk to them,” she says. Helpfully, she gives you a phone number.
  5. Call Apple, have an automated voice tell you it can help you with anything, just ask in a complete sentence. Humor the computer for a few moments before telling it you need to talk to a human being. It transfers immediately, and a woman answers on the fourth ring. Explain the situation, give her the number. She puts you on hold while she calls.
  6. A few minutes later, she says they gave her a different number to call. She also verifies that she has your wrong phone number (home number, presumably). She calls the next number, with you on hold.
  7. A few minutes later, the Apple rep introduces you to a Sprint rep, who wishes to ask a security question. In anticipation, you tell him your first cat’s name. After ascertaining the situation, the Sprint rep puts the two of you on hold while he talks to his supervisor. After a while, he comes back and says you must contact the National Sales Support Desk. Once informed that you’ve already done that, he talks to his other supervisor (more hold music) and he agrees to wait on hold while he places the call.
  8. All three of you talk to a man who inverstigates and finds no good reason for the delivery of your iPhone to be put on hold. He seems almost confident that the problem can be resolved. But first, he must ask for the Apple rep’s store ID number. She has no such number, since she is a customer service rep. The man replies, “we can only validate through a store” and gives some helpful hints as to where she might find an Apple department that he’s authorized to talk to.
  9. The Apple rep hangs up on Sprint and puts you on hold while she finds a way to communicate through proper channels. Eventually she brings you into a conference call. The other person transfers the two of you to Sprint, this time without hold music. At this point, the Apple rep explains that Apple cannot complete the delivery, so they are cancelling it, but will send you email so that when you place a new order you can respond to that email with your order number and Apple will expedite the delivery. They’ll try to get it to you as close to the original delivery date as possible. You can even order a different color or storage capacity.
  10. The latest Sprint rep assures you that there was no reason for the original hold on your order, claims it may have been a computer glitch– and offers to remove the hold. The Apple rep explains that the order has been cancelled. It will take 24 hours for the cancel to propagate. Do not order a new phone before then, or you will be renewing a contract that has just been renewed– and the order will be placed on hold as invalid.
  11. Wait 24 hours, or better yet, until Monday.
  12. Hope for the best.

That’s 1 hour, 20 minutes for the second call. Mostly on hold.

Advertisements

Scala emoticons

There are a lot of great things about Scala, but there are a few things where that programming language just goes overboard. Consider that there are several emoticons built into the standard library:

  • +:= (vampire pope) for adding items at the front of a sequence
  • <:< (sad witch) for comparing generic types
  • :/ (uneasy) fold right

And that’s just the ones I know about. Unfortunately, you can’t use a search engine to find any more, because none of the major search engines index emoticons. :/ (try it). Fortunately there is a well-hidden reference page.

Post a comment if you find any more.

Thoughts on recursion

I was poking through Code Complete, 2nd Edition by Steve McConnell recently, after I’d handed the book to a computer science student. The book is showing its age, as good object-oriented design is better understood than it used to be, but it remains the best book on how to program well.

One thing that struck me, though, was a particularly strong statement against recursion, on page 397 (2nd Edition):

If a programmer who worked for me used recursion to compute a factorial, I’d hire someone else.

To put this in context, McConnell had just presented a few appropriate uses for recursion (quicksort and maze solving [i.e. graph searching]), and is railing against the simple examples one typically learns in computer science classes. He sees recursion as an advanced technique, which should be avoided unless it provides a clear advantage.

McConnell says recursive algorithms are harder to read. I don’t buy that; it depends on your audience. But his biggest beef is with the stack. When a function calls itself over and over again, the stack grows (keeping track of all the variables in all those function calls) and you can run out of memory, the dreaded stack overflow.

In many computer science departments, the first language you learn is Scheme, which doesn’t support iteration, so you can’t compute a factorial (or do any other kind of looping) without recursion. Scheme handles this with tail recursion elimination, where if the last thing a function does is call itself (i.e. tail recursion), the Scheme interpreter overwrites the stack frame– essentially replacing recursion with a loop.

Since most languages don’t do tail recursion elimination, and since it can be harder to write a function as tail recursive, I mostly agree with McConnell– despite my initial reaction. However, I was thinking about what makes some algorithms amenable to recursion while others are a bad idea.

McConnell’s examples of good recursion– quicksort and graph searching– both involve branching. Most tree algorithms are recursive: one might say a tree is a recursive data structure. The recursive algorithm uses the stack to track the branching, which is cleaner than handling your own stack. (A good programmer can replace any recursive algorithm with a stack-based one.) What makes factorials different is that there’s no branching, so the stack is redundant. So we have two classes of algorithms:

  • Branching algorithms, which use recursion to track which branches have been visited.
  • Linear (non-branching) algorithms, which should be written in a tail-recursive manner to avoid stack overflows, or written with loops when the compiler/interpreter doesn’t support tail recursion elimination.

I should add that branching algorithms are also susceptible to stack overflows, but since the stack is providing a necessary service, it can’t be avoided with a non-recursive algorithm.

So here’s why I end up agreeing with McConnell: to properly write non-branching recursive algorithms, you must (1) write them in a tail-recursive manner, and (2) run them with tail call elimination. After you write a tail-recursive function, it’s easy to accidentally modify it to no longer be tail-recursive, and the difference can be subtle. That’s why Scala provides the tailrec annotation: so a function that’s supposed to be tail recursive won’t compile unless Scala can apply the tail call elimination. If you need the compiler’s help to safely apply a technique, it’s an advanced technique, and shouldn’t be done lightly.

UCU: better than MVC

I propose a replacement for the MVC (Model-View-Controller) model for software design. The problem with MVC is primarily that View and Controller both address the same concern: the user experience. After well over a decade, software developers now know better. My new model keeps the model, but all the words are changed to avoid confusion with MVC.

UCU: Utility — Connector — User Interface

  • A Utility provides a well-defined service. For example, accessing a file or storing a collection of items. It has a contract which defines what it does, and its correctness is measured against the contract. That contract is some combination of documentation, code (method signatures, interfaces, etc.), and a test suite.
  • A Connector is how components are discovered and constructed. Thus this category includes constructors, factory methods, and dependency injection. Connectors should be simple, since a program consists of a rat’s nest of interconnected components. Bad connections are hard to test, and even harder to debug, so the only recourse is to make them hard to be buggy. Constructors should do no extraneous work, except for checking for illegal arguments. When there’s an illegal connection, the program should fail immediately. For example, a constructor for a database utility which takes a database URL should check the syntax of the database URL, but it should not try to connect to the database. (If the database is inaccessible, that’s a problem with the database, not with the program trying to access it.)
  • The User Interface (UI) is the part of the program that relates to how the user perceives and interacts with the program. Its correctness is measured against the user’s experience. (Many practitioners prefer the term UX, User eXperience. In this case, because you can program an interface but not an experience, I am using UI to refer to the software.) Humans have different perspectives, and their expectations may change over time. As a result, UIs are developed using rapid prototyping techniques. Like a Broadway stage, the UI should be designed for frequent and rapid changes. UI components that get reused frequently are really utilities, thus classes tend to migrate from UI status to utility status.

For more reading, here are my earlier thoughts, before UCU gelled. And here’s a Google Tech Talk on writing clean, testable code which influenced UCU.

Dennis Richie, RIP

Dennis Richie was one of the most important computer pioneers. His language, C, is at the foundation of all operating systems in common use today. If you want some code to run on every smartphone, every desktop, and every server, you write it in C. If you got rid of all the C compilers, Apple couldn’t build Mac OS or iOS, Microsoft couldn’t build Windows, and Google couldn’t build Android or their servers. It is no exaggeration to say that all the most important software in the world is written in C.

Apple aims for the low end

John Gruber writes:

Another new pattern: the expansion of the iPhone product line down to free-with-a-contract pricing. Apple did this not by creating a new “low-end” model, but by keeping the 3GS around for another year. This move seems so obvious that I’m disappointed in myself for not having predicted it. Operations wise, the 3GS doesn’t just use cheaper components, but because Apple has been making it for two and a half years, they’ve surely streamlined the manufacturing process.

The most important cost savings is the value of simply keeping the factory doors open. For technology components manufacturers, costs break down into two categories: fixed and operational. The fixed costs can be huge. A new chip fab (factory) costs over a billion dollars. Companies like Intel spend the first several years just paying for the R&D and the factory. An Intel processor doesn’t actually start making them any money until they have a newer high-end chip, and the “obsolete” chip gets sold at discount prices. Without the fixed costs, the discount prices have a healthy profit margin.

Video game consoles are built around this model. They keep roughly the same price and the same specs over their lifetime. For the first few years, consoles are a huge bargain: the manufacturers actually loose money on them. Near the end of their lifetime, the components are laughably obsolete, but the price is justified by the huge library of video games they run. This drives their design. Hard disks were added only reluctantly, since their platters don’t get cheaper. Chips are good. And custom anything (processors, controllers, cases) is the best, as R&D is a pure front-end cost which keeps the console distinctive in later years.

Apple knows streamlined manufacturing, and it shows in the iPhone 4’s design. Using an antenna and two panes of glass for the case minimizes materials costs. As does a small battery. Small and thin, few buttons: it’s not just for looks, it’s to maximize the factory’s lifetime. The iPhone 4 was designed to be a third-world discount product. But for now, it’s cheaper to keep making the 3GS in an old factory than to put old components in an iPhone 4.

Steve Jobs: the Perfectionist who Shipped

In thinking back on Steve Jobs, I remember an insight I had years ago, while he was at NeXT. Most people in the computer industry are either perfectionists or pragmatists. The perfectionists do well in academia, where it doesn’t matter that their big ideas take years to turn into practical products (think Donald Knuth.) The pragmatists do well in the private sector, where a steady stream of adequate hacks trump elegant designs. Think Microsoft under Bill Gates: they had a reputation for shipping a laughable 1.0, followed by a nearly respectable 2.0, and then kill the competition with 3.0. Compare the Mozilla Foundation, which disappeared and left MS Internet Explorer with a monopoly while they perfected their browser. Or think of well-designed but expensive SCSI disks, which got eaten alive by the inconvenient, cost-cutting ATA format. Or BSD vs. Linux. (Or both vs. GNU Herd, which never shipped.) And on and on.

Of all the paradoxes of Steve Jobs, this is perhaps the most important. He was a perfectionist who didn’t miss deadlines.

RIP Michael S. Hart, E-books creator

Michael Hart is not exactly a celebrity. But as founder of Project Gutenberg, he’s an inspiration. He had a simple idea, digitizing and disseminating public-domain books. Perhaps it was inevitable that paper books would end up digitized, just as hand-copied ancient manuscripts were made into printed books. But he was the first. Often times the march of progress seems inevitable, especially in retrospect; just as often the appearance is misleading. When it comes to books online, the world doesn’t begin and end with Google and Amazon. Typically their source is Project Gutenberg, and it can be your source too. Thanks to Michael Hart.

A harbinger of things to come?

I just did a Google search for “Project Gutenberg.” Rather than finding the Project Gutenberg website, Google filled the results with entries from its own e-book catalog. A Bing search took me right to Project Gutenberg.

I filled out a complaint form (Google has a link at the bottom of the page.) A few minutes later, it was giving correct results. Questions: was this a broken server, or a normal result? Was my later search influenced by my complaint? If so, did it only affect my search results? No matter how well-intentioned the folks at Google are, there is too much incentive for bias, and it is too hard to detect* for bias not to creep in over time.

*See Appendix A of this academic paper for a discussion of the dangers of search engine bias.

Digital Archiving: paper is still best

The Internet Archive has announced a project to preserve physical copies of scanned books. There are two reasons for this. First, the original book is more authoritative than the scan. Second, books last longer than hard disks.

I find this interesting in the context of my Seventh Generation project. The letters I’m writing will be printed, but I’m planning to have electronic versions as well, hosted here at leppik.net. And I’m relying on the Internet Archive’s wayback machine to keep those available long since leppik.net has gone away.