Archives
-
Being a better developer by studying other peoples code
The course is wrapped up and I have 2 more entries to get out. Next week I'm at the Edmonton User Group to present about Fit and DDD so catch me there if you're in town. As the course winds down my brain is still in overdrive thinking about things, both technical and personal. I'm going to post a follow-up to the 6 months to a better developer spiel that's been going around, as I feel I didn't do the original question enough justice (that's justice, not Justice).
One thing Scott Hanselman mentioned in the his podcast on the subject was that you could get better by looking at other peoples code. I'm a strong believer of this and have about 200mb of projects squirreled away that I've collected over the years. From time to time I dump them as I realize they're junk, but some examples shine on and I just keep them around as reminders and ideas. I'm always finding little development nuggets in code that I come across (even the entire app is a gong show) and they go onto my USB drive for later reflection. When I was a graphic designer we would keep a physical file cabinet (I called mine a graveyard) where we just kept clippings. Ideas or designs or styles that we liked (or didn't like) would go here and from time to time you would peek inside. Everything was organized by subject or topic so sometimes I was doing a design that would require teddy bears and out came the teddy bear folder from the graveyard, to spark an idea. My USB drive is like that (although I'm trying to find a good way to organize it better than what folders can do).
Anyway, here's a list of projects that I've looked over and find to be valuable to check out if you're looking for coding examples, ideas, and snippets that I consider little gems in the open source world and refer to from time to time.
CC.NET is a great tool, but people keep forgetting it's open source and there's unit tests for everything. It's not a bad implementation and has some good ideas around separation of concern and handling providers. The code is clean and makes good use of interfaces almost everywhere.
Both of these unit test frameworks are open source and their own source is a pretty good resource to check out. Good overall design and good use of various patterns like proxies, listeners, and reflection. You can imagine how hard it might be to unit test a unit test framework but these guys did it and did it right.
This is a utility library written in Java but it follows Eric Evan's Domain Driven Design principles and is a good reference for such. There's a C# version kicking around on SourceForge you can check out (but it's not completed yet and I can't track down a URL for it).
Blog engines that have evolved. As Scott points out, dasBlog is the abyss but there's some good stuff in there either he, Clemens, or the community has written. Especially check out the HTTP handlers if you've never written one before. Again, lots of unit tests here. I feel the model falls down a bit with the XML dependency and requirement for test files, but all in all they're both good resources to study.
Despite my aggregation with this project switching the UI every chance it can get and tying itself to commercial libraries, it's a pretty good example of a WinForms RSS reader. The implementation does suffer from memory bloat (running it just chews up as much memory as it can) but overall it's a good application design and there are some nice things in here like HTML parsers, interacting with RSS, and a well designed plug-in system.
I can't this is a great example of code to learn by, but it's the only open source IDE out there that contains concepts you could follow (and for the most part, they're not that bad). You really can't crack open Eclipse and learn how it ticks but SharpDevelop is written in all C# and pretty easy to follow.
This is an odd name for a project, but it's an excellent reference app for an eCommerce web portal system which offers a forum, CMS-like functionality, blogs, polls, RSS feeds, shopping, and other goodies. A pretty good example of a nicely done ASP.NET website that can not only be used for studying, but building your own site.
The codebase isn't too bad here (although I feel there's a little too much in the ASPX code behind) but is a good example of a digg-like community site. Lots of AJAX here with user controls so if you're looking to build the next community, give kicks a look at for ideas.
CSLA is an application framework for building business apps. Rocky Lhotka has done an excellent job with the codebase and while I'm not a fan of Active Record or domain objects that know how to persist themselves, the code is clean and a good tool to study from. Rocky keeps it updated frequently.
While it's still only alpha, Jeremy Miller is doing a bang-up job on making this an indispensable tool for Fit development and using TDD to drive it out. Nice work here to take a look at even in it's young stages.
Omea reader is supposed to come online with it's source code released by JetBrains. To date they haven't released it yet but plan to. I emailed them a few months ago and they were still working on getting the code ready. Hopefully with a company like JetBrains behind it, the code base will be interesting to examine.
Feel free to add your own to the list via the comments (I'm sure I missed a few key ones) and go ahead and challenge me on my findings here as I may be off on some projects, however this is my opinion and YMMV on your own findings.
-
Fonts and Colours
A lot of people have been asking me about my Visual Studio settings, as I tend to favor a black background over the traditional white. Traditional. Heh. Remember the DOS days when it was all black? Guess that's just my old school showing through, but I prefer it and feel it's easier on the eyes. I use this in my blog posts as well as any presentations I do and my day to day work.
You can download them from here. They're based on Scott Hanselman's settings file that he posted here, except mine uses only Consolas, the only programmer font you'll ever need. You'll need the Consolas font installed for it to work (but I think it'll fall back to Courier New if you don't). If you're on Vista, you've already got it. If you're on XP you can grab the Consola Font Pack here.
Works for me. YMMV.
-
Nothin but .NET - Tips and Tricks - Day 3
Coffee, coffee, coffee. Oh we need coffee. Okay, got it now we're ready. It's been a crazy week and it's getting crazier. JP is coding at about 8,000 words and using about 40,000 ReSharper shortcuts per minute now. He's also talking at about 10,000 words a minute. If you blur your eyes when looking at him, he begins starts to look like Neo in the Matrix. There is no mouse.
Service Layers are Tasks
I really like this paradigm of naming the service layer classes. Rather than having something like CustomerService.GetAllCustomers(), it's named CustomerTasks.GetAllCustomers(). I've always used the ServiceXXX naming strategy but it makes more sense to name things as tasks because in reality, they are tasks. Tasks in the service layer to serve up information to external consumers. It's about readability so choose whatever works for you.
Recording Ordered Mocks
We were working on the database today (gasp) but started mocking out a data gateway. I found it amusing that we couldn't record an ordered mock (but there was a way).
Hey Oren, check this out (in case you didn't know). This block fails:
54 [Test]
55 public void Should_be_able_to_get_a_datatable_from_the_database_ordered_failure()
56 {
57 using (mockery.Ordered())
58 {
59 using (mockery.Record())
60 {
61 Expect.Call(mockFactory.Create()).Return(mockConnection);
62 Expect.Call(mockConnection.CreateCommandForDynamicSql("Blah")).Return(mockCommand);
63 SetupResult.For(mockCommand.ExecuteReader()).Return(mockReader);
64 mockConnection.Dispose();
65 }
66
67 using (mockery.Playback())
68 {
69 DataTable result = CreateSUT().GetADataTableUsing("Blah");
70 Assert.IsNotNull(result);
71 }
72 }
73 }
The error is:
[failure] DBGatewayTest.Setup.Should_be_able_to_get_a_datatable_from_the_database_ordered_failure.TearDown
TestCase 'DBGatewayTest.Setup.Should_be_able_to_get_a_datatable_from_the_database_ordered_failure.TearDown'
failed: Can't start replaying because Ordered or Unordered properties were call and not yet disposed.
System.InvalidOperationException
Message: Can't start replaying because Ordered or Unordered properties were call and not yet disposed.
Source: Rhino.MocksIn this case, the mock objects were created from interfaces that inherited from IDisposable. However it was a simple change to put the ordered call inside the record (because we don't care about ordering on playback). This slight change now works:
33 [Test]
34 public void Should_be_able_to_get_a_datatable_from_the_database()
35 {
36 using (mockery.Record())
37 {
38 using (mockery.Ordered())
39 {
40 Expect.Call(mockFactory.Create()).Return(mockConnection);
41 Expect.Call(mockConnection.CreateCommandForDynamicSql("Blah")).Return(mockCommand);
42 SetupResult.For(mockCommand.ExecuteReader()).Return(mockReader);
43 mockConnection.Dispose();
44 }
45 }
46
47 using (mockery.Playback())
48 {
49 DataTable result = CreateSUT().GetADataTableUsing("Blah");
50 Assert.IsNotNull(result);
51 }
52 }
Just in case you ever needed to do have run into this problem one day.
More Nothin
JP is doing this 5-day intensive course that stretches people to think outside the box of how they typically program and delve into realms they have potentially not event thought about yet, about one per month. For the next little while (he's a busy dude) he's going to be travelin' dude. In October he'll be in New York City. In September he'll be in London, England and other locations are booked up into the new year.
If you want to find out more details about the course itself, check out the details here and be sure to get on board with the master.
-
Being descriptive in code when building objects
As we're working through the course, I've been struggling with some constructors of objects we create. For example, in the first couple of days the team was writing unit tests around creating video game objects. This would be done by specifying a whack of parameters in the constructor.
9 [Test]
10 public void Should_create_video_game_based_on_specification_using_classes()
11 {
12 VideoGame game = new VideoGame("Gears of War",
13 2006,
14 Publisher.Activision,
15 GameConsole.Xbox360,
16 Genre.Action);
17
18 Assert.AreEqual(game.GameConsole, GameConsole.Xbox360);
19 }
This is pretty typical as we want to construct an object that's fully qualified and there's two options to do this. Either via a constructor or by setting properties on an object after the fact. Neither of these really appeal to me so we talked about using the Builder pattern along with being fluent in writing a DSL to create domain objects.
For the same test above to create a video game domain object, this reads much better to me than to parameterize my constructors (which means I might also have to chain my constructors if I don't want to break code later):
36 [Test]
37 public void Should_create_video_game_based_on_specification_using_builder()
38 {
39 VideoGame game = VideoGameBuilder.
40 StartRecording().
41 CreateGame("Gears of War").
42 ManufacturedBy(Publisher.Activision).
43 CreatedInYear(2006).
44 TargetedForConsole(GameConsole.Xbox360).
45 InGenre(Genre.Action).
46 Finish();
47
48 Assert.AreEqual(game.GameConsole, GameConsole.Xbox360);
49 }
Agree or disagree? The nice thing about this is I don't have to specify everything here. For example I could create a video game with just a title and publisher like this:
34 VideoGame game = VideoGameBuilder.
35 StartRecording().
36 CreateGame("Gears of War").
37 ManufacturedBy(Publisher.Activision).
38 Finish();
This avoids the problem that I have to do when using constructors in that I don't have to overload the constructor.
Here's the builder class that spits out our VideoGame object. It's nothing more than a bunch of methods that return a VideoGameBuilder and the Finish() method that returns our object created with all it's values.
44 internal class VideoGameBuilder
45 {
46 private VideoGame gameToBuild;
47
48 public VideoGameBuilder()
49 {
50 gameToBuild = new VideoGame();
51 }
52
53 public static VideoGameBuilder StartRecording()
54 {
55 return new VideoGameBuilder();
56 }
57
58 public VideoGameBuilder CreateGame(string title)
59 {
60 gameToBuild.Name = title;
61 return this;
62 }
63
64 public VideoGameBuilder ManufacturedBy(Publisher manufacturer)
65 {
66 gameToBuild.Publisher = manufacturer;
67 return this;
68 }
69
70 public VideoGameBuilder CreatedInYear(int year)
71 {
72 gameToBuild.YearPublished = year;
73 return this;
74 }
75
76 public VideoGameBuilder TargetedForConsole(GameConsole console)
77 {
78 gameToBuild.GameConsole = console;
79 return this;
80 }
81
82 public VideoGameBuilder InGenre(Genre genre)
83 {
84 gameToBuild.Genre = genre;
85 return this;
86 }
87
88 public VideoGame Finish()
89 {
90 return this.gameToBuild;
91 }
92 }
This makes my tests read much better but even in say a presenter or service layer, I know exactly what my domain is creating for me and I think overall it's a better place to be for readability and maintainability.
This isn't anything new (but it's new to me and maybe to my readers). You can check out the start of it via Martin Fowler's post on fluent interfaces, and the followup post early this year on ExpressionBuilder which matches what the VideoGameBuilder class is doing above. And of course Rhino uses this type of syntax. I guess if I'm 6 months behind Martin Fowler in my thinkings, it's not a bad place to be.
-
Nothing but .NET - Tips and Tricks - Day 2
It's the second day here with JP and crew. Yes, posting on the 4th day isn't quite right is it, but 12 hours locked up in a room with JP is enough to drive anyone to madness. Really though, it's just completely draining and for me I have an hour transit ride and a 45 minute drive to get home so needless to say, sometimes I get home and just crash. Anyways, expect days 3 and 4 to follow later today.
Okay so back to the course. After the gangs morning trip to Starbucks we're good to go for the day (and it's going to be a long one).
Decorators vs. Proxies
Small tip for those using these patterns, decorators must forward their calls onto the objects they're decorating, proxies do not have to. So if you have some kind of proxy (say to a web service or some security service) the proxy can decide whether or not to forward the call onto the system. When using decorators, all calls get forwarded on so decorators need to be really dumb and the consumer needs to know that whatever it sends the decorator, it'll get passed down the line no matter what. Good to know.
ReSharper Goodness
I'm always happy seeing new stuff with ReSharper and I don't know why I didn't get this earlier. NAnt support in Visual Studio with ReSharper. Oh joy, oh bliss. I was struggling with NAntExplorer, which never really worked. I never realized ReSharper provides NAnt support, until now. Load up your build script and hit Ctrl+F12 to see all the items, or do a rename of a task or property. Awesome!
Builds and Local Properties
A new tip I picked up is using local property files and merging them with build scripts via NAnt. Traditionally it's always been a challenge when dealing with individual developers machines and setups. Everyone is different as to what tools they have installed, where things are installed to, and even what folders they work in. A clever trick I've done (at least I thought it was clever) was to create separate environment configurations with a naming standard, then using post-build events (NAnt would have worked as well) and copying them as the real app.config or web.config files. This is all fine and dandy, but still has limitations. I think I've found a utopia with local property files now.
So you have your build script but each developer has a different setup for their local database. Do you create a separate file for each user? No, that would be a maintenance nightmare. Do you force everyone to use the same structure and paths? No, that would restrict creativity and potentially require existing setups to change. The answer my friend is blowing in the wind, and that wind is local property files merged into build scripts to produce dynamic configurations.
Typically you would create say an app.config file that would contain say your connection string to a database. Even with everyone on-board and using a connection string like "localhost", you can't ensure everyone has the tools in the same place or whatever. This is where a local property file comes into play. For your project create a file called something like local.properties.xml.template. It can contain all the settings you're interested in localizing for each developer and might go like this:
1 <?xml version="1.0"?>
2 <properties>
3 <property name="sql.tools.path" value="C:\program files\microsoft sql server\90\tools\binn\" />
4 <property name="osql.connectionstring" value="-E"/>
5 <property name="osql.exe" value="${sql.tools.path}\osql.exe" />
6 <property name="initial.catalog" value="NothinButDotNetStore"/>
7 <property name="config.connectionstring" value="data source=(local);Integrated Security=SSPI;Initial Catalog=${initial.catalog}"/>
8 <property name="devenv.dir" value="C:\program files (x86)\microsoft visual studio 8\Common7\IDE"/>
9 <property name="asp.net.account" value="NT Authority\Network Service"/>
10 <property name="database.provider" value="System.Data.SqlClient" />
11 <property name="database.path" value="C:\development\databases" />
12 <property name="system.root" value="C:\windows\"/>
13 </properties>
In this case I have information like where my tools are located, what account to use for security, and what my connection string is. Take the template file and rename it to local.properties.xml then customize it your own environment. This file does not get checked in (the template does, but not the customized file).
Then inside your NAnt build script you'll read this file in and merge the properties from this file into the main build script. Any properties with the same name will be overridden and used instead of what's in your build script so this gives you the opportunity to create default values (for example, default database name). If the developer doesn't provide a value the default will be used. The NAnt task is simple as it just does a check to see if the local properties file is there and then uses it:
60 <!-- include the machine specific properties file to override machine specific defaults -->
61 <if test="${file::exists('local.properties.xml')}">
62 <echo message="Loading local.properties.xml" />
63 <include buildfile="local.properties.xml" />
64 </if>
That's it. Now each developer can have anything setup his own way. For example I only have SQL Express installed but the others have SQL Server 2005 installed. We're all using the same build scripts because my local properties file contains the path to osql.exe that got installed with SQL Express and my connection string connects to MACHINENAME\SQLEXPRESS (the default instance name).
Finally, these values are used to spit out app.config or web.config files. The key thing here is that we don't have an app.config file inside the solution. Only the a template is there which is merged with the properties from the build script to generate dynamic config files that are specific to each environment (and again, not checked in to the build).
BTW, the whole build process, build scripts and differences from deployments could be an entire blog post so I don't think I'm finished with this topic just yet.
Notepad++
I'm a huge fan of Notepad++ and use it all the time. I have it configured on my system to be the default editor, default viewer for source code in HTML pages, and well... the default everything. I was a little surprised when our build ran the MbUnit launched Notepad. Nowhere I could find a place to change this and I'm told that it's using the default editor. That's a little odd to me because Notepad++ is my default editor. So maybe someone has info out there as to how to get it to launch my editor instead of Notepad? Either that or I need to physically replace Notepad.exe with Notepad++.exe (which can be done, instructions on the NP++ site).
New Cool Tool of the Day
Console2. When I launch my command prompt, it's a giant glowing screen of goodness. I'm a bit of a console junkie as I find I can get a lot more done by jumping around in the console rather than hunting and pecking in something like Windows Explorer. I got a tool from JP called Console2 by Marko Bozikovic which makes my command line experience that much better. It's not really a cmd.exe replacement but rather a shell that runs cmd.exe. However the really cool thing here is that a) it can launch any shell you want (like PowerShell) b) supports transparency (even under Windows XP) and c) it has a tabbed interface. It's like a command line ala Firefox (or that other browser that has tabs).
Now I don't have to launch a whole bunch of consoles, just one will do, and I can tab back and forth and even mix things up with cmd.exe and PowerShell (insert whatever shell you like here as well).
Wrap up
Another draining day but full of good things to inject in your head. I can't say enough praise for this course, although things are moving along much slower than I would like them to, it's still a great experience and I highly recommend it for everyone, even seasoned pros.
As I mentioned before, I'm trying to get away from the mouse. I have always found the mouse to be a problem. It's the context switching from 1. take hand away from keyboard 2. move hand to mouse 3. move mouse 4. move hand back to keyboard. Bleh. Yesterday was a mostly-keyboard day, today I'm going commando with all keyboard as I have my mouse locked up and hopefully won't need it at all.
More Nothin
JP is doing this 5-day intensive course that stretches people to think outside the box of how they typically program and delve into realms they have potentially not event thought about yet, about one per month. For the next little while (he's a busy dude) he's going to be travelin' dude. In October he'll be in New York City. In September he'll be in London, England and other locations are booked up into the new year.
If you want to find out more details about the course itself, check out the details here and be sure to get on board with the master.
-
Nothin but .NET course - Tips and Tricks - Day 1
I'm currently popping in and out of Jean-Paul Boodhoo's Nothin but .NET course for the week and having a blast. We brought JP in-house to the company I'm at right now for his .NET training course, which is arguably probably the best .NET course out there. Period.
I don't claim to be an expert (at least I hope I've never claimed that) and I'm always looking for ways to improve myself and add new things to my gray matter that I can hopefully recall and use later. Call them best practices, call them tips and tricks, call them rules to live by. Over the course of the week I'll be blogging each day about what's going on so you can live vicariously through me (but you really need to go on the course to soak in all of JP and his .NET goodness).
So here with go with the first round of tips:
File -> New -> Visual Studio Solution
This is a cool thing that I wasn't aware of (and makes me one step closer to not using the mouse, which is a good thing). First, we have a basic empty Visual Studio .sln file. This is our template for new solutions. Then create new registry file (VisualStudioHack.reg or whatever you want to call it) with these contents:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\.sln\ShellNew]
"FileName"="Visual Studio Solution.sln"Double-click the .reg file and merge the changes into your registry. The result is that you now will have a new option in your File -> New menu called "Microsoft Visual Studio Solution". This is based on your template (the empty .sln file) that you provide so you can put whatever you want in here, but it's best to just snag the empty Visual Studio Solution template that comes with Visual Studio. Very handy when you just need a new solution to start with and don't want to start up Visual Studio and navigate through all the menus to do this.
MbUnit
MbUnit rocks over NUnit. My first exposure to the row test and while you can abuse the feature, it really helps cut down writing a ton of tests or (worse) one test with a lot of entries.
In NUnit let's say I have a test like this:
35 [Test]
36 public void ShouldBeAbleToAddTwoPositiveNumbers()
37 {
38 int firstNumber = 2;
39 int secondNumber = 2;
40 Calculator calculator = new Calculator();
41 Assert.AreEqual(firstNumber + secondNumber, calculator.Add(firstNumber, secondNumber));
42 }
And I need to test boundary conditions (a typical thing). So I've got two options. First option is to write one test per condition. The second is to write a single test with multiple asserts. Neither is really appealing. Having lots of little tests is nice, but a bit of a bear to maintain. Having a single test with lots of asserts means I have to re-organize my test (hard coding values) and do something like this in order to tell which test failed:
33 [Test]
34 public void ShouldBeAbleToAddTwoPositiveNumbers()
35 {
36 Calculator calculator = new Calculator();
37 Assert.AreEqual(2 + 2, calculator.Add(2, 2), "could not add positive numbers");
38 Assert.AreEqual(10 + -10, calculator.Add(10, -10), "could not add negative number");
39 Assert.AreEqual(123432 + 374234, calculator.Add(123432, 374234), "could not add large numbers");
40 }
Or something like, but you get the idea. Tests become ugly looking and they feel oogly to maintain. Enter MbUnit and the RowTest. The test above becomes parameterized that looks like this:
28 [RowTest]
29 public void ShouldBeAbleToAddTwoPositiveNumbers(int firstNumber, int secondNumber)
30 {
31 Assert.AreEqual(firstNumber + secondNumber, calculator.Add(firstNumber, secondNumber));
32 }
Now I can simply add more Row attributes, passing in the various boundary conditions I want to check like so:
23 [Row(2,2)]
24 [Row(10, -10)]
25 [Row(123432, 374234)]
26 [RowTest]
27 public void ShouldBeAbleToAddTwoPositiveNumbers(int firstNumber, int secondNumber)
28 {
29 Assert.AreEqual(firstNumber + secondNumber, calculator.Add(firstNumber, secondNumber));
30 }
That's cool (and almost enough to convince me to switch) but what's uber cool about this? In the MbUnit GUI runner, it actually looks like separate tests and if a Row fails on me, I know exactly what it was. It's a failing test out of a set rather than a single test with one line out of many asserts.
As with any tool, you can abuse this so don't go overboard. I think for boundary conditions and anywhere your tests begin to look crazy, this is an awesome option. I haven't even scratched the surface with MbUnit and it's database integration (I know, databases in unit tests?) but at some point you have to do integration testing. What better way to do it than with unit tests. More on that in another blog.
Subject Under Test
This term was coined (at least my first exposure to it) was from Gerard Meszaros excellent book xUnit Testing Patterns and he uses it throughout. It makes sense as any unit test is going to be testing a subject so therefore we call it the Subject Under Test. One nomenclature that JP is using in his tests is this:
15 private ICalculator calculator;
16
17 [SetUp]
18 public void SetUpCalculatorTest()
19 {
20 calculator = CreateSUT();
21 }
22
23 private ICalculator CreateSUT()
24 {
25 return new Calculator();
26 }
So basically every unit test has a method called CreateSUT() (where appropriate) which creates an object of whatever type you need and returns it. I'm not sure this replaces the ObjectMother pattern that I've been using (and it's really not a pattern but more of a naming convention) but again, it's simple and easy to read. A nice little tidbit you pick up.
In doing this, my mad ReSharper skills got the best of me. Normally I would start with the CreateSUT method, which in this case returns an ICalculator by instantiating a new Calculator class. Of course there's no classes or interfaces by this name so there's two options here. One is to write your test and worry about the creation later, the other is to quickly create the implemenation. At some point you're going to have to create it anyways in order to compile, but I like to leave that until the last step.
Under ReSharper 2.x you could write your test line by writing CreateSUT() then press CTRL+ALT+V (introduce variable). However since ReSharper 2.5 (and it's still there in 3.x) you can't do this. ReSharper can't create the ICalculator instance (in memory) in order to walk through the method table (which would give you intellisense). So the simple thing is to write the CreateSUT() method and just whack ALT+ENTER a few times to create the class and interface.
Thread safe initialization using a delegate
I have to say that I never looked into how to initialize event handlers in a thread-safe way. I've never had to do it in the past (I don't work with events and delegates a lot) but this is a great tip. If you need to initialize an event handler but do it in a thread-safe way here you go:
private EventHandler<CustomTimerElapsedEventArgs> subscribers = delegate { };
It's the simple things in life that give me a warm and fuzzy each day.
Event Aggregators and Declarative Events
We spent the better part of the day looking at events, delegates, aggregators and whatnot. This is apparently new to the course that he's just added and hey, that's what Agile is about. Adapting to change.
Anyways, as we dug into it I realized how little I knew about events and how dependent I was on the framework to help me with those object.EventName += ... snippets I would always write. Oh how wrong that was as we got into loosely coupled event handlers (all done without dynamic proxies, which comes later). It's pretty slick as you can completely decouple your handlers and this is a good thing. For example, here's a simple test that just creates an aggregator, registers a subscriber, and checks to see if the event fired.
First the test:
25 [Test]
26 public void ShouldBeAbleToRegisterASubscriberToANamedEvent()
27 {
28 IEventAggregator aggregator = CreateSUT();
29 aggregator.RegisterSubscriber<EventArgs>("SomethingHappened", SomeHandler);
30 eventHandlerList["SomethingHappened"].DynamicInvoke(this, EventArgs.Empty);
31 Assert.IsTrue(eventWasFired);
32 }
Here's the delegate that will handle firing the event:
58 private void SomeHandler(object sender, EventArgs e)
59 {
60 eventWasFired = true;
61 }
And here's part of the aggregator class which simply manages subscribers in an EventHandlerList:
7 public class EventAggregator : IEventAggregator
8 {
9 private EventHandlerList allSubscribers;
10
11 public EventAggregator(EventHandlerList allSubscribers)
12 {
13 this.allSubscribers = allSubscribers;
14 }
15
16 public void RegisterSubscriber<ArgType>(string eventName, EventHandler<ArgType> handler)
17 where ArgType : EventArgs
18 {
19 allSubscribers.AddHandler(eventName, handler);
20 }
21
22 public void RaiseEvent<ArgType>(string eventName, object sender, ArgType empty) where ArgType : EventArgs
23 {
24 EventHandler<ArgType> handler = (EventHandler<ArgType>) allSubscribers[eventName];
25 handler(sender, empty);
26 }
27
28 public void RegisterEventOnObject<ArgType>(string globalEventName, object source, string objectEventName)
29 where ArgType : EventArgs
30 {
31 }
32 }
Again, basic stuff but lets you decouple your events and handlers so they don't have intimate knowledge of each other and this is a good thing.
A very good thing.
BTW, as we extended this we sort of built CAB-like functionality on the first day and in a few hours (only event publishers and subscribers though). We just added two attribute classes to handle publishers and subscribers (rather than subscribing explicitly). It wasn't anywhere near as complete as Jeremy Miller's excellent Build your own CAB series, but none-the-less it was a simple approach to a common problem and for my puny brain, I like simple.
It was fun and appropriate as the team is using CAB so the guys in the room are probably more positioned to understand CAB's EventBroker now.
Other Goodies and Tidbits
JP uses a nifty macro (that I think I'll abscond and try out myself) where he types the test name in plain English but with spaces like so:
Should be able to respond to events from framework timer
Then he highlights the text and runs the macro which replaces all spaces with underscores:
Should_be_able_to_respond_to_events_from_framework_timer
I'm indifferent about underscores in method names and it's a no-no in production code, but for test code I think I can live with it. I reads well and looks good on the screen. Using a little scripting, reflection, or maybe NDepend I could spit out a nice HTML page (reversing the underscores back to spaces) and form complete sentences on my test names. This can be a good device to use with business users or other developers as you're trying to specify intent for the tests. I have to admit it beats the heck out of this:
ShouldBeAbleToRespondToEventsFromFrameworkTimer
Doesn't it?
Wrap up
The first day has been a whirlwind for the team as they're just soaking everything in and making sense of it. For me, I'm focusing on using my keyboard more and getting more ReSharper shortcuts embedded into my skull. I've now got MbUnit to go plow through, check out the other fixtures and see what makes it tick and take the plunge from NUnit if it makes sense (which I think it does as I can still use my beloved TestDriven.NET with MbUnit as well!).
More Nothin
JP is doing this 5-day intensive course that stretches people to think outside the box of how they typically program and delve into realms they have potentially not event thought about yet, about one per month. For the next little while (he's a busy dude) he's going to be travelin' dude. In October he'll be in New York City. In September he'll be in London, England and other locations are booked up into the new year.
If you want to find out more details about the course itself, check out the details here and be sure to get on board with the master.
-
Another soul for the collective
Like John Lam and others before him, Scott Hanselman has been absorbed into the collective and ceased to become an MVP and RD. He's now a Blue Badge and will be starting his quest with the Blue Monster in September. Congrats Scott!
-
Cool Tools: Taskbar Shuffle
Something that should be inherently built into Windows (does Vista have this?), the ability to drag and drop icons around on your taskbar.
Free and simple to use. Check it out here.
-
Looking for some Code Review Tools
I'm looking around for some tools to help us with code reviews. Currently code reviews are setup every couple of weeks, reviewers are sent into the codebase to pick what they want to review (we had been giving them chunks but I felt that put us at a disadvantage in picking out the good code and not seeing the bad), then during the review we'll just have Visual Studio up walking through the solution. ReSharper is great and makes navigation a breeze, but I'm looking for something better and wondering what other people use. Ideally we only want to review code that's changed since the last review of it, so something that would give us visual diffs from a date or something might be useful (but haven't quite figured out how that would work logistically). So what tools are you using for your code reviews to help automate or speed up the process? Print outs and projectors or is it a little more sophisticated then that?
-
eScrum, part deux
Microsoft has come out with an update to what I consider their Gong Show release of eScrum. The new version (v1.0 as opposed to v1, go figure) has the following fixes:
- MSI to provide a prerequisites separately during installation
- Provided start menu link to documentation, to locate Help
- Provided choice to install only the process template, and/or the web application
- Rebuilt with latest Ajax Control Library Version
- Automated copy of XSS library in MSI
- Automated creation and configuration of application pool and website in MSI
- Automated upload of process template in MSI
- Automated share point template setup in MSI
- Automated creation/configuration of cache and log paths in MSI
There are still some manual steps involved but it's a vast improvement and it all sounds good, I just can't tell you first hand right now if it's all it's cracked up to be.
You can download the package from here.
-
At least she's not named Longhorn
Lots of great feedback (good, bad, and ugly) on our naming strategy with our daughter. I'm still compiling the list as they come in and will be posting a large assortment of links with the various humor people have added to it. Saw a new one this morning which was well written but accompanied by this cartoon which was bang-on with our experience (although I didn't survey you guys to determine her name).
Hmmm... I wonder if various recent baby names (Google, 2.0, etc. including our own) spawned this cartoon? What's really funny is the notes from people saying this was all a marketing ploy. If that were true, I'm still waiting for my cheque Microsoft!
-
FIT and DDD in Edmonton
I'm giving a talk to the Edmonton .NET Users Group at the end of the month (man how time flies) about how to use FIT with Domain Driven Design. Should be a blast as we're heading up for a couple of days to soak in the shopping experience (what else do you do in Edmonton?). Here's the abstract:
Many development teams undertake projects by diving straight into writing code, maybe even doing Test Driven Development based off of requirements. For business scenarios, there exists an excellent tool that can help the team both understand the domain and produce testable requirements as the understanding about the domain grows. What does it take to translate business requirements from spec to tests and how can you ensure that the domain is valid and meets the needs of the system?
This session will outline the important of FitNesse and the FIT Library by showing how to drive out foundations of domain-driven design and walk through building out testable requirements that a cross functional team can produce in a short amount of time. We will explore the identification of domain concepts and how they "fit" in with the testing model through code and web pages.
More information about the session with directions, times, and all that boring stuff on their website here. See you there!
-
SCSFContrib First Release
The SCSFContrib gang (Kent Boogaart, Ward Bell, Chris Holmes, Ezequiel Jadib, Matias Woloski, and myself) got our first release out after a month of forming, storming, and norming. This includes:
- A full implementation of the UI layer for CAB done in WPF with 100% code coverage in tests
- The Outlook Bar Workspace with a new Quickstart application
- A WPF CAB Visualizer that lets you see behind the scenes how WorkItems, SmartParts, Workspaces, and Services fit together
- The BankTeller Quickstart rewritten using SCSF 2007 and WinForms SmartParts
- The BankTeller Quickstart rewritten using SCSF 2007 and WPF SmartParts
Not bad for a first release and a month of work. Hopefully we can maintain the momentum and crank out releases every month (I'll probably get beat up for that comment from the team).
You can the release here from CodePlex.
-
Being a Better Developer... in 6 months
I've been a little behind in blog-land (both reading and writing, gasp) as other things have occupied my time. However my good friend Justice tagged me in his update on how he's going to be a better developer over the next 6 months so naturally I can only reply, and tag 5 more people. Yes, this is like the tell 5 things about someone but with a geek slant and I think it's more interesting this way. So here goes...
Reading
I have a list of books I normally keep on my shelf. These include Domain Driven Design, Test Driven Development and such and I plan to re-read some of these in the next 6 months (to me, something like Applied Domain Driven Design by Jimmy Nilsson you can read over and over, but then I'm a geek). For new stuff, I'm consuming Windows Presentation Foundation Unleashed by Adam Nathan right now and getting into that and I'll round it out to say that I'm prepared to soak up 3 new books over the next 6 months. Sometimes I can gobble up a book in one sitting, but for the most part I suck one down then go back to it over the course of a few weeks to really did into the nitty gritty parts (and maybe write some small spikes to really grok a subject, like WPF will be for me).
Writing
Other than my blog, I intend to have a few new articles published that are currently in the works (MSDN Magazine, O'Reilly, etc.) and generally keep the pace I have on my blog. I'm no Oren and you'll never see 150 posts in a month from me (other than "All work and no play makes Bil a dull boy"), but I intend to keep up the pace to around 20 good posts a month. This is an increase from last year and who knows, maybe with some hallucinatory inciting drugs, I *can* get posting 150 times a month with some choice stuff.
Speaking
The speaking schedule this year is a little slow thanks to baby and family (which is the way it should be) but I'm still heading out to amuse and bemuse you from time to time. The next 6 months will be a few user groups (Edmonton and Calgary specifically, but I'm open to others and you can contact me through the MSDN Canada Speakers Bureau which is painfully out of date) and I'm just submitting some talks to DevTeach Vancouver. Hopefully I'll get in, but the competition is tough and I might not make it it depending on how many heavy hitting Agile guys there are out there who are far better than me (and there are a lot of them). I don't consider myself a great speaker but I have passion and try to emote that through my presentations with a little humor. The best advice I got from some of the top speakers out there is to keep doing it. So if you're like me, get out there and just do it. Speak at your own company first, or user groups then move up to the conferences if you like it and you think it's your thing. I get a lot of satisfaction when someone comes away from a session I've done and uses it in their day job. Maybe you can get the same.
Community
I have my own personal vanity site (down right now thanks to an unsuccessful DNN upgrade) at bilsimser.com and it really needs to get it rebuilt. It's been such a pain as I try to find content, yet I have 200 gigabytes of code, documents, snippets, articles, tools, projects and games that I've written over the years that *needs* to get out there. Why? Because I like to share and let people dissect what I do. What doesn't kill you makes you stronger type of thing. So in the next 6 months that *will* come online and I'll get lots of goodies up there to share with the rest of the class.
Learning
I think learning is the key to growth. I'm a sponge. I see a new toy, tool, technology, etc. and just soak it up. Although for me there's an initial soaking-inception-phase where I test the waters to see if I'm really going to like this. I talked to John Lam long ago about Ruby and still have yet to pick it up but some day (maybe now that Silverlight can do it dynamically I'll take that approach). One thing about learning is that you can't learn everything yourself. Don't be afraid to ask stupid questions. I find the MVP group and the Agile guys out there are a wealth of information. I'm often emailing people for hints or ideas or just to bounce things off them. Many times I just get back a nugget with something so subtle but I fit it into my work and I feel I'm a better developer for it. So more of that as you can never know enough.
Code, Code, Code and more Code
I feel you can only get betting by doing it. For me, that's writing code and trying out new things. I constantly refine what I consider my reference architecture for applications. I have one for Smart Clients, one for SharePoint Apps, and one for Web Apps and keep them lean and simple. They're not templates but more like guidelines so any time I spin up a new project I use it and tweak it, then incorporate those tweaks into new applications. I code every day even if I have a day full of meetings so I'm going to keep doing that. I think it's important to be there in the code (even though technically I'm an "Architect") as things change and the software is build from code, not Visio drawings. Like speaking, the more you do it the better you get. So code, code, code everyday until you drop.
Okay, so here's my tag list. These 5 dudes, should they choose to accept this mission, should be telling you on how they're going to be better developers over the next 6 months (and you see from the list, it's going to be tough as these guys are already at the top of their game, however everything can be improved):
- Scott Hanselman - You can't improve perfection, but it's great to peek inside the mind of the great ones from time to time.
- Oren Eini (Ayende Rahien) - Because he's probably writing this up right now anyways, and doesn't really post enough.
- Jeremy Miller - Because all of the books on his "Books that Influence me" post are my library too, I'd like to see what else makes J tick.
- Jeffrey Palermo - For all the times I've misspelt Jeff's last name (including this post)
- Rocky Lhotka - Because Rocky needs a reason to stop posting about CSLA ;)
Enjoy!
Update: Strangely enough, I was *supposed* to tag 4 peeps, not 5. However this gives Rocky, Scott, or Oren an out since both J's accepted my challenge and are prolly writing up the blog to institute world peace as we speak. Maybe after the first 6 months I should learn how to better read other peoples blogs.