Pages

Saturday, June 25, 2011

Coding in the Clink IV - my second coding retreat at Marion Correctional Institute

On Saturday, I attended Coding in the Clink IV at MCI. It was great to see the inmates again. We all agreed they have made great strides in their learning since the last time we worked with them in March.

This was my second time spending a day programming with inmates at MCI. The first time in, I got to have my stereotypes blasted. As I said in my previous post about Coding in the Clink, one thing that struck me most was how similar the day was to a full-fledged CodeRetreat on the outside.

This time, I was reminded all day of just how careful I need to be when pairing with or coaching a less experienced developer. If I'm not careful, it's easy for me to press ahead with my own ideas and simply explain to my pair what I'm doing. That doesn't always leave my partner room to struggle with ideas, and in that moment I'm not letting them succeed in solving a problem or explaining something to me or probably other ways.

On the outside, while pairing in this way is not what I strive for, a little bit of it isn't necessarily a disaster. Unless they are in way over their head, most devs I pair with will assert themselves and claim their role a partner, even when I'm not sharing well that day. When that happens, I often "wake up" and start "playing nice" again.

But in prison, inmates are predisposed to not assert themselves to outsiders. Dan Weibe mentions it in his post "But-but there are CRIMINALS in prison!":
...The program is seen by the prisoners as a very good thing, and any attack on it ... could get the whole program ejected ... [and] life would immediately become very dangerous for the offending prisoner. Everybody knows this...
Here's the part that illustrates why I have to be extra-careful to be a good pair in the prison:
... in some cases the normal give-and-take of pairing can be hamstrung when a volunteer and a prisoner pair together because the prisoner strains to be pathologically accommodating.

To some extent, I let myself fall victim to that this weekend at CitC IV. I still think the inmates that I paired with had good experiences this time, but I would have liked to offer them more. Looking back to my first visit to MCI, I was better pair/coach that day, doing a good job at things like:
  • meeting the man where he is
  • inviting him to try things
  • asking him some questions that he knows the answer to
  • asking him harder questions so he has to stretch himself to come up with an answer
  • making small suggestions when he's stuck rather than giving answers
  • putting aside my desire to make progress in the code in favor of getting to know my partner a little and facilitating his learning
Now that I've spent some time thinking about this, I feel prepared to be the kind of coach/pair that I know I can be at the next CitC. I just wish the institution could accommodate more than one event like this per quarter.

Monday, March 28, 2011

Coding in the Clink - CodeRetreat III at Marion Correctional Institute

Since Dan Wiebe already did a great job of summarizing today's "Coding in the Clink - III" CodeRetreat at Marion Correctional Institute (MCI), he suggested I blog specifically about the two sessions I participated in.

I paired with Wes in the first cycle. He has programming experience "on the outside". Not only was he disappointed that we had to use Eclipse instead of IntelliJ, he was further disheartened that we had to work on a generic workstation that didn't have his Eclipse template(s) on it. But he got over all that quickly and we had a blast (and got some work done). Wes and I were yukking it up so much that another insider asked us to keep it down. (Wes is known in the group for his loud enjoyment.) Wes did most of the driving. I mainly suggested ways for the tests to drive the code and offered ways to break his ideas into smaller TDD steps . Wes was great about this. He feigned frustration at my suggestions while making it clear that he appreciated me keeping him "honest". It seemed to help him take a break from the all-too-common block of "I've already got it designed in my head, how do I write it with tests first?" I did occasionally contribute to our design, mainly by suggesting tests that I thought would cause interesting problems. One suggestion I made seemed to lead us down a rabbit hole, but Wes and I made the best of it by turning it into real refactoring practice (when our tests were green).

After our first session, the inside guys and we outsiders pulled our chairs into a rough circle and discussed the morning. The insiders really seemed to appreciate the learning that happens in both directions, even in pairs that have significant skill differences. One said he liked being a triple because he had the resources and perspectives of two other programmers instead of just one.

A quick anecdote about lunch: we were served "brunch" food (eggs, sausage, English muffin...) and a couple of the insiders made a point to say that we shouldn't think they eat like this all the time, that this is a nicer meal than they usually have. And overhearing them, a nearby corrections officer ("CO", never "guard") answered something like: "Don't listen to them, this is no better than what they always eat". I'm not sure what was behind this exchange. It was the only thing I heard the whole day that could even remotely be taken as playing for sympathy. Otherwise conversation was just about like what goes on at CodeRetreats on the outside: insiders asked us about what other languages we've used, they told us about their past computer experience, and two told me at lunch about a job they both worked on with a private company in Arizona from inside MCI. (I tip my hat to those guys - telephone was the only way they were allowed to communicate with their civilian colleagues, and one of the colleagues didn't initially want to work with men in prison.)

