Monday, November 09, 2009
Wednesday, August 26, 2009
Build proxies that pass through most requests, but create mock results on well-known data.
We needed to be able to verify the behavior for error conditions from our Selenium (web) tests. We had already created mock services that would return these results. We then had to manage when we connected to which endpoint, which put the expectation about behavior outside the test and in the server configuration. In order to do a single regression pass, we had to stop and reconfigure the server.
We created Moxies (mock proxies), which most of the time are just a plain passthrough to the real endpoint from our vendors' test systems. For a well known set of data (addresses in Broken Arrow, Oklahoma) the Moxy returns error conditions. Those addresses and their expectations are defined in a single class, shared both by the Moxy implementation and the tests.
Test real success and mock failure in same server configuration.
Data and its expectation is in sync (shared classes).
Code is explicit about which tests depend on which Moxies, and which specific behaviors.
With the same solution we expect to create a set of test cases that do not rely on the availability of the vendor test systems, based on similar conventions. (Eureka, CA)
We considered using wrapper objects injected via Spring to accomplish the same thing with less monkeying around with endpoints. This would avoid needing to deploy a real http mock service, and avoid issues around certificate verification and authentication. However, an injected solution would require deploying the mock software on all the client machines, and tweaking its configuration so that the wrapper bean is injected in our test environment, but not production. The injection solution also doesn't test the parsing of the error response, though that should probably be done in unit tests anyway.
If we were using a ESB like Mule, we could have configured Mule to redirect the requests based on the data, and used our mock services unchanged, and the test system configuration also unchanged.
Some solutions avoid having to use key data in the request object by manipulating http header info instead. This wasn't an option for us, unless we create some kind of signal for that header all the way through to our public pages. That seemed too invasive for our situation.
It works for us, and has a cool name*. What more could you want?
* Yes, you could probably more accurately describe this as a decorator. But Mockorator isn't nearly so awesome a name.
Monday, August 03, 2009
Self Organization, Collaboration != Fire Your LeadershipOne of the questions I've tackled with the agile teams I've worked with is how to find a balance between the need for direction and quick decisions with the open and self-organizing approaches that are recommended for teams practicing agile processes. A lot of this perceived conflict comes from people overstating the basics. In particular:
Self Organization != No Leadership. Collaborative Approach != Everyone Votes On Everything.
Self Organization: Invite owners and participants rather than assigning people to teams
Transparency: Discuss topics openly, rather than among a separate team.
Collaboration: The point of the self-organized group
Direction: The owner is responsible for driving to dates, providing major guidance (sometimes from above), and deadlock resolution.
Review: Periodic review of practices and applications is key to success.
Example: Spacely Sprockets Quality Issue
Problem: All the sprockets we've got are throwing NullPointerExceptions.
The Development Director in this case wants to delegate this task to the team. In order to do that, she asks for volunteers to be the "owner" for this issue, and Olaf steps up. After consulting with the Development Director for parameters (due dates, budget, etc) the first thing Olaf does is send an invitation: (Self Organization)
- To: yourWholeTeam
- Subject: Spacely Sprockets Quality Issue
- Hello Team,
- We need to determine whether to stay with Spacely Sprockets, change to Cogswell Cogs, or pursue some third option. if you're interested in participating, send me an email and I'll include you in tomorrow's meeting.
The group meets a couple of times (Collaboration), trades emails (via whole team mailing list, for Transparency) and works towards a recommendation. One participant suggests Gary's Gears, but Olaf shares that Gary's Gears are outside the budget for the project. (Direction). Absent of that option, the group finds consensus on staying with Spacely after an impassioned speech by George J., one of their salesmen. Olaf shares that recommendation with the rest of the team, then the Development Director, who puts the recommendation into place after a few additional questions/clarifications (more Direction).
Self Organization Problem: nobody signs on
Often you'll be expecting "the usual suspects" to show up when you invite people to collaborate. Sometimes you'll be surprised to find no responses to your hot topic. As the owner, this gives you the opportunity to find out why. This may be for many reasons:
- People are busier than expected
- People are tired of working with the issue
- People feel that the solution is obvious
- People feel that the recommendation won't result in change.
What to do:
Talk to your usual suspects with these possibilities in mind. The major advantage of the process in this case is that as the owner you are aware of these problems at the beginning rather than the end of the process.
Self Organization Problem: everybody signs on
Instead of "the usual suspects", you get the whole department. Reasons for this include:
- Concern that some aspects of the issue are being ignored or are unknown to the group
- Concern about "the expected outcome"
- Size/Impact of recommendation
What to do:
Hold a first meeting and have a round-table where you invite each participant to share what motivated them to participate.
People who feel that they're alone in a concern have an opportunity to share it, and can hear others if they exist. Those who are worried about an "expected outcome" can share their point of view. If the source is that the impact of the recommendation is huge, then team members have an opportunity to voice general concerns and witness for themselves the process by which the recommendation is being made. Sometimes just having the preliminary session is enough -- the team can identify when enough of each viewpoint exists and will drop out satisfied that their viewpoint is represented.
Another approach is to assure the team as a whole that there will be an opportunity to review the recommendation before it is "ratified." This can make team members feel less urgency about allowing others to tackle a difficult or contentious issue.
You may be tempted as the Owner to be aggressive in this case about reducing team size. Be sure that you are keeping in mind that the real goal is not to simply make a recommendation, but to have it understood and implemented by the entire team. To this end, it may be more effective to allow for some up-front "inefficiency" in order to get everyone on the same page and reach the real desired outcome faster as a result.
Direction Problem: small project
Sometimes this all seems like a lot of effort, with more time spent sending invitations and setting up meetings than it would take to do the work.
What to do:
Use IM and/or email for self-organization. Set a deadline for response (self-organization), and list your planned actions by that deadline (Direction, Transparency). Ex:
- To: yourWholeTeam
- Subject: I hate the PMD "use if x==y not if x!=y" rule
- Hey all, Can someone tell me why I shouldn't hate this rule? If nobody objects, I'll remove it on Wednesday.
- -Developer Danielle
Collaboration Problem: can't reach consensus
Rational people can disagree on a subject. Time doesn't always allow all avenues to be examined.
What to do:
This is the "big job" of the owner. It's the owner's responsibility not only to identify when it's time to just make the call, but to also make all the participants feel that they've been heard even if they haven't been agreed with.
Every time the process is used without the need for this outcome are like money in the bank. That money (trust, really) is expended in these situations. If you've got a positive balance, then this is just a a problem. If you're overdrawn, then this situation can become a fiasco. Team members must feel that the situations where the owner makes the call without consensus are rare, and due to issues that are a toss-up, or due to outside pressure. If you're doing a lot of this, it's probably an issue that should be considered in the process review.
Transparency Problem: When should I include everybody?
Is copying yourWholeTeam on *everything* really the recommendation? What if they're unlikely to care and it's just noise?
What to do:
Use a restating of the golden rule to determine what to send to the whole group: If you weren't an active participant, would you want to know about this part of the discussion? Err on the side of Transparency.
Criteria For Review
These criteria help determine success of this approach and your specific practices:
- Does everyone feel they understand the approach?
- Does everyone feel that quality recommendations are being made?
- Do team members feel involved, not dictated to?
- Are recommendations timely and within expected parameters, ie conforming to Leadership's direction?
To restate a problem from above, it's important to keep in mind that the end goal isn't a decision, its a decision whose spirit is implemented and upheld team wide. I use this approach not because it makes everyone feel good, but because it's the most effective way to get real results.
Wednesday, April 15, 2009
I grabbed my old files off of my external hard drive and: No love. No mysql. Oh, of course. Installed mysql and a visual editor, felt warm and fuzzy about that process. Created the tables with the table-creation script I created when I used this last time, made another mental note to look into rails' migrations and
Fail. My tests are talking about fixtures that have some kind of problem. This is fixed, and something else doesn't work, a nil where I didn't expect it. Oookay, bwuh? Maybe this is just old and I'll start over. It's got deprecation warnings in it too, so meh.
$ mv timemachine timemachineOldAndBusted
$ rails timemachine
Fail again. The mysql gem isn't installed by default anymore. Okay, so:
$ sudo gem install mysql
Fail again. some crap about headers and native extensions. I turn to google, and go through a lot of gymnastics around installing stuff from source, upgrading gems itself, etc. etc. I follow all the directions I see in a pretty helpful article, everything seems to be passing and:
$ mv timemachine timemachineFail
$ rails -d mysql timemachine
Fail. Now it says that the mysql gem isn't installed, but gem list says it is. Back to google, now the suggestion is to do some trickery with 64-bit mysql vs 32-bit mysql and binary hacking the broken mysql.bundle file to fix the problem.
This all feels like why Java and platform independence is still important. I'm tired of mucking with building from source into my operating system. AppEngine supports Java, right?
Wednesday, March 25, 2009
What's your favorite compliment of all time, or of the last year? Chances are, your complimentor has identified something that comes easily to you, a natural gift of yours that was appreciated. It may be more valuable to improve something that you're already pretty good at than try to rebuild yourself in something that is difficult.
Let's say it's some mode of communication, maybe written communication. Where else can you use this skill? How could you be even better at it? What is it that makes you good, exactly?
These kinds of questions, when asked about something you're already doing well have a much lower "effort." If you've picked an area you're good at, that you're excited about, you may find that they return energy to your day instead of subtract it.
Monday, February 09, 2009
Now, it's a document attached to an email. It requires just one more click to see it, and I don't do it. It had some nice information in it -- new hires, birthdays, other company news. Stuff I could read "incidentally". Clicking that link feels like committing to reading the whole document, rather than just skimming over what's already in my box.
I've been thinking about how I can lower barriers when I communicate as well. The easy one is that instead of just mailing a link (which most people won't click on), I paste the whole document into my email.
The same thinking has led to a lot of physical printouts in our office. This strikes some people as funny -- we're a tech company, yet much of our process is documented on giant sticky notes. Yet the results are clear: a giant sticky note next to the fridge communicates much more effectively than email, or a diagram in a folder in Sharepoint.
But what other barriers exist in our group that I'm not aware of? We've worked pretty hard to reduce them: we move desks when we reorganize teams so members can sit together, we aggressively encourage pair programming, our scrum process has its standups, etc.
A better question might be: how do we identify them? I'm not aware of a metric that I can rely on. Things come up in the retrospective, but that's just once every three weeks. Perhaps the real story here is about using all channels of communication.
In my email example, I have only one channel so I need to make sure it's as effective as possible. Even then, I don't really expect everyone to get the information I'm sharing.
When I give presentations, I try to say my point three times, and in three different ways: Once in text, once with a picture, and once verbally. Maybe there's a correlation there when I'm looking to drive change in our office (or just hold us to changes we've already agreed on): A poster, an email, and a verbal reminder during standup.
I'm going to look for things where I'm using only one mode of communication, and either reduce my expectations around that message or increase my modes. (make a poster, send an email, include it in our standups)