Sunday, May 30, 2010

Seen more of the world...

She's seen much more of the world than we have.

That's what my mother-in-law said about Mausi (which means "auntie"), the maid who cleans the common areas of our apartment building and Leena hires to clean our living room and balcony a few times a week.

We were complaining to Leena's mother about what a horrible, stupid, bitter old woman the maid is. How she never remembers simple things, like Leena's told her a million times by now not to knock on the door before 11am.

Mausi is basically stupid and incompetent and lies all the time. She's unreliable and incapable of doing the same job day-in, day-out without assistance. She gets confused about what bucket to use if they're stacked in a different order in the bathroom. And she can't open the sliding glass doors on her own, or even move the chairs away from the dining table and put them back in a neat order.

She used to work a 7 hour day at the apartment building and kept asking for a raise. But back then she was doing a bad job cleaning from about 9am to noon, then having lunch with other maids from nearby, then sleeping in our garage till 4pm and going home, and she skips many days because she's not well or relatives are sick or dying (I'd be more sympathetic, but honestly, I think she's lying more than her relatives are dying).

And no one ever stepped out of their apartments into the common areas and thought "wow, this place really shines."

There's some dirt spots that have been there for a long time, and I'm sure all they take is a bit of scrubbing, that she's not putting in. Not to mention when she's done cleaning for the day, she throws her own garbage all over the place.

I really don't think Mausi has seen more of the world than me, Leena or Leena's Mummy... We've all traveled, seen other parts of India, the United States, Canada, the United Kingdom and so forth.

What Mausi has seen more of, though, is a lot more of one itty-bitty, tiny, almost insignificant corner of the world.

Friday, May 28, 2010

Sun Down


When I got home from work, around dusk, I found this on the balcony... What to call it?

Day break? Night fall? Sundown?

It made me think of the saying, "day breaks without having fallen, but night falls without breaking."

Wednesday, May 26, 2010

Snatching Defeat from the Jaws of Victory

After all the work I put in to the recruitment stuff from Cyrus Innovation for a senior Java / Ruby developer job, I lost it.

A few weeks ago I had a really good interview with their technical recruiter, Glenn. Then he gave me a code test to do. He mentioned the Ruby one, but then corrected himself and gave me the URL to the Java one. Since I mentioned I like learning new things, I dug around and fiddled with the URL for the test to find the Ruby one and did both of them, with an email explaining it was my first ever Ruby code (it was). A while after sending them to him I got a response:
I just heard from our development team, and this is one of the best code tests we've seen at Cyrus! The Java submission was, by our standards, essentially perfect, and the Ruby test was also extremely strong.

So, it looked good. I spent some time on the weekend putting together the job application document, getting it printed and signed and scanned back in.

Then Glenn arranged for me to do a pair programming type session with Alfredo on Monday for a few hours. We used Skype and its desktop sharing and voice. It wouldn't let us do both desktop sharing and video, however. That session went okay, not fantastic, but not yet a disaster and afterwards Glenn gave me positive feedback.

For Tuesday night he arranged an even longer session for me with Matt there. I felt that went even better for the two of us. And Matt sounded really positive when we got off the Skype thing.

In both sessions we did some refactoring of the code I wrote for the initial Java test and added a little new functionality. I guess I should've guessed, since in neither session did we ever finish the functionality we were adding. A lot of discussion about how to do it and in both cases we began with test cases and some refactoring to move out what looked like would be good interfaces, but never quite completed.

It was fun both times working with Alfredo and Matt. We laughed, swapped some stories about coding and platforms and weird things in tools and all that. I described some of how my project structures things and what-not. Both guys were pretty cool to work with.

A little while later I got an email from Glenn:
I just had a chance to sit down with Matt and talk about the second pairing session. As I've heard from everyone thus far, it was a real pleasure working with you, and in terms of personality, everyone here agrees that you would be a great fit at Cyrus and would get along well with the team. Matt and Alf both spoke highly of your instinct toward agile practices, and your deep knowledge of design patterns.

There were a couple of points of concern that came up in both of the pairing sessions over the past two days. Matt mentioned today that parts of your code test seemed like they were packed a bit too tightly to pull things out easily - a fact that was made apparent when adding a new parser to the project, and that your approach to refactoring the code could have been better. Alf noted yesterday that the flow between testing first, coding, and then following up with additional tests was not as smooth as it could have been. Because we'd be bringing you in at a senior level here at Cyrus, these became points of concern for the development team, and unfortunately we have decided that because of this, we have to pass at this time.

I think remote pairing is certainly a challenging prospect, and as discussed, it is largely uncharted territory for Cyrus. To that end, in the event that you relocate or travel to the NY area, I would love for you to come in and pick up the recruiting process again. We would could conduct a pairing session in person to ensure that any potential issues related to the remote connection are not to blame for the team's assessment.

