Wow. Just finished day one of JP Boodhoo’s Nothin’ but .NET bootcamp. I’ve found it pretty tough so far. I can generally follow along ok but start to flounder as soon as we have to pick up the code and start adding to it. The exercises have been pushing me far beyond the level I normally work at, but that’s pretty much the idea. :) I don’t think it would help much to cover everything we did (you kind of have to go through it), but I’ll try and outline the main points that stick out in my memory.
First, generics and delegates. Turns out I know nothing about them. I mean, I know what they are, how they work, and even some ways to use them, but I don’t really know them. Generally it’s been a LINQ call here, a simple function pointer there, and an occasional generic class or method. Until today I’d never seen generics and delegates used and combined in such a way as to permeate through an entire design as off-handedly as most of us use int
and string
. JP just slung this stuff together like it was Hello World, while the rest of us hung on for dear life. Each individual part seemed to make perfect sense once I had seen JP’s examples, but trying to code it for myself left my undersized brain desperately trying to hold on to information like the type of a method that had a generic type PropertyValue
in a class that had a generic type Item
that took a Func<Item,PropertyValue>
and a Criteria<PropertyValue>
.
Hot on the heals of revealing my inadequacy in that area, I also discovered my knowledge of responsibility assignment and problem decomposition is sorely lacking. JP made it look effortless as he stepped through implementing a fluent interface, starting with creating a static method that returned a factory or builder for our DSL, then driving down into separate classes that would handle each phrase in our grammar. I got some good tips on how to get better at this: look back over the GRASP patterns and focus on identifying and separating out responsibilities. One interesting technique I’ll have to try out is over-zealously applying the Single Responsibility Principle (SRP), then potentially "de-factoring" some of the code if it is overly abstracted.
We also got some practice identifying a whole raft of design patterns which cropped up while going through the exercises. We had Adapter for adapting a Predicate<T>
to a Criteria<T>
, Factory for creating Criteria
instances, Composite for creating potentially infinite chains of IComparator<T>
references, Iterator both as a custom implementation and as built into .NET with the yield
keyword, and Decorators for negating Criteria
. It was great to see these naturally emerging from the application of the SRP, rather than as a deliberate refactoring toward a pattern.
I also had a long-held suspicion all-but-confirmed today. TDD/BDD can help inform your design decisions, but if you don’t know good design principles up front then you are pretty much stuffed. I was sort of holding out hope that TDD can somehow teach good design, but I think I’ve given up on that. TDD helps point out some inadequacies in design approaches, like not using dependency injection, not adhering to SOLID principles etc., but you really need to know this stuff before TDD becomes really effective. So what makes me think that? Well, today we didn’t use TDD at all, and I’m almost positive I would not have come up with the approach we did had I been using TDD. My design-fu just is not strong enough. The goal is clean code that works. This is a result of the good application of design principles. TDD can help you apply the principles, but you need to know them first.
Even the small amount we’ve done so far (today was apparently the "easy day") has opened my eyes to some areas I really need to improve upon, and given me some ideas on how to start doing so. It’s definitely given me lots to think about for the next time I’m tackling a problem, especially around responsibility assignment. Tomorrow we start on the real work, including introducing TDD/BDD. I’m really interested to see the how TDD affects how we go about segregating responsibilities.