My adventures in Agile Software Development and Coaching from Ann Arbor, MI.
Sunday, February 20, 2011
#RubyOnRails and partial forms
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
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
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.
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
Saturday, December 4, 2010
On Giving Useful Feedback
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
- 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.
- 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.
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
- 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.
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?
Sunday, October 24, 2010
Another Thought on Certification
Besides his very interesting content, he mentioned something that else that caught my attention - the Google Qualified Developer program. It's a different approach to the question of developer certification (which I know is a hot topic in the Agile world in general and at the Agile Skills Project in particular). Google's program is free, and it focuses on accomplishments, references, community participation, and knowledge. If you become certified, you get a badge for your blog.
To be certified in a particular Google API (Chrome extensions, Maps, etc.), a developer must earn at least 3000 of the available 5000 points towards that API in any. She/he can earn points in the following ways:
- showing proof of their work (working code) - up to 1000 points
- providing references (from paying clients) - up to 1000 points
- demonstrate community participation - up to 1000 points
- take the online exam - up to 2000 points
What I like about this approach is that no one type of mastery is enough to earn certification. For instance, a developer who aces the exam can not be certified without other evidence of their competence.
I wonder what an Agile badge in this style would be like.
There are already Scrum exams. Perhaps taking one of them would earn some points. There would be a cap on how many points could be earned through exams, and exam points might expire after a certain time.
I'm not sure how working code is necessarily any indication of someone's skill in Agile, so I think we'd have to come up with something else.
Attending certain classes might be worth points. I know there's been a lot of talk about how taking a class doesn't necessarily mean a person learned anything, and I agree. So perhaps any given class would be only worth a small amount, say 200-300 points, and it would only count if you had taken the course in the past year, and only 1000 points could be earned by attending classes.
Certainly some Agile developers could provide references from customers, and capping the number of points from references would reduce the chance and affect of quid pro quo referrals. Developers who don't have professional references could earn their points in some of the other ways.
And maybe book quests or webinar quests could provide a few points, perhaps with a fairly low cap.
I know there's a non-trivial amount of administration that would be required to manage a program like this. Please join the discussion on the Agile Skills Project Google Group.
Wednesday, September 8, 2010
Scrum Developer Certification is Now Real
Hello ADS Course Participants,
The mechanism for applying for the Scrum Alliance Scrum
Developer Certification is now available. The Agile Developer
Skills course you took with us satisfies the Basic Developer Skills
portion of the certification requirement. If you also hold a
Certified ScrumMaster (CSM) certification you may now apply for the
CSD.
The application can be found at:
http://www.scrumalliance.org/
So whatever your view about the value of certification, it's happening. As for me, I'm not a CSM, so I won't be applying for a CSD any time soon.