Saturday, June 30, 2007

iPhone: Gmail for your domain

Update: (From Napoleon via comment)
I believe this is the answer to your problem: Google Hosted Email Answer

Change your account login information to: recent:username@domain.com
Making the change on my iPhone seems to do the trick. Thanks Napoleon.


I've run in to my first real issue with the iPhone: weak support for Gmail for your domain.

First of all, the initial sync doesn't work correctly. By default the iPhone postfixes all 'Gmail' accounts with @gmail.com. I'm not sure what qualifies an account as a 'Gmail' account (on the iPhone), but I'll guess that the pop and smtp google servers might be the key.

So, following the initial sync, the iPhone tried to access my email with username@domain.com@gmail.com. Not good, but not the end of the world. I was able to get around this by creating a new pop account on the iPhone and putting in the correct server and user information. Now my iPhone can receive my email, but here's the catch: it only picks up email if it's the first to find it.

What I mean by 'first to find it' is that if the iPhone finds a new message, it grabs it, but then Apple Mail never gets the message. Or, if Apple Mail grabs a new message, I never get the new message on my iPhone.*

According to Russell Whitman:
[T]his happens because google only allows one pop pull down...
Great.

I considered forwarding all mail to phone@mydomain.com and simply checking that email, but then if I ever reply it will come from phone@mydomain.com. Then, any replies to my reply will never make it back to Apple Mail. Same problem, once again.

I'm not sure how many people have Gmail for your domain, so I'm not very optimistic that this is going to be resolved soon.

* Yes, I do have the settings set to never delete messages on the server. In fact, if I log into the web interface, the message is still unread as far as Gmail is concerned.

My iPhone

My experience getting an iPhone was very similar to Scott's. Well, truthfully, the only similarity was that we both slept outside on Wednesday and Thursday. Of course, I was napping on the [pictured] beach, and only during the day.

Getting an iPhone was actually surprisingly easy this morning at the Apple Soho location. When I got there at 10am there were only 4 people in line. Apple did a great job of making sure that their stores were stocked with plenty of inventory.

Anyway, my initial opinion is that it's a great device. The resolution is great, the setup was simple, and the mail integration is very good. All the sync'ing (music, video, pictures, calendar, contacts) works well, as expected. Even using Safari is better than I expected it to be.

I do have a few complaints. First of all, where are the games? I'm not much of a game player, but I do like to play Sudoku on the plane when my laptop dies.

My other complaint is that I can't queue SMS messages when I don't have a signal available. For example, I often create SMS messages when I'm on the subway and immediately send them. I don't actually have a signal, and every other phone I've ever had would queue the messages and send them the next time I have a signal. Instead of following this pattern, the iPhone simply errors when you try to send a message and don't have a signal.

Those are small complaints though. Overall, I'm very happy with the purchase.

Wednesday, June 27, 2007

The next big language

I believe the large success that Ruby has enjoyed has made programmers eager to find the next big language (NBL). The NBL holds a lot of promise for the aspiring software developer. Become an expert in the NBL and you'll be able to command a premium while riding the next wave. If your lucky you may also design the testing or build framework that will ensure stardom in the NBL community.

So, how can you be ahead of the curve? How can you be one of the first to master the NBL? Tim O'Reilly already told us how to start: watch the Alpha Geeks.

The NBL might be a language that already exists. Dave Thomas recently blogged a bit about Erlang. Avi Bryant continues to invest his time in Smalltalk. And, it would be foolish to ignore Paul Graham and the Lisp community.

Then again, the next big language might be Ruby with YARV, Rubinius, JRuby, XRuby, or IronRuby. It could also be a language that exists but has a small community such as IO or Boo. Or, it could be a new language with more or less rope.

