Fear and Loathing
Gonzo blogging from the Annie Leibovitz of the software development world.
-
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!