Monday, February 22, 2010

Replacement iPhone

Those Apple folks are pretty cool -- my iPhone 3G had developed a crack starting at the dock connector so I took it in to one of the Apple stores in town and they said it still was under warranty and replaced it with a brand new one (3G, no free upgrade to 3GS). I had researched the problem a bit before making the appointment to take it in and found that my iPhone was not the only one with that problem, but I was a bit skeptical that it would be as easy as it sounded to get it swapped out for a new one.

Sure, it shouldn't have cracked in the first place, but they definitely made good on it in my book. I assume the warranty doesn't reset with the new hardware (although maybe that assumption is wrong) but it doesn't matter, really -- I now have a brand new device that should last well beyond the original warranty period.

If you have an iPhone, go to the Apple Service and Repair site and enter your hardware serial number to see if you are covered. Don't assume that using a protective case prevents the crack from occurring; although I don't use a case, it doesn't seem to be related to anything a case could prevent from happening. My guess is that the problem is related to repeated use of the dock connector, and everyone uses that.

UPDATE 3/8/2010: The new iPhone had a dud battery -- it seemed like about 8 hours was all it was good for even with minimal active use (e.g. sitting on the night stand overnight). I watched it one day during the day and noticed that after about 6 hours following a full charge it would be down to 25%, again with minimal use.

Over the past weekend we were in the shopping center that has the Apple store where I got the replacement, so I stopped in to see if there was any chance of getting an appointment with the Genius Bar. This was a busy Saturday at a busy location, and the concierge said she had one spot, which was an hour and ten minutes away. That actually wasn't going to be a big problem because we had just gotten there, but then she looked in the Mac queue (she had looked previously in the iPhone queue) and saw that they had a slot coming up in 25 minutes, so she gave me that one instead, a nice touch.