I think part of the problem with guessing what the next big language will be is that the question assumes there will be one language that can satisfy all your needs. The truth is, differing systems have very different needs. How many web applications have you worked on that actually needed an object oriented language? Because of the request/response nature of the Internet, most web applications could easily be built using a procedural language. There's tons of PHP sites that work just fine without objects. Sure, some sites are complicated and need a bit more than PHP4. For example, building Yahoo Store must require an Object Oriented language, right? While Yahoo Store was probably a bit complicated for PHP4, Paul Graham lists Lisp as their secret weapon of success. I'm not implying that OO languages are better than Lisp or vice versa. I'm simply pointing out that a language choice is probably not something worth making at an Enterprise level. The same is true when looking for the NBL, you aren't likely to find one that is perfect for solving all possible problems.

So then the question becomes, of the various NBLs of the future, which one is designed to address the problems you are interested in? If multi-processors and concurrency interest you, Erlang might be the ticket. If you love building web applications, Ruby/Rails isn't likely to go away any time soon. Or, if you want to build on years of experience with the same language, Smalltalk and Lisp have plenty of lessons for you to learn.

In my opinion it doesn't matter what NBL is. Most languages have unique solutions that allow you see problems in an entirely new way. That's why the Pragmatic Programmers suggest that you learn a new language every year. So instead of looking for the NBL, learn a language with a paradigm that differs from the one you use at your day job. For example, if you are currently using an OO language, learn a functional language. The established languages of today have plenty of lessons for you to learn. Knowledge of Ruby, Smalltalk, C#, Java, Lisp, Erlang, PHP, Perl, etc will ensure that you will quickly become proficient in any language you adopt in the future.

If you still insist on trying to predict the future, here's something to consider. As an industry we spent many years learning the lessons of procedural languages. Next, the majority learned the lessons of statically typed object oriented languages. Now, more than ever, we are learning the lessons of dynamically typed object oriented languages. If I had to guess, I think sooner or later the masses are going to figure out that functional languages also have power to offer.

Monday, June 25, 2007

Reading technical books

How to Read a Book suggests that when you read a book for the first time you should deliberately skip-read it, unhesitatingly skipping over detail sections. -- Martin Fowler (DuplexBook)
In the past, I read technical books very differently. Actually, I always read as fast as I could; however, I would also do every example in technical books. I found that if I did the examples, I would remember how to do something without needing to reference the book. This worked fine for me, but I was working off a poor assumption: I wouldn't want to reference the book.

Then, Obie Fernandez and I worked together on my first Ruby/Rails project. I had been doing fat client development in C# for the previous 2.5 years, so I had a lot of catching up to do. I told Obie I was a bit overwhelmed by the number of books I wanted to finish (Ruby books, Rails books, Ajax books, CSS [no more tables!]). He gave me a great tip: Read books to create a table of contents in your mind, but don't focus too much on the implementation details. I argued at first, but in the end I conceded. The truth was, I didn't need to know everything in the book. In fact, anything I did need to know, I would remember after the first or second time I had to look it up. All that I really needed from my first trip through the book was to know what was possible, not exactly how to do it.

Since that conversation, I've been very happy with the results I've gotten from mentally indexing the concepts instead of memorizing the text. And now the Pragmatic Programmers have made it even easier by offering their books in PDF form. With searchable versions of the books available it's now easier than ever to read a book well enough to know what's available and then search the PDF for the details when you need them.

The technique I'm describing is what DuplexBook tries to offer you by providing the summary and details in different sections of the book. I think DuplexBook is a great idea, but only time will tell if it is effective. A possible issue I see with DuplexBook is that the summary may provide too many or not enough details depending on your personal preference. Truthfully, I end up reading all DuplexBooks cover to cover anyway. I generally like more detail than the summary provides.

Monday, June 11, 2007

Testing: Inline Setup

In order to have an effective test suite, you must have a maintainable test suite. Only if the test suite is maintainable will all members of the team take ownership and ensure the tests are performing as expected.

Far too often I see the following behavior
  1. Run test suite before checking in.
  2. A test for part of the system you are not working on fails.
  3. Find the failing test, but don't take the time to understand the test.
  4. Determine from the failure what the issue is and change a value.
  5. Move on because the test is now passing, never knowing if the test still verifies what was originally intended.