It has been a real pleasure speaking with you, and the team wants to thank you for taking the time to go through our recruiting process. I wish you all the best, and please keep in touch.
So that's sort of that... I feel like I put in an awful lot of effort on this one.

I suppose part of the problem was me. When it comes to the job hunt, I do manage to mess things up that would normally be easy. If one of my teammates asked me to do the same things with the code that Alfredo and Matt did, I'd probably jump up to the board, or a notebook and start scribbling just what to do and get it done quickly. But when I'm being tested for a job interview I'm nervous and I screw up easy things. I don't handle that context very well.

Another problem is I'm sure I wasn't at my best in the evenings after full work days. Caffeine probably wasn't a good substitute for being well rested and fresh.

Maybe I also let the friendly chit-chat get away from us. Not that we shouldn't have been friendly, but discipline... Maybe I should've tried to focus a little more on the tasks at hand and solving the problems put to me. Then again, that gets harder to do after a full work day as well.

The remote stuff added to the difficulty. It's not trivially easy to pair that way even with teammates I've known for a few years and worked in-person with, so with someone I don't know, I think communication that way was a little tougher and maybe we didn't pass information back and forth very well. Without video we couldn't even use our hands for body language while talking.

So, at this point, now that I have a better idea of where they're going with the code, and given how much time and effort I've put in already, it's probably worth it to spend a few hours this weekend updating the test code I sent them and just emailing it to Glenn with "here, I've done some of what Alfredo and Matt had me doing..." and see.

Not much to lose, and lots to gain if I'm successful.

Sunday, May 23, 2010

Just the Fax

As part of the job hunt I recently had to print, sign and scan a document to either fax or email back to the potential employer. The woman who owns Pica Type, a computer dealer we're friendly with said "no problem" that she would be happy to do it for me.

But she also gave Leena a brochure of HP printers and scanners and things with a recommendation that if we want one, a low-end Deskjet with printing, scanning, faxing and copying would suit our home needs. It probably will, although we'd have to jump through some nasty hoops to get ISD in order to send faxes out-of-station...

But it got me remembering my first job at Maynard Rigby and Associates, back in 1992-1993. As the junior member, I was given responsibility for all the faxing the company did. The boss, to save money, didn't buy a fax machine. It was a spare computer with a scanner, modem and fax software. And a pain in the arse...

In order to send a fax I had to:
  1. Print the document the sender gave me.
  2. Scan each page, one-by-one, plus a handwritten cover sheet.
  3. Convert each page, one-by-one from the scan software's format to the fax software's format using some utility that only did one document at a time.
  4. Rename each page's file to the fax software's naming convention.
  5. Create a fax job in the fax program, specifying the base filename of the set of image files.
  6. Get everyone to not use that phone line.
  7. Hit a "fax" button in the fax software.
  8. Repeat steps 6 & 7 until the blasted thing was successful.
Very inefficient. Then again, as the most junior, cheapest and most technically skilled person in the office, it was less inefficient for me to do it than anyone else.

At my second job we had a real fax machine, the first one I ever used and what a complete luxury that was!

Tuesday, May 18, 2010

Big Trouble

Today's May 18th, the 30th anniversary of the biggest thing I've ever gotten in trouble for... Now don't get me wrong, I'm not admitting I did it.

It was about 8:30am on a weekend morning in Waldport, with my parents and I still in bed, and suddenly the house started shaking, and the window blinds started banging against the windows.

"Quit jumping on the bed!" my father yelled from their bedroom.

"I'm not!" I yelled back. And the house continued to shake, and the blinds continued to bang against the windows.

"Quit jumping on the bed now! Dammit!" my father yelled again.

"I'm not!" I yelled back. After a little bit things settled down again. And when we got up I was in trouble. My parents grounded me for a month for not stopping when I was told to stop and for lying about it.

Only later, watching the 6:00pm news did we find out what it was, and my parents convinced it wasn't me...

Sunday, May 16, 2010

Side Effects

The thing about a migraine-type experience is that it's like being only half alive. You find yourself walking through this tomb world, everything gets far away and kind of dull and dead.
- Perkus Tooth in Jonathan Letham's Chronic City

So, I've been taking the two medications as a prophylactic for my migraines since early March now. One is an antidepressant and one is a beta blocker. For the most part they're working. While I'm not completely without migraines, they've reduced an awful lot. And for when I do get them, there's a triptan I can take that usually relieves one.