During the second (and last) cycle of the day, I was in a triple with Larry and Dave (I think). Dave was much more comfortable than Larry, and seemed to have more experience. This cycle, I was especially aware of being a coach, maybe because Larry wasn't as quick to see where Dave was going and was less assertive with his ideas than Dave was. I found myself pulled in two directions - on the one hand, I was drawing Larry out by asking him to suggest tests or suggesting that he implement code to make Dave's new test pass. On the other hand, I wanted to encourage Dave's enthusiasm and ideas. The conclusion I drew from this cycle is that I think inexperienced developers probably shouldn't be in triples unless they are very outgoing and ready to take risks. If I'm coaching someone who is shy or inexperienced or both, I'd like to be able to give them my full attention as a paring partner.

It seemed like everyone, insiders and outsiders, had a great experience. More than one insider spoke of what he learned. We worked about 9:30 to 3, so if you figure we had 30 minutes for lunch, we only had about 5 hours. Most people seemed to think that this was too short a day. Apparently, they usually have until 4:00 but were cut short today because of scheduling of other outside programs.

Many thanks to Dan, Jo Dee (Dan's "prison boss"), the COs that accommodated us, the insiders and the other six volunteers. I'd very much like to do this again.

Sunday, February 20, 2011

#RubyOnRails and partial forms

I'm working on some exercises in the Ruby on Rails Tutorial book. I noticed a lot of duplication in my new and edit views, so I thought I'd try and make it more DRY. I knew I'd need a partial, but I hadn't written one for a view yet.

I'd heard good things about the #RubyOnRails IRC channel, so now was a good time to try it out. I had to download an IRC client for my MacBook, and chose Colloquy. In almost no time, I got enough help to implement my partial. (If you aren't familiar with it in Rails 3, you can see my solution here.) I don't know why it tripped me up so much. I finally got the second argument right in the form_for correct and used it as a local variable in the submit line so that the button has the right text. And all my rspec tests pass.

gist vs pastie