At the appointed time a tech ran a piece of diagnostic software on the phone that seemed like it was more for show than anything (e.g. the tech noticed it had a handful of dropped calls, which seemed significant to him, although I don't see how that has anything to do with anything relating to the battery, but hey, who am I to complain?) and deemed it a dud. He grabbed out a new one from the back, swapped the SIM and did the paperwork, and we were out of there.

I am happy to report that the battery in this latest handset is working extremely well, holding a charge for a couple of days under normal use, and once again I felt like they had done right by me, even with the hassle of having to take the replacement unit back. That's good customer service.

Friday, February 12, 2010

Aggregate extension method in LINQ

It seems that I never stop finding new reasons to love LINQ and today I've found another: the Aggregate extension method.

Here's the scenario: we have a Silverlight application with a UIElement that binds to an IEnumerable of type string where the contents of each item is an error or validation message. There are times when instead of binding to the list I just want a concatenated string of all the items in the collection with a CRLF stuck on the end of each. Just for kicks I asked my friend Nick what at the time felt like a silly "how many convoluted ways can you think of to solve this simple programming problem, and how would you do it in LINQ?" question and, being the genius that he is, he suggested using the Aggregate extension method.

I already had a passing awareness of .Aggregate() but to be honest it hadn't occurred to me that it would be useful for something other than aggregating numbers, and at any rate I found it a bit unintuitive to use initially. It turns out, of course, that the accumulator can work on a series of strings just as easily as, say, ints, and it really couldn't be much simpler.

Here's how it looks as a C# Statement in LinqPad:

string[] words = { "foo", "bar", "ski" };
words.Aggregate(string.Empty, (seed, w) => seed + "\r\n" + w).Dump();

And in the Results pane:

foo
bar
ski

Pretty slick!

Wednesday, January 20, 2010

If It's Not Information It's Just Noise

If you write code for a living, you don't have to be around very long before the subject of coding standards comes up, and it is a subject about which people tend to have very strong opinions. My own very strong opinion is that most so-called standards really are styles, and that they do not rise to the same level as standards. How many spaces you use to indent a line of code is a style (or do you use tabs?); whether your code compiles when you don't have a trailing semicolon is a standard.

Call me pedantic (you wouldn't be the first) but I think the distinction is important. When people are discussing the formatting of any given piece of code, it is easier for the proponent of a certain style (opening curly braces, for example) to get his way if he can appeal to the authority of the "standard" to support his position (reference to the logical fallacy fully intentional). Just because that person was pushy enough to get his way codified doesn't make it right, though.

Countless hours have been spent discussing, drafting, arguing about, and then conforming code to some standard or another, and that's a sad waste of time. Worse, for me anyway, is that many coding standards make code harder to read, such as requiring comments on every method, requiring regions (collapsible blocks in which code lives in a code file) around every conceivable form of code in a file and in a certain order (sometimes even where there is nothing actually *in* the blocks, or when the block already has a collapsible region with a title!), and worst of all, requiring that something like a property getter or setter take up four lines of code when it could all fit on one.

Standards that don't help your code convey something important or interesting about the code should be eliminated, at least as far as what a coder has to deal with on a day-to-day basis. If stylized code makes it easier for the source control tool to diff and merge, well, require running it through a prettifier before committing changes. Just make sure the prettifier can reverse-engineer the code back to *my* way before I have to see it!

Monday, January 11, 2010

Silverlight UIAutomation Testing -- Using WatiN to navigate to a page and White to test a Silverlight app

I had the need recently to automate testing of a Silverlight app and ran into a problem using white (could anyone have come up with a more difficult name to search on?) where white does not provide functionality to get a reference to a hyperlink in the DOM and click it in the way that, for example, WatiN does. The scenario where this came up is there is a web app with a landing page that has a link to the page hosting the Silverlight app and we need to click through the link into the Silverlight hosting page.

I briefly thought about just cribbing the functionality from WatiN and extending white's capabilities but quickly discarded that idea as too complicated and out of concern that it would become a maintenance nightmare.

The solution I came up with is to use WatiN and white together in a hybrid fashion, where WatiN spins up a browser instance and then white attaches to that browser instance using the ProcessID of the instance from WatiN. White doesn't expose an Attach method up in the InternetExplorer class where Launch lives, but it does have it down in White.Core on the Application class, so it was a simple matter to create an extension method on the InternetExplorer class to expose one that can be used in unit tests.

It goes a little like this (warning: horrible formatting):

public static class WhiteExtensions
{
// the extension method to simplify usage
public static InternetExplorerWindow Attach(
this InternetExplorer val, int processId, string title)
{
InternetExplorerFactory.Plugin();

return (InternetExplorerWindow)Application
.Attach(processId)
.GetWindow(title);
}
}

// new up a browser with WatiN
Watin.Core.IE watin = new Watin.Core.IE(url);
watin.Link(Find.ByText("foo")).Click();

// spin up white and attach to the browser that WatiN started
White.WebBrowser.InternetExplorer white = new White.WebBrowser.InternetExplorer();
white.Attach(watin.ProcessID, "browser window title");

// get the Silverlight app reference from the white browser reference
White.WebBrowser.Silverlight.SilverlightDocument sl = white.SilverlightDocument;

// do stuff
sl.Get<Button>(SearchCriteria.ByAutomationId("SomeButton")).Click();

Tuesday, December 15, 2009

787 First Flight

Monday, December 07, 2009

Ender's Game come to life

Monday, November 30, 2009

Unit Testing as an afterthought

Something you hear a lot in the development world is "We'll write unit tests if we have time," which usually means "we'll go back and take a look at the huge stack of code we are about to toss over the wall to QA and try to write tests for all of it." Quite often it is the case that some tests are better than none, but as part of a mature development process, this is the wrong way to view unit tests.

If your motivation for writing unit tests is that you do it so that you can put a check mark on a development process list, you are missing the point of writing the tests in the first place. Writing the tests as you go (as mini test harnesses to help quickly test and guide development, or immediately along with development to test edge cases and cyclomatic complexity pathways) helps you to write more accurate code more quickly, which is what most people would say their goal is in the first place when they set out to commit acts of programming on their trusting clients' code bases.

Very often it is the case that writing tests for a given piece of code leads to a much better understanding of the code under test, which helps to a) write the correct code and b) be able to explain and understand it later when you need to look at it again, or when a colleague or QA tester comes calling.

Writing unit tests is like showing your work in elementary school -- the point is not to write down an answer, it is to work through the process so that you understand what you actually are doing. And with unit tests we have an added bonus: the tests are repeatable and automatable, and they inform future developers (including the author of the code) of the intent and purpose of the code under test quickly and clearly, in a way that just reading the tested code alone cannot.