But wow, there's side effects, too...

  • Every time I wake up I'm extremely confused and disoriented. Especially if I go to sleep when it's dark and wake up when it's light. Then I have no idea where the light came from or who's shining it through the curtains. The doctor assures me it's normal, everyone wakes up confused in the morning, but if I compare the roughly 14,800+ times I've waken up before I was on the medications with the 70 times I've woken up after taking it, I know the difference.
  • Hallucinations, especially when I'm tired. When I wake up from sleep, the view from the bed is almost always that I'm on the edge of a huge chasm, and the little foot board that sticks up from the bed is a railing to keep me from falling off. The dressing table, a couple of feet away, looks to be a mile away, across the chasm. Whoever's in the mirror on the dressing table when I wake up, I usually don't recognize them for a couple of minutes and I'd swear there's someone else in the room.
  • One hallucination I had was when Leena came in on a weekend morning I waved to her in the doorway, but my impression of it was that I was holding a picture postcard of her, with the doorway being the white border around it.
  • Songs get stuck in my head more often. It's harder to get them out once they're there, even when I'm concentrating on other things. I think early on, before I recognized this I may have blurted out some lyrics at work when someone asked me a question. It's probably a good thing I haven't been in a Soundgarden mood much to listen to Louder than Love.
  • I'm a lot more angry than I was before taking the medications. I've lost a bit of my former easy-going nature. I think I've snapped at coworkers, and I know I've written at least one email at work I regret (not the concepts, but I think I could've phrased things a bit gentler).
  • Impotence, I just have no interested in sex since starting the medications. On the other hand, before that I had the interest but was in too much pain to do anything about it, so maybe it's not a bad trade-off for the short term. But it still makes me wonder, "what the fuck's wrong with me?" (which of course, I can answer...)
Hopefully I won't be on these medications for too much longer. From what I've read the usual time is in the neighborhood of six months, give or take a little. Although the one night I forgot to take it (actually, I was super-sleepy and couldn't remember if I took it or not and didn't want to double the doses in case I had) I had a bad, bad headache the second day after that, the worst one since I started it, so maybe I'm not ready to quit them yet...

Monday, May 10, 2010

Job Hunt and a Coding Test in Java and Ruby

Thursday evening last week I had a Skype interview with the technical recruiter from a small New York City company, Cyrus Innovation.

One of the things we talked about was if I was interested in sticking with Java or if I'd be flexible about other technology, Ruby, in particular. I said I was open to other technology, but mainly focusing on Java because as it's what I'm doing day-to-day, it's what I'm most comfortable interviewing about.

At the end he said he would send me the Ruby coding test. I said something like "sure, I'll try that. Doing it in Ruby should give me a push to learn a little more Ruby". Then he apologized and said it was a slip of the tongue and he would send me the Java test.

Shortly after that I got an email from him with a link to their Java based coding test on their website. I read through it, and since he'd mentioned a Ruby test, thought I'd just tack on "_ruby" to the URL. That worked and I got a Ruby version...

So, Friday night I began work on the Java one, wrapped it up on Saturday evening and then decided to try it out in Ruby. It was essentially the same test, although the text on the website was formatted a little different and it gave the individual input files and output files instead of a zip containing them all, but really, the same test.

I worked from late Saturday night till nearly dawn on Sunday, searching Google for some Ruby help and digging in the index of The Ruby Programming Language by Flanagan & Matsumoto to find answers to my questions about getting it done in Ruby. I actually had a lot of fun doing that. With a dearth of ideas for what to program, rather than a lack of interest in learning, this gave me a specific project to do.

I continued it later Sunday morning and by early evening had the same output from the Ruby code as I did the Java code, and the same unit tests. I didn't copy and translate the code directly, I tried to use Ruby idioms where I understood them, but since it was my first real Ruby code, I doubt it's top quality.

I emailed both zip files to Cyrus Innovation with the explanation that he gave me the Java test and mentioned the Ruby one, so after finding I did it just so I could learn a little more Ruby. Hopefully that'll make some kind of good impression and back up what I said about being interested in learning (which is certainly true!).

So that's step 2 of 4 from their recruitment process done. Everything he told me about the company made it sound like a place I'd enjoy working. At this point I really want to get through the next steps and I hope they hire me, it sounds fantastic.

The only problem is step 4 of the process... I can't easily fly there to spend a day in their office and fly back. He said he'd talk to some people there about what might be done via the internet for that.

To Mock or not to Mock, that is the question...

Yoda: … But beware the mock side… Easy they flow, quick to join you in a test. If once you start down the mock path, forever will it dominate your destiny, consume you it will...
Luke: … Is the mock side stronger?
Yoda: No, no, no. Quicker, easier, more seductive.
Luke: But how am I to know the good mocks from the bad?
Yoda: You will know…

Over the last three years that I've been on a project doing extensive unit testing (not that I was ever doing unit testing before, though I'd heard the name) one of the major battles our team has had is about using mocks. Primarily it's "do you mock concrete classes or not". Mocking interfaces isn't such a question because that's the whole point of an interface, you write whatever implementation you want, and in a unit test that could very well be a mock object.