I started another post (which I'll finish at another time) about using the RoR channel on IRC to get help with creating a form partial to eliminate duplication in my new and edit forms. I started writing about gist, saying it was like Pastie, and then I started looking at the difference between the two. There are enough similarities and differences to be worth an entire post, so here it is.

Gist is associated with your github account. Gist allows public and private pastes. Other gist users can clone or fork your code using a url that is created for each paste.

Pastie doesn't require a login, so it's nice for quick-and-dirty. Pastie claims to have a bot that you are supposed to be able to access right inside IRC. You send it a public message, it private messages you a link, you click the link, paste your code, click OK and the bot is supposed to announce the link to your paste to the channel. Unfortunately, I'm told it's never worked.

Pastie does have a nice feature for Rails developers that gist does not: Ruby on Rails syntax highlighting. Apparently it has C# syntax highlighting too, but it's only mentioned in the blog.

I plan to stick with gist for now, because of its connection to guthub.

EDIT: I didn't realize that gist not-only has syntax highlighting for lots of languages, it will auto-detect based on the filename extension that you give your paste (for example, this partial that I will discuss in my next post.) Now I'll stay with gist for sure.

Friday, February 4, 2011

Success with Reflector.NET

At my day job, we had a custom application in the field, a one-off, that a long-time customer had recently requested an important change for. The trouble was that we didn't seem to have source for it, and no one could remember who in our company had written it. All we knew was roughly when it was written (a few years ago) and that it was probably written with C#.NET.

So I ran RedGate's .NET Reflector on the hope of maybe getting some usable source code. I'd poked around inside assemblies before, but I'd never disassembled an executable to generate code. My hopes were exceeded - I have a very usable C# project now, with meaningful method names and so on! Here's how I did it (I'm sure this story has been countless times, but I enjoyed doing it, so I'm presenting my experience.)

I launched .NET Reflector and it asked me to pick a .NET framework to load default assemblies from, but I just clicked Cancel. File | Open ..., browse to my application, click open. After briefly poking around inside my app, I clicked my .exe in the tree and selected Tools | Disassemble, making sure that C# was selected in the language combo box on the toolbar. Then Tools | Export. Reflector wrote out a couple .cs files (Global.cs and AssemblyInfo.cs) and then prompted me for the location of an assembly that it could not locate. Fortunately, the field engineer had included that assembly with when he gave me the executable to experiment on. So I browsed to the assembly and clicked OK.

(Side note: I'm actually writing about this as I repeat the process at home, for a second time, from scratch. I hadn't taken sufficient notes at work to be able to write this post. The first time I did this, I skipped the step telling Reflector about the assembly. What that cost me was that while this second time reflector knew about the enums that were defined in the DLL, it didn't the first time. I had to find them by inspecting the method prototypes, using DevStudio's object browser, reading error messages in the code, and knowing generally what the app was supposed to do. It wasn't a lot of extra work, and I enjoyed my sleuthing but I'm glad to know that Reflector can do it for me.)

Reflector went on to write a Form1.cs, two .cs files that I recognized as containing functions common to many of my company's products, a .resources file, and a .csproj file. Things were starting to look good.

The .csproj opened fine in Visual Studio 2003. The first thing I noticed was that even though I had told Reflector where the referenced assembly was, the reference to it in the project was wrong, so I easily fixed that. Next I opened Form1.cs and was welcomed with the familiar WinForm layout of the app I had started with. Crossing my fingers, I started the solution building. 74 build errors, but many of those were duplicates. This might not be too bad.

There were ten or more errors of the form:

'System.Environment.CurrentDirectory.get': cannot explicitly call operator or accessor

on lines like this:

string str = Environment.get_CurrentDirectory();

That's not the model that .NET uses for getters! Changing the line to:

string str = Environment.CurrentDirectory;

got it to compile without even a warning. There were also setter lines I had to fix, like this:

Environment.set_CurrentDirectory(WorkingDirectory);

which became:

Environment.CurrentDirectory = WorkingDirectory;

And then there were the lines that looked to be assigning delegates:

objFMon.add_ReceiveCodes2(new __CCodeMonitor_ReceiveCodes2EventHandler(this.objFMon_ReceiveCodes2));

which I fixed in this way:

objFMon.ReceiveCodes2 += (new __CCodeMonitor_ReceiveCodes2EventHandler(objFMon_ReceiveCodes2));

Another example of this type of error was was:

FAULT_CODE fault_code = this.m_aryFaultCodes.get_Item(i);

which became:

FAULT_CODE fault_code = (FAULT_CODE) m_aryFaultCodes[i];


There were about 25 errors of the form:

Method 'MyApplication.Form1.Form1_Load(object, System.EventArgs)' referenced without parentheses

that referred to a line like:

btnAck.Click += new EventHandler(this, this.btnAck_Click);

I changed that one to:

btnAck.Click += new EventHandler(btnAck_Click);

I'm not sure what inspired me to think that the signiature was wrong except, perhaps, the vague feeling that the handler already knows that I'm giving it a method on 'this'.

Including all the delegates, there were about a dozen that I fixed by changing them from the function style to the property style.

Interestingly, Reflector didn't do a great job getting the number type right on a value given to a switch statement. I got this error:

A value of an integral type expected

on the first line of this switch statement:

switch (num2)
{
case -1f:
base.WindowState = FormWindowState.Minimized;
goto Label_0474;

case 0f:
base.WindowState = FormWindowState.Normal;
goto Label_0474;
}


because num2 was a float. Notice that Reflector added "f" after the integer values in the case lines. Searching upward in the code, there didn't seem to be any reason for num2 to need to be a float, so I changed it to an int and got rid of the "f"s. I had to do this for a second switch statement as well.

It wasn't hard to figure out that I had to cast several returns from ResourceManager.GetObject as Image or Icon as in this case:

base.Icon = (Icon) manager.GetObject("$this.Icon");

The following line called a function familiar to me, with my company's SpecialRead function. I knew that returning zero was a success code, so I was confident that I could replace null with 0.

if (SpecialRead(specialHandle, ref retValue, ref this.retLength, this.lenBufferInt16) == null)

There were 10 or 11 of those that I fixed.


This error had me stumped briefly:

Resources 'MyApplication.Form1.resources' and 'MyApplication\Form1.resx' have the same manifest resource name

'MyApplication.Form1.resources'.

But after a brief trip out to google, I decided to try deleting the .resources file. That seemed to do the trick. So with the compile and link errors gone, I cautiously pressed F5. I was disappointed when I got:

An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in MyApplication.exe
Additional information: COM object with CLSID {XXXXXXXX-YYYY-ZZZZ-MMMM-NNNNNNNNNNNN} is either not valid or not registered.


I was missing a COM object that needed to be registered.

So I took what I had built to the original engineer. His laptop was fully configured to run the product. Sure enough, my app ran successfully on his laptop. He sent it off to the customer to see that it runs the same in the field as the original. If it does, then I'll make the original requested change.


UPDATE: After we shipped the executable I built, another engineer found the original source code, in a remote, nearly neglected corner of our version control system. It's possible that the code in version control is not as current as the (now lost) code that was used to build the original exe I was given. So my next task will be to compare the two sets of source and see if I can determine if one is newer that the other

Tuesday, January 25, 2011

I'm hot on Rails, git, and CodeRetreat

Now that I'm back from CodeMash, where I attended an overview session called "Rails 3 from A to Z", I'm excited about taking a deeper dive into Rails. My first exposure to Ruby was the excellent Ruby Koans PreCompiler session at CodeMash 2010. I didn't complete all the koans at that session, and I didn't follow up and finish them afterward (although I was bitten again by the koan bug when I helped Dianne work on her Scala Koans PreCompiler session during Six Weeks of Scala), but now that I've completed Rails for Zombies, I'm totally going to go back and finish the ruby koans. Maybe before that, I'll finish another Ruby tutorial I started, TryRuby.org. It leads you through lessons and has you enter your answers at a command prompt. After that, I will probably go on to RailsTutorial.org (as recommended at the end of Rails for Zombies.) They have a free tutorial book online and they sell a pdf version and tutorial screencasts.

And after that, I've found a series of interesting articles on programming Rails on Apple's website:
And somewhere among all that, I'll want to learn the Twitter API, as I have an idea for a site related to Twitter.


Another CodeMash 2011 session that I've taken to heart is the awesome Git Immersion. While my department at work uses Subversion, I've started keeping my experiments in a git repository. And since so Ruby (and other projects) use git and/or github, it will be good to be familiar with git.

And finally, I'll be attending the 2nd Anniversary CodeRetreat in Ann Arbor this Saturday, Jan 29. This will be number 5 for me. Come join us!


Saturday, December 4, 2010

On Giving Useful Feedback

Successful agile teams do well, in part, because of the types and amount of communication they use. One place where communication is most important and comes with significant risk is giving "constructive criticism" or "corrective" feedback. I've noticed two patterns of feedback that don't work well: indirect or soft feedback, focused on not hurting the recipient's feelings and unnecessarily frank, or even blunt feedback given with little regard for the recipient's feelings. The first pattern tends to communicate insufficient information and the second pattern, while containing full information, is not presented in a manner that that is often met with defensiveness.

A friend told me about a pattern of giving feedback that I think does a good job of avoiding the pitfalls of the first two patterns. I didn't ask him where he learned it, and I could only find one reference to it: http://bit.ly/dEwGw4 The pattern is called "what-what-why" and it works like this:
  • Tell what you didn't/don't like or what you think didn't/doesn't work well
  • Tell what you would like instead
  • Tell why you think your suggestion would be more effective
For example:
  • I don't like how our team is spread out and in individual cubicles
  • I'd like it if we moved into one room and sat at a cluster of tables
  • We'd "overhear" important information and there would be fewer barriers to asking each other questions.
Or:
  • One thing that didn't work for me in the retrospective was when you would say something before someone else was finished speaking
  • I'd like it if you allow other people to finish their point and then add yours
  • I think the meeting would flow more smoothly and everyone would that they would get their chance to be fully heard.
There are a couple things I really like about giving feedback this way. First, it makes it clear that this is what I don't like and what I want instead. If I were to instead say: "You know, it might be better if you let people finish their point..." or "Don't interrupt people...", I'm not really owning that this feedback is coming from me. Second, it focuses on the desired benefit instead of focusing on anything about the person, making it less likely that they will take what I am saying personally and become defensive. And finally, I don't have to spend a lot of time thinking about how I am going to give feedback or worry much about how the person might take it. As soon as I see something that I'd like to be different, I can give the what-what-why and address the issue right away. This is great because communication is most effective when it happens early.

I recognize, however, that not all feedback is intended to cause a different outcome. Sometimes someone is doing something that I like or that I think is working well and I want to let that person know. In that situation, I use a "what-why" pattern:
  • Tell what you like/liked or what you think works/worked well
  • Tell why you like it or think it works well
For instance:
  • On the story wall, I like how you've given each team member a tag that they can put on the story that they are working on.
  • Not only does it let everyone know what everyone else is working on, but it's a good way of reminding people to only work on one story at a time.
Like what-what-why, this pattern lets me own that this is my viewpoint, it focuses on the process and outcome rather than the person, and it's a template that lets me communicate as soon as I recognize that I want to.

If you try what-what-why or what-why, I'd be interested to hear your results. Do you have similar feedback patterns that you find useful?