Apprenticeship/Mentorship Success!
One of my apprentices from this past summer just accepted a job… at another company. I’m totally pumped for him, but most of the people I brag to about it say the same thing with the same reaction:
<sigh_of_defeat>Shoot, we didn’t get him.</sigh_of_defeat>
As if we failed miserably.
For me, the apprenticeship/intern process has the following 4 goals (in order of importance, most to least).
- Teach and develop the apprentice as much as they can possibly absorb. This includes technical skills, sof-tech skills (like how to learn, what it means to be an engineer, passion, etc.), and soft skills (e.g. how to deal with your lead/PM/that annoying guy next door, etc.).
- Learn from the apprentice as much as I possibly can. These guys are at school at an amazing time with amazing things happening. Leech this new knowledge… it’s relatively free. (I’m unapologetically selfish in this regard… I love to learn
- Develop an environment where the apprentice feels comfortable with his mentor, and can start to learn and teach with his mentor back and forth… a true partnership.
- Oh yeah, the last/least benefit… recruiting. (Sorry Raman)
If at the end of this he happens to also be productive, great, win-win… but that isn’t the point (again, that’s my opinion).
After that list, does this look like defeat? Not to me. This looks like a dead-on success. We NAILED it. Let’s celebrate! Congrats Man. Next time we meet, I’m sure I’ll have something to learn.
[I’m at least going to pretend I played some small part in this outcome. Whether I really did or not, is debatable.]
Single File Split Buffers in Visual Studio!
Man, I’d searched for this feature time and time again. And finally found it here: http://www.kevinwilliampang.com/post/Visual-Studio-Split-Views.aspx
If you don’t want to follow the link…
Just double click that guy, or drag it downward, and you’ve split your file into two buffers. Awesomeness.
every team needs a toolsmith
Every software project is different, and there are subtleties associated with each one. Every project requires unique and specific tools, and we need someone to build them, or each member of the team needs the freedom and responsibility to do it him/herself.
I have very little (zero?) tolerance for waste when it comes to automatable processes that aren’t automated because “we don’t have time”, or “we’ll discuss it later” and then it gets dropped, or any other reason that is less than justified.
Zero Friction Development is what I’m going for here. (here is an article that I found interesting around this topic… it’s not really our fault, it’s built into our nature)
What kinds of things am I talking about? Anything that slows down my development that can be automated away to make me a happier developer. Whoa, wait, happy? Is that a requirement I have of my workplace? Absolutely. I can put up with periods of un-happiness, but long-term unhappiness is not acceptable (for me). Oops, sorry, almost derailed there for a minute.
Specific frictions I’ve addressed or have seen addressed… just so you can get an idea about the things that I’ve seen done, that might trigger an idea for you:
- Code-diff generation – On a previous project, all the code for our product was stored in the database itself (Intersystems’ Cache), so we didn’t have a real decent way to generate diff-sets for code review. So we wrote a tool to do it. A previously laborious task (at least 30 minutes for a simple changeset), with much room for human error, turned into a 30-second, enter in a task number and press ‘Go’ joy.
- Code Generation – On a previous project the best way to get where we needed was simply to inspect the structure of a piece of data, and then generate code to deal with it. You’ve probably done this one before… many times.
- Source Control Integration – Again with the Cache project, we needed a way to version our code using standard tools. We wrote a tool to bridge between the file system (for TortoiseCVS, or any other VCS) and the database storage.
- Client requires code-diff uploaded to their CMS for each completed task – Seems like a bogus business process, but it needs done. It’s painful because their CMS is slow and clunky. So I wrote a ruby script, paired with selenium, to automatically create a diff of my code and upload it to their CMS with some browser automation.
- Data generation – Ever need test datasets? Yeah, me too. Whip out some ruby and get it done.
- Tool integration – ever have two systems that need to be kept in sync? Yeah, it’s a pain, especially when neither have an API. What they both usually have though is either a command line interface or a web interface. Both of those are easy enough to script with, given some ruby magic and some browser automation.
- Time tracking – There have got to be 8 billion time tracking tools out there… if one doesn’t match your style, bust out a quick one that matches the way you work. Need it to integrate, there’s probably either a web interface, command line, or API, go for it… it’ll make you happier (hmm… there that is again!).
What other things have you automated? What are your thoughts on the toolsmith? There is a whole book about doing this type of stuff with Ruby. I’ve never read it, but I’ve heard it’s pretty good: Every Day Scripting with Ruby. Another excellent book by the guys at the prag bookshelf is Pragmatic Project Automation. It deals a lot with things we already do (build automation), but takes it further as well. Here is an intro: Pragmatic Project Automation Intro.
For sake of full disclosure, this is not a new idea, and I’m not claiming to have come up with it. It’s been tossed around for years, just wanted to bring it up again.
Question Debugging
There isn’t much I dislike more than asking a question at a high level and getting an answer back that feels demeaning because the answerer explains everything to me from the ground up [without ever pausing to breathe or giving me an opportunity to say ‘Yeah, I know, move on’]. I typically already understand the details, or don’t care at this point, which is why it's so frustrating (to me).
I hadn’t ever really thought [at least not too much] about how to solve this problem until I heard Matt verbalize it like this a couple months ago:
I first try to gauge where the person is, and try to respond at a similar level. I also adjust the response as I get visual feedback from the person as they are listening to my response.
Whoa.
I have been acutely aware of a person’s inability to do this every time I ask a question ever since I heard Matt say this (Shoot! Now I’m ruined!).
So here is how I try to debug your question (and you) so I don’t irk you off when you come to me with a question:
- Think about the problem first.
- Understand the problem/Be empathetic.
- Assess where you are in the solution space of the problem, so I can give an answer in a neighborhood relevant to you.
- Start trying to help solve the problem.
- Be clear and specific.
- Change my response based on any feedback I'm receiving from you (verbal or otherwise).
- Respond with help that leads you into the pit of success.
I’ve come up [involuntarily… sorry, just something I do] with a list of don’ts when I ask you a question as well:
- Don’t blow me away with your superior knowledge/expertise/arrogance/cockiness/awesomeness. I already know you’re awesome… that’s why I asked you!
- Don’t drown me with inane details.
- Don’t be condescending.
- Don’t be vague.
- Don’t pretend to know if you don’t. (Hint: I can tell when you don’t!)
- Don’t yell at me, or yell about someone/something else, or go off the hook for some other reason. Not cool.
Reflecting over those two lists, looks like the moral of the story: Be a good listener, be resepectful, don't be an a-hole. Sounds about right
Do you run into this (or think about it)? How do you try to solve it (from both sides of the question)?
Do You Own Your Tools?
I saw this tweet from @unclebobmartin the other day.
Why do we feel like our company ought to buy our tools for us?
This is an interesting concept to me, because, as of late, I’ve been considering pimping my work area to be mine… just as any other craftsman might.
My dad is a skilled tradesman. He’s a Mould Maker in a glass shop. He’s been doing this for over 30 years… and he is what I’d call a master craftsman. I asked about the idea of owning your own tools last weekend. He nearly interrupted my question by saying:
Yeah, I’ve got about $6000 of my own tools.
I stood floored. I had no idea.
Previously, I considered the idea to include things like my IDE (Visual Studio, since it is somewhat expensive), ReSharper, Profilers, Editors, Static Analysis Tools, and more. I also feel like this applies to books (you do read [tech] books… right?). Someone asked me the other day:
so how do you get SEP to just buy all of your books?
… uhhh, I don’t. I use my own money.
I can only assume that all machinists have their own copy of the machinist handbook as well.
I actually do have my own copy of all the tools I [willingly] use every day.
Do you?
P.S. I’ll leave you with one more thought. I challenge you to add one more piece of equipment to your tool chest (or to at least think about it)…your dev machine. Should your company provide you with a dev machine? Why not? Why so? I had never considered this until I read this article talking about Hashrocket. They all use their own machines!
Update:
I think my lack of skill in writing prose has caused some confusion or misunderstanding [Thanks for the feedback! For Reals.] This was really meant to be more about responsibility and craftsmanship than about money (or anything else). The main thought I wanted to invoke was who's responsibility is it to buy/make your tools?
I also did not try to infer that SEP doesn't buy me all the things I need (I'm sure they would, in fact... I just wonder who's responsibility it really is).
Sorry for any confusion.
Autotest… in .NET
The first time I saw autotest (presented by Anthony), the idea of Continuous Testing captured me.
I live in a .NET world most of the time, and I know of no similar solution for .NET. It’s been awhile since that first time, and I’ve tinkered here and there trying to get something comparable, but usually come up short. That is until I found watchr.
Watchr gave me the file change detection capabilities I needed, and the extensibility to do whatever I want when a file has been detected as changed. This made it incredibly easy to hook up some autotest goodness in my .NET world.
You'll have to have ruby installed, and gems. Then, the very first thing you'll have to do is
gem install watchr --source=http://gemcutter.org
Here is my watchr script:
require 'autotest.rb' watch( '^.*UnitTest.*.cs$' ) do |match| run_test(match.to_s) end
This is basically just a regex that says to watch any *.cs files that also contain the string “UnitTest”, and when it finds a change in a file matching that description, call run_test with the matched file name.
So all the magic is in autotest.rb… lets check it out:
require 'rexml/document'
def build(test_project)
`msbuild /nologo #{test_project}`
end
def mstest(test_container, test_results_file, tests_to_run)
tests_to_run = ([""] << tests_to_run).flatten
File.delete(test_results_file) if File.exists?(test_results_file)
`mstest /nologo /resultsfile:#{test_results_file} /testcontainer:#{test_container} #{tests_to_run.join(" /test:")}`
test_results = process_mstest_results(test_results_file)
File.delete(test_results_file) if File.exists?(test_results_file)
return test_results
end
def process_mstest_results(results_file)
results = {}
File.open(results_file) do |file|
xml = REXML::Document.new(file)
results[:num_tests] = xml.get_elements("//UnitTestResult").length
failures = []
xml.elements.each("//UnitTestResult[@outcome='Failed']") do |e|
failure = {}
failure[:message] = e.elements["Output/ErrorInfo/Message"].get_text
stack = e.elements["Output/ErrorInfo/StackTrace"].get_text.value
stack_match = /^.*at (.*) in(.*):line (\d+)$/.match(stack)
failure[:stack] = stack_match[1] if stack_match
failure[:location] = stack_match[2] if stack_match
failure[:line] = stack_match[3] if stack_match
failure[:stack] = stack if !stack_match
failures << failure
end
results[:failures] = failures
end
return results
end
def show_results(results)
puts "#{results[:num_tests]} tests run (#{results[:failures].length} failures)"
results[:failures].each do |failure|
puts "---------------------------------------"
puts "Message: #{failure[:message]}"
puts "Location: #{failure[:location]}"
puts "Line: #{failure[:line]}"
puts "Stack Trace: #{failure[:stack]}"
end
end
def run_test(file_name)
test_container = ""
test_results_file = "result.trx"
test_project = ""
system("cls")
system("echo Detected change in:")
system("echo #{file_name}")
system("echo Building and Testing")
test_namespace = ''
test_class = ''
test_names = []
File.open(file_name, "r") do |f|
f.each do |line|
ns_match = /^namespace (.*)$/.match(line)
test_namespace = ns_match[1] if ns_match
class_match = /^\s*public class (.\w*).*$/.match(line)
test_class = class_match[1] if class_match
test_name_match = /^\s*public void (\w*).*$/.match(line)
test_names << test_name_match[1] if test_name_match
end
end
test_names = test_names.map { |n| "#{test_namespace}.#{test_class}.#{n}" }
build(test_project)
results = mstest(test_container, test_results_file, test_names)
show_results(results)
end
The key parts (I think) are the fact that I’m using MSTest to run my tests (this can easily be modified to run your framework of choice… note MSTest is not my choice
). The result parsing is also specific to the MSTest output format, but should be simple enough for any framework that can output XML. Also, I'm making some assumptions based on my project... we've got one unit test project, so I know I can run tests in a single DLL, and rebuilding only that project, I don't have to worry about choosing the correct project and output dll to build and run tests in.
To get the thing up and running, just run
watchr <path to watchr script>
Please, use/adapt/give feedback/whatever at will.
Go forth and autotest, .NET comrades!
Stable or Stagnant?
In a recent discussion with a co-worker we made an observation on the topic of progress. Things that look like they are working, appear to be stable. However, from another viewpoint that very same subject is stagnant.
Which camp do you live in?
I’d say I [mostly] live in the viewing things as stagnant camp (it’s nice and cozy in my camp, won’t you come join me?). I’m not trying to say there is anything wrong about believing and adhering to things that we know already work (stable), but what I am trying to say is that we can use stable as a platform to continually achieve better.
If you live over in stable-ville, you’re probably asking questions like:
- Why change it if it already works?
- We’ve done this before, let’s just do it that way, it’s safer (why would we possibly introduce risk!?).
- We made money doing this the last time, if we do it the same way, we’ll make money doing it again.
I admit, you ask great questions. It’s hard to win an argument against [apparent] concrete profitability.
Here are my sentiments, however, in response to those questions.
First you must assume that things can always get and be better. I’m not asking to make huge sweeping changes and walk away. Rather, embrace the stable approach, incrementally make changes, measure, rinse and repeat.
Of course, if things seem to be broken, or you seem to have hit some ceiling (most likely artificial), you may need to take a step back, and take a completely alternative approach.
The key to making change to any subject for the sake of improvement is measuring. Know what it is you’re trying to optimize, measure it, make the change, and measure it again. That is the only way to know if you actually got better, worse, or had no impact at all. (In a slightly related note, Steve McConnell, in Code Complete 2 drove this into my skull at least 50 times during his performance tuning chapters, and I agree whole-heartedly).
Oh, and on that profitability question? You better always be changing (don’t forget to measure!) otherwise you’re gonna get leapfrogged into oblivion and your competitor that you didn’t even know existed is going to be raking in all your cash. Likewise with risk. If you’re not taking risks and just sitting in your comfort zone, you’re probably not growing as an organization or as an individual.
For me, it’s all about continuous improvement. Don't let stable be the enemy of change, strive for improvement.
If you’re not getting better, you’re getting worse… right?
Testing Events with Awesomeness
How many of you have written this code when testing an event?
[Test]
public void LameTest()
{
var objectWithEvent = new ClassWithEvent();
var awesomeFired = false;
objectWithEvent.AwesomeEvent += ( o, e ) => awesomeFired = true;
objectWithEvent.DoSomethingAwesome();
Assert.IsTrue( awesomeFired );
}
or its big brother:
[Test]
public void LessLameTest()
{
var objectWithEvent = new ClassWithEvent();
var awesomeCount = 0;
objectWithEvent.AwesomeEvent += ( o, e ) => awesomeCount++;
objectWithEvent.DoSomethingAwesome();
Assert.AreEqual( 1, awesomeCount );
}
Every time I write that code, it feels WET (read: not DRY), especially when I’m doing it for more than one event in the same test.
What I’d like to see is something like:
[Test]
public void AwesomeTest()
{
var objectWithEvent = new ClassWithEvent();
var awesomeTracker = new EventTracker<EventHandler>();
objectWithEvent.AwesomeEvent += awesomeTracker.Delegate;
objectWithEvent.DoSomethingAwesome();
Assert.IsTrue( awesomeTracker.WasCalled );
}
Yeah! Now that’s what I’m looking for. Is this possible?
Yup.
How? Let’s see.
So basically what this means, is that we have to generate a method (at runtime) that matches the signature of the delegate we pass to the tracker as the type argument (so it can be added as a handler for the event). Inside the method, we need to update our tracking variable (either setting a flag, or incrementing a counter). We can ignore any of the arguments passed to the delegate (e.g. the sender, event args, or anything else), since for our purpose we really don’t care about them. What I think is so cool about this is that it works for ANY type of delegate you pass to it! Sort of like generics, but for methods (makes sense in a meta sort of way).
Here is the implementation:
public class EventTracker<TDelegate>
where TDelegate : class
{
public static implicit operator TDelegate( EventTracker<TDelegate> tracker )
{
return tracker.Delegate;
}
public EventTracker()
{
var delegateMeta = typeof( TDelegate ).GetMethod( "Invoke" );
var delegateParams = delegateMeta
.GetParameters()
.Map( param => param.ParameterType )
.Prepend( GetType() )
.ToArray<Type>();
var invokedMethod = GetType().GetMethod( "Invoked", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public );
var dynamicHandler = new DynamicMethod( "", delegateMeta.ReturnType, delegateParams, GetType(), true );
var generator = dynamicHandler.GetILGenerator();
generator.Emit( OpCodes.Ldarg_0 );
generator.Emit( OpCodes.Call, invokedMethod );
generator.Emit( OpCodes.Ret );
Delegate = dynamicHandler.CreateDelegate( typeof( TDelegate ), this ) as TDelegate;
}
public TDelegate Delegate
{
get;
private set;
}
public int CallCount
{
get;
private set;
}
public bool WasCalled
{
get { return CallCount > 0; }
}
public bool WasNotCalled
{
get { return !WasCalled; }
}
// called via the dynamic method
private void Invoked()
{
CallCount++;
}
}
This is my first foray into IL generation… not exactly my forte. A little more on IL generation next time. Oh yeah, must give credit where it is due… thanks to Shawn for the help when my fu was weak.
connect windows mobile 6 Emulator to ActiveSync
This might be more for me, than for anyone else, but I had an issue yesterday trying to connect my Windows Mobile (Classic 6.1.4) Emulator to ActiveSync (4.5) on my machine so I could tweak some files over on the device.
Turns out its pretty simple…
In the File –> Connections dialog check the “Allow connections to one of the following” box.
This will allow DMA (which is what it wants)… and it should work magically.