Mocking collaborators is a great way to work out the interactions between objects, and for stateless service methods allows you to isolate your tests to primarily just the object you're trying to test without by not forcing you to set up way too much data and classes and state around the other objects.

And of course, you have to think about the purpose of testing. Some say it's about using tests to design your objects. I don't disagree, but based on pretty long experience writing software, I think another purpose of tests is to "protect" your code from future changes.

We all know that code changes as the product/project or whatever evolves and goes through future changes, that's pretty much a given. Having spent years working on untested code, I like the idea that tests tell you later when changes affect code by failing. They tell you that a future change, possible to some other class, requires you to change a class you may not have thought of. It's great, and it helps reduce regression bugs later on.

At first it wasn't a question, we used JMock version 1 and that only allowed mocking interfaces. Using it we had test code that looked like:
Mock mockService = new Mock(BlahBlahBlahService.class);
mock.expects(once()).method("doSomething").with(eq(domainObjectId), eq(newValueAmount));

And so forth. It works, but the part that's inelegant is having the method name in quotes so that refactors don't automatically change it and you can't easily find where that method is called.

But then with JMock2, we got better syntax like:
BlahBlahBlahService mockService = createMock(BlahBlahBlahService.class);
addExpectations(new Expectations() { {
one(mockService).doSomething(domainObjectId, newValueAmount);
} });

But with this JMock2 also brought the ability to mock concrete classes... And that's where I think the trouble begins.

On our project we've set up "builders" for just about every domain object so that in tests we can fairly easily create a stateful domain object with any state our tests need. It works quite slick in our test code:
DomainObject domainObject = new DomainObjectBuilder()
.someStringValue("xyz")
.someOtherStringValue("abc")
.someObjectValue(new Object())
.someIntegerValue(123)
.build();

Granted, some can get fairly complicated with a test requiring building multiple objects. I'm not saying it's always 100% easy. And often if setting up data for your unit test is really hard, it's a sign your design isn't quite right and it's time to think about changing that. On the other hand, I kind of think that if the code is complicated, the test should be equally so, they go hand in hand, and if the test is too much simpler, it may not be a good test.

When we switched to JMock2, a lot of the younger, less experienced guys, who didn't have much experience at maintaining older code through generations of changes wanted to start mocking every object except the one being tested. They were concerned about "purity" and that every unit test had to be a "pure unit test" which meant that the object being tested was the only one not a mock. They wanted all other objects mocked so that each test tested only one single object.

I understand the argument about purity, but I disagree, if they're too pure, they're not future-proofing your code (in metallurgy, pure steel isn't as flexible if impurities, such as manganese aren't added). By mocking everything else, it prevents our tests from catching necessary changes in an object if the objects it collaborates with change in some way. The test is essentially "putting words in the mouth" of other objects. I think if an object is dependent upon another object, it's good for the test to be equally dependent.

Another coworker gave a good argument against "purity". How would you test this function?

public String truncateTo10Chars(String source) {
if (source.length() > 12) {
return source.substring(1, 12);
} else {
return source;
}
}

A mock test for that would be simply silly, mocking a String? It would look like:

String mockString = createMock(String.class);
String truncatedString = "123456789012";

addExpectations(new Expectations() { {
one(mockString).length()
will(returnValue(15));
one(mockString).substring(with(equalTo(1)), with(equalTo(12)));
will(returnValue(truncatedString));
} });

String actualString = truncateTo10Chars(mockString);
assertThat(actualString, is(truncatedString));

That'd be a bit of a crazy test...

One of the unit tests that a mock fan wrote in our code dealt with a domain object's method returning a particular enum value. The mock fans didn't want to build it, they wanted the test to be pure and the test of the class calling the domain object to mock the domain object to avoid "testing" the domain object itself. I tried to suggest "well, what if in the future it returns a different one of the enum's values, we'll have to change the code calling it because it's dependent upon what's returned, but the test won't tell us because it's still the same data type and it won't fail."

I lost the argument, not by logic but by not talking loud enough, not yelling my answer to "that'll never happen, this is the way we've written," and then the other mock fellows switching to Hindi to cut me out of it.

And two years later, we added a new option to the enum and changed the return values of newly created domain objects that used it. All the tests passed, and the code failed when we ran the application, because the tests used mocks and didn't tell us what code depended upon that domain object that needed changing.

Anyway, after quite a while I began to think a little different, and come to a balance. I saw an example of a concrete class where we didn't care what values were in it, we only wanted to make sure a particular method was called, and there a mock made sense.

So, what I've come to is, mocking interfaces is fine. But with concrete classes, never mock the state of it, but if your test has nothing to do with the state, it's okay. Essentially, that's mocking just the interaction, and that's essentially the concrete class's "interface".