You can claim that the above scenario only happens when you have weak developers. You'd be wrong. I work with some of the best developers in the industry and it still happens.

I agree that part of the blame is on the developer who doesn't take the time to understand the test; however, more of the blame is on the code's original author, who didn't give the new developer a fighting chance.

The original author didn't ask the right question: How can I make this code as maintainable as possible? In the previous sentence, maintainable is the keyword. Maintainable doesn't always mean DRY, abstracted, or object oriented. When it comes to tests, maintainability means: When the test breaks, what can it contain that will make it easiest to fix.

The reason the original steps were important to this entry is because they show the most common usage of tests: You've written/changed code that caused unexpected test failures. In this scenario your workflow is very simple, find the broken test and make it work. Therefore, when you get to the test, which of the following would you prefer to find?

test "when attribute is not nil or empty, then valid is true" do
validation = Validatable::ValidatesPresenceOf.new stub, :name
assert_equal true, validation.valid?(stub(:name=>"book"))
end

test "when attribute is not nil or empty, then valid is true" do
assert_equal true, @validation.valid?(@stub)
end

The first test contains all the information necessary to understand the intent and implementation of the test.

On the other hand, the second test pulled the creation of the validation instance and the stub into a setup method. While the setup method can create a DRYer test, it has reduced your ability to maintain this test. If the test file happens to be long, this problem is magnified by the fact that it may not be immediately obvious that a setup method is even being called. Even worse, if you don't notice that the setup method exists you may see unexpected behavior.

Another problem with setup is that it doesn't fail if unnecessary behavior creeps into the setup method. For example, the original author of a test file creates 3 test methods that all have common setup. He moves this behavior to the setup method and checks in. The next author needs to write some tests that use some of the shared behavior but not all. The correct thing to do is move the uncommon behavior to the original 3 tests; however, in practice I've never seen this happen. Again, you can argue that it's the developers fault; however, do you ever remember doing what I'm describing?

Of course, the above scenario assumes you even know that a setup method is executing. It's very possible to open a test file to create a new test and the file is over 80 lines long. In that case it's common to create a new test without noticing that a setup is even being executed. Now, since your test isn't taking advantage of the setup, the code from the setup is no longer common to all tests, and maintainability has again been lost.

Worse, I once opened a test that had a setup method and several tests that depended on it. Additionally, the test file also contained another group of tests that used a private method to initialize a few objects. The logic from the setup and the private method was almost exactly the same. Clearly, the two different authors didn't notice their differing implementations. Ironically, in their attempt to be DRY they created a greatly inferior alternative: Duplicate code that's not easy to follow.

What does all this mean? It means that when writing tests you should think about them in isolation. They run in isolation and the chances are when they break (if you write robust tests) they will be fixed in isolation; therefore, abstracting anything that is 'common' actually hurts maintainability. With every test, pretend it's the first and only test you are writing in that class. If that were true, it would be hard to justify those setup or private helper methods.

A question that always comes up: What if my test requires a large amount of set up code? This is often a clear sign that the domain model of the application is broken. Another explanation I've seen is, all the setup isn't actually required if you stick to testing one thing at a time. This is another reason that using one assertion per test is valuable.

Another question that always comes up: What about writing DRY code? For me, the value behind DRY has never been typing something once, but that when I want to make a change I only have to make it in one place. Since I'm advocating the duplication in a test file, you still only need to make the change in one place. You may need to do a find and replace instead of changing one helper method, but the other people who are stuck maintaining your tests will be very happy that you did.

Wednesday, June 06, 2007

Testing: One assertion per test

Limiting your tests to using one assertion is a controversial topic. I originally stumbled upon the idea on Dave Astels' blog. I liked the style of development that Dave described and decided to give it a try, that was over 2 years ago. Since then I've worked on teams ranging from 4 developers to 16, codebases in Ruby and C#, and project timelines ranging from 3 months to 8. I think it's fair to say I've given the concept plenty of chances to fall down. But, regardless of the variables, the guideline has always remained valuable.

For me, the main motivator for using one assertion per test is the resulting maintainability of the test. Tests that focus on one behavior of the system are almost always easier to write and to comprehend at a later date. I've always been better at understanding through examples, so let's take a look at some tests written to test the PhoneNumber class.

class PhoneNumber
attr_accessor :area_code, :exchange, :station

def initialize(area_code, exchange, station)
@area_code, @exchange, @station = area_code, exchange, station
end
end

class PhoneNumberTest < Test::Unit::TestCase
def test_initialize
number = PhoneNumber.new "212", "555", "1212"
assert_equal "212", number.area_code
assert_equal "555", number.exchange
assert_equal "1212", number.station
end
end

The above code works, but if the PhoneNumber class contained a bug in the initialize method, only the first failing assertion would be reported.

class PhoneNumber
attr_accessor :area_code, :exchange, :station

def initialize(area_code, exchange, station)
area_code, exchange, station = area_code, exchange, station
end
end

class PhoneNumberTest < Test::Unit::TestCase
def test_initialize
number = PhoneNumber.new "212", "555", "1212"
assert_equal "212", number.area_code
assert_equal "555", number.exchange
assert_equal "1212", number.station
end
end

# >> Loaded suite -
# >> Started
# >> F
# >> Finished in 0.006025 seconds.
# >>
# >> 1) Failure:
# >> test_initialize(PhoneNumberTest) [-:14]:
# >> <"212"> expected but was
# >> <nil>.
# >>
# >> 1 tests, 1 assertions, 1 failures, 0 errors

This is the first reason I dislike multiple asserts in one test. In this example it would be easy to notice that all three variables are set incorrectly; however, more often fixing the first failing assertion only leads to finding out what's wrong with the 2nd assertion. I'd rather know the first time I run the suite that 10 things are failing, not that 5 are failing and a few others may or may not be failing.

Another reason I dislike multiple assertions is that it's hard to give a descriptive name if you are testing various behaviors. For example, the error message test_initialize(PhoneNumberTest) [-:14]: <"212"> expected but was <nil> isn't the most descriptive in the world. You can argue that I didn't name my test correctly; however, the test_area_code_exchange_and_station_are_initialized_correctly test doesn't tell me much either. On the other hand, the test_area_code_is_initialized_correctly test tells me exactly what behavior I'm testing (or what behavior is currently wrong when a test fails).

require 'test/unit'

class PhoneNumber
attr_accessor :area_code, :exchange, :station

def initialize(area_code, exchange, station)
area_code, exchange, station = area_code, exchange, station
end
end

class PhoneNumberTest < Test::Unit::TestCase
def test_area_code_is_initialized_correctly
number = PhoneNumber.new "212", "555", "1212"
assert_equal "212", number.area_code
end

def test_exchage_is_initialized_correctly
number = PhoneNumber.new "212", "555", "1212"
assert_equal "555", number.exchange
end

def test_station_is_initialized_correctly
number = PhoneNumber.new "212", "555", "1212"
assert_equal "1212", number.station
end
end

# >> Loaded suite -
# >> Started
# >> FFF
# >> Finished in 0.01048 seconds.
# >>
# >> 1) Failure:
# >> test_area_code_is_initialized_correctly(PhoneNumberTest) [-:14]:
# >> <"212"> expected but was
# >> <nil>.
# >>
# >> 2) Failure:
# >> test_exchage_is_initialized_correctly(PhoneNumberTest) [-:19]:
# >> <"555"> expected but was
# >> <nil>.
# >>
# >> 3) Failure:
# >> test_station_is_initialized_correctly(PhoneNumberTest) [-:24]:
# >> <"1212"> expected but was
# >> <nil>.
# >>
# >> 3 tests, 3 assertions, 3 failures, 0 errors

Testing this way also helps me think critically about my domain model. If I aspire to write tests that contain only one assertion, often the methods of my domain model end up with a single responsibility.