Sometimes the appropriate response to reality is to go insane - Philip K Dick RSS 2.0
 Wednesday, March 26, 2008

Prompted by a discussion on the altdotnet yahoo group ... why I like broken builds ...

Some people try desperately to avoid breaking the build, by doing very infrequenet check ins (the number of broken builds per day drops dramatically, the time to fix each goes up though), or by trying to ensure their development environment is as close to the build environment as possible.

But a broken build is not a problem - it is an opportunity. A broken build allows you to identify a weakness, and to resolve it early.

The weakness might be in your architecture, it may be in your dependencies, or in your assumptions, or in your developer skill levels - but the whole point of having a continuous integration server is to fail fast and let you deal with the underlying problems rather than the specifics of the code you checked in.

 

Wednesday, March 26, 2008 9:14:57 AM (GMT Standard Time, UTC+00:00)  #    Comments [4] -
.NET | Agile | alt.net | C# | Continuous Integration | Design | Development
 Saturday, March 15, 2008

A short while ago I wanted to get VSTS code coverage reports from NUnit tests ... and after some asking around found that using the Profiler I could get what I needed. I just released a CodePlex project to wrap this functionality. Hope it helps somebody else.

Project Description
This project is an attempt to provide a wrapper around the VSTS instrumentation and code coverage tools.

VSTS provides very powerful code coverage tools with Visual Studio, but as packaged, you need to be running MSTest unit tests to obtain this coverage data. There is a way of getting this data without using MSTest though, bu using another test framework such as NUnit or MbUnit for example.

This wrapper encapsulates the generation of the .coverage file from a run of NUnit or MbUnit (or similar), but in addition it provides an automated generation of the .xml version of the .coverage file (both can be read by Visual Studio directly), and then uses an XSLT template to transform the XML output into a final human readabale page (by default a .html file)

Further extension will pull the actual parameters from the hardcoded values in the console application into a wrapper class, and will wrap both with a command line tool and with an MSBuild task - however the code is functional enough, and is transparent enough, that both of these tasks should be easy to implement for anyone wishing to do so for themselves if they require this immediately.

 

Saturday, March 15, 2008 9:37:51 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Code Coverage | Development | Sample Code | Testing
 Thursday, March 06, 2008

As I am about to use a number of these to try and identify weakenesses in our current requirements and documentation, I thought I would link them for the benefit of all - I'm not sure many people know these exist and are available online. They come from possibly the best book written on software development, Code Complete 2 by Steve McConnell

You can read the full list of checklists (a free and simple registration is required), but the ones I think are critical to the success of a project are from the Requirements Checklist. As Steve says, they may not be comprehensive, they may not be complete, they don't tell you how to do these things, it is just a good sanity checking list:

Specific Functional Requirements

  • Are all the inputs to the system specified, including their source, accuracy, range of values, and frequency?
  • Are all the outputs from the system specified, including their destination, accuracy, range of values, frequency, and format?
  • Are all output formats specified for web pages, reports, and so on?
  • Are all the external hardware and software interfaces specified?
  • Are all the external communication interfaces specified, including handshak-ing, error-checking, and communication protocols?
  • Are all the tasks the user wants to perform specified?
  • Is the data used in each task and the data resulting from each task specified?

Specific Non-Functional (Quality) Requirements

  • Is the expected response time, from the user's point of view, specified for all necessary operations?
  • Are other timing considerations specified, such as processing time, data-transfer rate, and system throughput?
  • Is the level of security specified?
  • Is the reliability specified, including the consequences of software failure, the vital information that needs to be protected from failure, and the strategy for error detection and recovery?
  • Is maximum memory specified?
  • Is the maximum storage specified?
  • Is the maintainability of the system specified, including its ability to adapt to changes in specific functionality, changes in the operating environment, and changes in its interfaces with other software?
  • Is the definition of success included? Of failure?

Requirements Quality

  • Are the requirements written in the user's language? Do the users think so?
  • Does each requirement avoid conflicts with other requirements?
  • Are acceptable trade-offs between competing attributes specified-for ex-ample, between robustness and correctness?
  • Do the requirements avoid specifying the design?
  • Are the requirements at a fairly consistent level of detail? Should any re-quirement be specified in more detail?
  • Should any requirement be specified in less detail?
  • Are the requirements clear enough to be turned over to an independent group for construction and still be understood?
  • Is each item relevant to the problem and its solution? Can each item be traced to its origin in the problem environment?
  • Is each requirement testable? Will it be possible for independent testing to determine whether each requirement has been satisfied?
  • Are all possible changes to the requirements specified, including the likeli-hood of each change?

Requirements Completeness

  • Where information isn't available before development begins, are the areas of incompleteness specified?
    Are the requirements complete in the sense that if the product satisfies every requirement, it will be acceptable?
  • Are you comfortable with all the requirements? Have you eliminated re-quirements that are impossible to implement and included just to appease your customer or your boss?
Thursday, March 06, 2008 7:58:05 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
Design | Development
 Monday, January 28, 2008

Today I wanted to setup JetBrains TeamCity as a pilot to run continuous integration for us.

With their new licencing model, TeamCity is free for up to 20 build configurations, 3 build agents and 20 users, which is more than enough for us to get going and see if it improves our process.

Other options were Team Foundation Build or CC.Net

Personally I discounted Team Build early, various comments on mailing lists and forums made it very clear that it was far from being a CI server out of the box, and although after some apparently extensive configuration it could be made to do something similar, it is far from a friction free piece of software.

CC.Net I have used a number of times before, but the XML configuration it requires is less than joyous, and no matter how often I set it up, I never seem to get quicker at it. Good it may be, easy to configure it isn't.

So we decided to start off with a clean Windows 2003 Server installation, as it comes out of the box. That meant that we didn't even install IIS, as TeamCity includes Tomcat to serve up its dashboard.

We had a few teething problems, but the installation was up and running inside a few short minutes ... albeit not building.

The first problem was rather major - under the VCS settings in TeamCity we had opted for Team Foundation Server, and given it all the settings we knew to be correct - but it repeatedly gave us an obscure error - one with no information other than a java exception:

jetbrains.buildServer.vcs.VcsException: TFS execution error
Stdout:
TFS Native Verifier v1.0 Copyright (C) 2006-2007 JetBrains s.r.o. by Mikhail Pilin and Eugene Petrenko
Stderr:
Exception:
at jetbrains.buildServer.buildTriggers.vcs.tfs.TfsNativeExeRunner.start(TfsNativeExeRunner.java:20)

We spent a fair while on this, eventually giving in and dropping an email to JetBrains - all credit to Serge there for a quick response. After a few confusing emails backwards and forwards, the first solution they could suggest was that I needed a "full TFS" install on the CI server.

This wasn't a great solution - we were deliberately trying to keep the server clean, the last thing I wanted was Visual Studio or Team Explorer installed.

After a bit of searching around, and some helpful hints on the altdotnet mailing list, I found that MS now package the Team Explorer as a download on its own. This looked after unpacking to install some kind of Visual Studio "light" which I still didn't want on the server - but after drilling down I found the Microsoft.TeamFoundation.xxxx assemblies were included in the package. I added these into the GAC, and the problem was instantly resolved without an install of Team Explorer or Visual Studio. A very short while afterwards a clarification came from JetBrains:

To be more specific, the following components must be in PATH:

Microsoft.TeamFoundation.Client.dll
Microsoft.TeamFoundation.Common.dll
Microsoft.TeamFoundation.Common.Library.dll
Microsoft.TeamFoundation.dll
Microsoft.TeamFoundation.VersionControl.Client.dll
Microsoft.TeamFoundation.VersionControl.Common.dll
Microsoft.TeamFoundation.VersionControl.Common.Integration.dll
Microsoft.TeamFoundation.WorkItemTracking.Client.Cache.dll
Microsoft.TeamFoundation.WorkItemTracking.Client.DataStore.dll
Microsoft.TeamFoundation.WorkItemTracking.Client.dll
Microsoft.TeamFoundation.WorkItemTracking.Client.Provision.dll
Microsoft.TeamFoundation.WorkItemTracking.Client.QueryLanguage.dll
Microsoft.TeamFoundation.WorkItemTracking.Client.RuleEngine.dll
Microsoft.TeamFoundation.WorkItemTracking.Proxy.dll

The GAC solution was therefore on the mark, but we may have got away with dropping the assemblies in the path too. Either way - this was a much cleaner install.

Our second problem was a silly mistake in configuring the project. We are using MSBuild to do the building, and we kept getting a "MSBuild Schema could not be found" error. After a lot of head bashing it turned out I had managed to click on the Validate option in TeamCity, and it was TeamCity rather than MSBuild that was throwing the error - TC could certainly do with better logging. The missing schema file could probably have been dropped alongside the .build file, but as we didn't need it to be validated, we unticked the option, and voila ... it all worked ... almost ...

One last little niggle caught us, NCover was timing out while running, and giving us an error regarding the profiler. We had included NCover in our TFS tree, along with NUnit, Rhino, and all the other tools we need, this was to avoid having to install anything on a workstation to be able to build the projects.

After a hint from Ayende, it turned out that NCover requires an assembly to be registered with regsvr32, something I haven't done in so long, I had forgotten the command even existed! So to solve this problem, the answer is:

regsvr32 coverlib.dll

It may not be ideal, but it does the job, and I think I can live with one assembly needing to be registered, at least in the short term.

Update: Grant Drake posted about this a while ago, and has 4 possible solutions here ... using //reg on the command line is a much better option in a CI environment, so I'm switching our build to do that this morning.

And with all that done, we now have a *very* clean CI server, running a very basic Windows Server install, with a very neat TeamCity install.

Now to show the business benefit!


Monday, January 28, 2008 6:32:32 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Agile | Code Coverage | Continuous Integration | Development | NCover | TeamCity | Testing
 Thursday, January 17, 2008

Previously I got my basic interception going, to allow me to strongly type resource requests.

The next step was to allow me to inject that capability via Windsor. The test for this was a bit tricky, due to me not understanding the Windsor container syntax in C#, but after a bit of playing around, we end up with the following code to create my IResource via the container.

    [TestFixture]
    public class SpikeProxyResources
    {
        [Test]
        public void TestWithFactoryCreation()
        {
            IWindsorContainer container = new WindsorContainer();
            FactorySupportFacility facility = new FactorySupportFacility();
            container.AddFacility("factory.support", facility);
            facility.AddFactory<IResource, ResourceFactory>("ResourceFactory", "CreateResource");

            IResource resource = container.Resolve<IResource>();
            Assert.AreEqual("GetVal", resource.GetVal);
            Assert.AreEqual("NewValue", resource.NewValue);

        }
    }

    public class ResourceFactory : IInterceptor
    {
        public IResource CreateResource()
        {
            ProxyGenerator generator = new ProxyGenerator();
            IResource proxy = generator.CreateInterfaceProxyWithoutTarget<IResource>(this);
            return proxy;
        }

        public void Intercept(IInvocation invocation)
        {
            if (invocation.Method.Name.StartsWith("get_"))
            {
                //TODO: Lookup resource here.... 
                invocation.ReturnValue = invocation.Method.Name.Substring(4);
            }
            else
                invocation.ReturnValue = null;
        }
    }

The next step will be to pull this configuration out into Xml ... or if I can convince the people that matter, into Binsor and Boo!

Thursday, January 17, 2008 5:43:55 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | C# | Development | Sample Code
 Wednesday, January 16, 2008

Whilst discussing Globalization and Localization on the current SharePoint stuff I am working on, the issue of resource files, their location, their abstraction, and their general use came up.

One option was to use resgen.exe to create strongly typed classes for the resources, but I felt that this lost us the flexibility that dropping the .resx files into app_globalresources would provide us with.  Although accessing the compiled resources from the AppDomain is easy enough (look for an assembly called "app_GlobalResources"), we would then lose the strong typing, and have to resort to:

    ResourceManager rm = new ResourceManager(... ,...);
    rm.GetString("MyNonTypedName");

So to work around this I spent a bit of time looking into DynamicProxy2 from the Castle stack. After a few interesting diversions into the world of DictionaryAdapter (thanks to Ken Egozii and Josh Robb. Sadly poorly documented, but I'm sure it will prove invaluable soon), I finally came up with the simple bit of code I was trying to achieve:

    public class SpikeProxyResources
    {
        [Test]
        public void Test()
        {
            ProxyGenerator pg = new ProxyGenerator();

            IResource proxy = pg.CreateInterfaceProxyWithoutTarget<IResource>(new MyInterceptor());

            string s = proxy.GetVal;
            
            Assert.AreEqual("GetVal", s);

            Assert.AreEqual("NewValue", proxy.NewValue);
        }
    }

    public interface IResource
    {
        string GetVal { get;}

        string NewValue { get; }
    }

    public class MyInterceptor :IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            if (invocation.Method.Name.StartsWith("get_"))
            {
                //TODO: Lookup resource here.... 
                invocation.ReturnValue = invocation.Method.Name.Substring(4);
            }
            else
                invocation.ReturnValue = null;
        }
    }

Fundamentally, this allows us to intercept the calls to the getter on IResource, and look up the resource we are after within the compiled resources. For the moment it may only return the called Method Name, but only because I saved you the boring bit that goes off and gets back the real value.

IResource can now be instantiated by Windsor and adding more strongly typed resources is just a matter of adding a get property onto the interface.

 

Wednesday, January 16, 2008 4:03:44 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Castle | Development | Sample Code
 Thursday, January 03, 2008

Whilst reading a great article on getter and setter methods, I came across a small quotation that perfectly encapsulated the problems I see with a lot of code at my current client: Developers by their nature have a desire to hang on to global data, and to create global methods.

In 1989, Kent Beck and Ward Cunningham taught classes on OO design, and they had problems getting people to abandon the get/set mentality. They characterized the problem as follows:

The most difficult problem in teaching object-oriented programming is getting the learner to give up the global knowledge of control that is possible with procedural programs, and rely on the local knowledge of objects to accomplish their tasks. Novice designs are littered with regressions to global thinking: gratuitous global variables, unnecessary pointers, and inappropriate reliance on the implementation of other objects.

This problem is particularly common where I am at present as a large part of the development work is in MOSS 2007, which encourages global data and methods in a large number of insidious ways.

I'm now off to re-read Beck and Cunningham in more detail ... but in the meantime, pretty please MS, could you stop encouraging bad practices!

 

Thursday, January 03, 2008 8:26:26 AM (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET | Design | Development | MOSS 2007 | rants | SharePoint
 Wednesday, December 12, 2007

There are many forms of speed bump in development, things that cause you to slow down, stop, change your train of thought. From large things like people coming to your desk and asking questions, to smaller things like your IDE pausing for that half a second to refresh the screen. In fact if you think about your day, it is amazing how you get any work at all done with this many distractions and diversions.

But, to me, the most annoying of all these things is a poorly thought out IDE - after all I spend a lot of my time inside it, and that means a lot of my wasted time is caused by it too.

On the ALT.NET mailing list Frans Bouma suggested that most refactorings were small things that take less than a minute to do without a tool like ReSharper or Refactor.

To me - that is a speed bump - it is a minute I really shouldn't have to waste, just because I thought of a better way to structure a small part of my code. I don't think I have ever written a piece of code that was right first time, so pretty much I refactor everything I write to some lesser or greater degree.

Visual Studio is a great IDE, but it still has lots and lots of annoying things, and the refactoring it supports is pitiful. So for me, ReSharper is essential, it removes so many speed bumps from my daily path, that I can continue onwards and keep watching the road.

Technorati Tags: ,

Wednesday, December 12, 2007 9:02:08 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
Development | rants | ReSharper
 Tuesday, December 04, 2007

Whilst browsing the blog of Serge van den Oever I came across some brillaint tools he links to ... and for my future reference ... here they are:

SharePoint 2007 'Attach to Debugger' menu item

Which then links to the CodePlex project where this lives

And a really cool EventsManager for lists and documents

Tuesday, December 04, 2007 11:55:11 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
Development | SharePoint
 Monday, December 03, 2007

I am pleased to say, not only do I have a full working Model-View-Presenter implementation running within a SharePoint WebPart now, but I am very very close to having the rendering abstracted away from the WebPart and into a UserControl too. I'll blog more about this when I'm happy with the whole solution end to end.

In the meantime however, one annoying problem got me very very confused for a while ... if only SharePoint didn't give such stupid error messages and let you debug it properly, my life would have been much easier ... It was silly mistake really ... would have found it in 30 seconds in an ASP.NET application ... anyway I digress.

Remember, if you are using Castle Windsor from the GAC (as you need to for SharePoint work), then the web.config entry must specify the stong name of the assembly in the ConfigSections entry:

<section name="castle" 
type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,
Castle.Windsor, Version=1.0.3.0,
Culture=neutral, PublicKeyToken=407dd0808d44fbdc" />

I had copied and pasted the entry from another project, not in the GAC, it only had the entry as Castle.Windsor and voila I got a lot of cryptic errors from SharePoint.

As a secondary note, remember all of your entries in the <castle> section must also specify the strong name, or they too will give you cryptic messages and a lot of wasted effort.

Another one to watch out for!

Monday, December 03, 2007 1:39:10 PM (GMT Standard Time, UTC+00:00)  #    Comments [1] -
C# | Castle | Development | rants | Sample Code | SharePoint

I have little idea why, but I have now encountered this a fair few times, so much so that I thought I might as well blog it, others must be getting it too.

If you are missing your 'Step Into' option from the Debug menu and toolbar in VS, there is a simple fix: Select Tools / Import and Export Settings from the menu, then select Reset All Settings and follow through the next parts of the wizard.

This should have your Debug menu items back, though you may have to fix some other things back to how they were (like fonts and colours). Also if you have ReSharper installed, you need to go to the ReSharper / Options menu and under the General section reset your ReSharper shortcuts there.

 

Monday, December 03, 2007 10:13:30 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Development | ReSharper
 Friday, November 30, 2007

I have my MVP project coming along nicely, unit tests all running, presenters and interfaces doing their basic stuff. The assemblies are all being stongly named for SP deployment (into the GAC). Then I add my WebPart and implement IView on it.

Problem Numer 1 : Implementing an Interface on a WebPart using VSeWSS Causes Deploy to Fail

Oh yeah, that was fun. For speed and as I am working on a VM, I used the VSeWSS extensions to quickly create and deploy the web part. An hour later wasted, I pin down a problem with the Deploy command the Visual Studio extension provide. Just implementing an interface on the WebPart class causes the Deploy to fail - with a cryptic message about a reflection error.

Well done guys, I guess you are trying to find something that implements WebPart and nothing else? Whatever the reason, VSeWSS gone for good from my machine, I'm going back to doing this the hard way, where at least I have some control.

Problem Number 2 : The GAC ... "I'm not lying. Take my pen, write this down. Do not trust her."

So, my WebPart is now working, and all seems happy. With the assemblies deployed, I can now view my WebPart in all it's glory displaying "Hello World" with data coming from my repository via the presenter. All is good. All is level. All is pretty.

Then I do a bit of basic refactoring. Following some suggestions from ALT.NET people, I play around with my event signatures, remove out 'object sender' as this will be provided to the presenter on construction, and define an EmptyEventHandlerArg.

All pretty simple stuff. Hit build, all compiles just fine first time. Run all unit tests ... whoa there donkey...

System.InvalidOperationException: You have called the event raiser with the wrong number of parameters. Expected 1 but was 0
at Rhino.Mocks.Impl.EventRaiser.AssertMatchingParameters(MethodInfo method, Object[] args)
at Rhino.Mocks.Impl.EventRaiser.Raise(Object[] args)

Surely some mistake. Go over all code. Try to figure out if my usage of Rhino Mocks is wrong. Nope - all is correct, the IEventRaiser is being called correctly with the right number of parameters. The correct number of parameters in the view and the presenter.

Try this a dozen time more. Can't figure out why this worked just fine in my first prototype project where I had damn near the same code, so go back to that project. It all works just fine there. Change the signature there. It works just fine.

Back to my WebPart project. Stare blankly. Drink more coffee. Spark of inspiration ...

Delete the previous built assembly from the GAC. Now it all runs just fine.

It seems that the unit tests/Rhino are getting their references from the GAC, where as my projects are getting their reference from the build directory. On a machine where the assembly is built, but may also be in the GAC this is an issue for unit tests.

Off to try and find an explanation or solution. Of course I can copy to the GAC every build ... but I'm not sure I want to ... and I don't think it is healthy to have to ...

Friday, November 30, 2007 10:59:34 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
C# | Development | SharePoint | Testing

Whilst looking for something entirely different, I came across a post by Eric Kraus on putting options on the explorer context menu for .DLL files to allow them to be installed in the GAC and to open them in Reflector. As posted his code didn't quite work, so I modified it a little and it is below.

Create a dll.reg file in notepad, copy and paste the following in, then double click it to install the shortcuts. Make sure you change the paths if needed, but be careful to keep the escape sequences intact:

Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\dllfile\Shell]
@="\"c:\\Program Files\\Reflector\\reflector.exe\" \"%1\""
[HKEY_CLASSES_ROOT\dllfile\Shell\Reflector]
[HKEY_CLASSES_ROOT\dllfile\Shell\Reflector\command]
@="\"c:\\Program Files\\Reflector\\reflector.exe\" \"%1\""
[HKEY_CLASSES_ROOT\dllfile\Shell\InstallGAC]
[HKEY_CLASSES_ROOT\dllfile\Shell\InstallGAC\command]
@="\"c:\\Program Files\\Microsoft Visual Studio 8\\SDK\\v2.0\\Bin\\gacutil.exe\" /i \"%1\""


Thanks Eric

Technorati Tags: ,
Friday, November 30, 2007 8:50:56 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Development | Sample Code
 Thursday, November 29, 2007

Jean-Paul has updated his test naming macro to deal with class names as well as method names, and while I like naming my tests in the form of Test_That_Data_Has_Been_Loaded, I find that JP's macro doesn't work well for me.

The reason is that as I type in the form JP does ("Test That Data Has Been Loaded") I find ReSharper kicks in and start inserting class names for me. I have also got in the habit of typing "TestThatDataHasBeenLoaded" which is a lot less readable than JP's convention.

So I took JP's macro and modified it for my own use ... it will now turn my style of typing into JP's style of naming... voila ... readable test names!

TestThatDataHasBeenLoaded  ==>>  Test_That_Data_Has_Been_Loaded

Code below - all credit to JP for the bulk of this (and I am no VB programmer so my changes are pretty poorly coded, no critique needed pls):

Imports System
Imports System.Windows.Forms
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Imports System.Text.RegularExpressions

Public Module CodeEditor

    Sub ReplaceSpacesInTestNameWithUnderscores()

        If DTE.ActiveDocument Is Nothing Then Return
        Dim wrCS As Boolean = DTE.Properties("TextEditor", "CSharp").Item("WordWrap").Value

        Try
            DTE.Properties("TextEditor", "CSharp").Item("WordWrap").Value = False
            Dim selection As TextSelection = CType(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection)
            Dim index As Integer

            selection.SelectLine()
            If selection.Text = "" Then Return

            Dim methodIndex As Integer = selection.Text.IndexOf("public void ")
            Dim classIndex As Integer = selection.Text.IndexOf("public class ")

            index = CType(IIf(methodIndex >= 0, methodIndex, classIndex), Integer)

            Dim prefix As String = CType(IIf(methodIndex >= 0, "public void ", "public class "), String)
            prefix = selection.Text.Substring(0, index) + prefix
            Dim description As String = selection.Text.Replace(prefix, String.Empty).Trim
            Dim r = New Regex("[A-Z][^A-Z]*")
            Dim myMatches As MatchCollection
            Dim reformedDescription As String

            myMatches = r.Matches(description)
            Dim successfulMatch As Match
            For Each successfulMatch In myMatches
                reformedDescription = reformedDescription + successfulMatch.Value + "_"
            Next
            reformedDescription = reformedDescription.Trim("_")

            selection.Text = prefix + reformedDescription + vbCrLf
            selection.LineDown()
            selection.EndOfLine()
        Catch ex As Exception
            MsgBox(ex.Message)
        Finally
            DTE.Properties("TextEditor", "CSharp").Item("WordWrap").Value = wrCS
        End Try
    End Sub
End Module
Technorati Tags: ,,
Thursday, November 29, 2007 11:55:29 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | C# | Development | Sample Code | Testing

There is a really cool video, showing the power of ReSharper in the hands of a keyboard wizard ... but recently it went missing from the blog post in which it was first mentioned.

But, after a desperate plea, it is back in a new location http://www.jetbrains.com/resharper/documentation/index .html 

Watch it, learn from it, speed up your coding today

Thursday, November 29, 2007 10:52:00 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
C# | Development | ReSharper

Previously I blogged about finding out ther hard way about the limits on database size for MOSS and SQL Express.

At the time we took the 'reinstall the whole damn show' approach - after all it is a dev server! However it struck me there must be a better way, and indeed there is as Todd Klindt has recently posted:

Microsoft so very graciously provides a free version of SQL 2005, SQL Express, with MOSS. If you install MOSS using the Basic option or Single Server under Advanced you get SQL Express automatically. So what if as a budding newbie SharePoint admin you chose the Basic option, but now as a wise aged SharePoint admin you've seen the error of your ways and want to use a more respectable version of SQL for your SharePoint backend? You're in luck. In this blog post I'll walk you through upgrading SQL Express to SQL Standard or Enterprise.

http://www.toddklindt.com/blog/Lists/Posts/Post.aspx?ID=55 

 

Thursday, November 29, 2007 8:32:48 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
Development | SharePoint | Testing
 Friday, November 23, 2007

It looks like even the released version of ReSharper for VS2008 may have some quirks and glitches, even when targetting .NET2.0 - apparently the C#3.0 compiler is always lurking ...

ReSharper 3 can be installed with Visual Studio 2008 and works fine, unless you are using C# 3.0 new features, like lambdas, LINQ, extension methods and such. This constructs are not parsed by ReSharper 3, which was developed to support C# 2.0 only. It is not only highlighting which doesn't support C# 3.0, it is all the core and code intelligence. For example, rename refactoring will not find usages of extension methods and will not update them.
There also could be some glitches, even if you don't use new C# 3.0 constructs. This is due to the fact that C# 3.0 compiler is always used in Visual Studio 2008 C# projects, regardless of target framework. It it is not widely discussed, but changes in language are wider than just several new features. There are differences in type inference in generics and candidates lookup for binding, to name few. If you happen to hit this special cases, ReSharper could behave incorrectly.

ReSharper and Visual Studio 2008

Still not a good reason not to use it, but something to be aware of.

Friday, November 23, 2007 8:23:06 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
Development | rants | ReSharper
 Sunday, November 18, 2007

The interfaces we have created in Abstracting SharePoint allow us to unit test our code, but only if we mock the objects. We can do this in 2 ways, we either write an implementation of our own that mimics the SharePoint model (by storing data in in-memory objects for example), or we can use a mocking framework like Rhino Mocks or TypeMock.NET

My first approach was to write my own mock of SharePoint. This, I reasoned to myself, would allow me to actually setup test data, and to use the mocked layer to operate as a way of demonstrating the system in addition to testing.

This approach soon became a nightmare, the SharePoint object model is convoluted and confused. The interactions between objects are unclear, and often unexpected. I gave up on this one after a few hours of work that convinced me I needed to go down the other route.

For mocking I had a range of mocking frameworks to choose from, but Rhino Mocks (which I have used before with great success) was the obvious choice. Rhino has one limitation though which made me consider an alternative, it cannot mock Sealed classes. The bright sparks that wrote Microsoft.SharePoint decided the classes would be sealed, so although I can use Rhino to mock my newly formed interfaces, I would not be able to use it to mock Microsoft.SharePoint classes should the need arise (for example if it becomes too complex to complete the interface abstractions).

TypeMock.NET can, I am told, mock sealed classes. This would make it an ideal candidate for dealing with SharePoint. It is however a commercial product, and a pricey one at that. Cost isn't really a major issue here, but still it is a factor. It is also somewhat trickier than Rhino to get to grips with, at least for someone that has only just got to grips with the simpler aspects of Rhino.

For the present I am going to use Rhino, and I am going to hope I do not have to mock any sealed classes. If I do then TypeMock.NET may save me, but I suspect at that point I am in deeper trouble anyway. The two syntaxes are different enough that the learning curve is probably not worth it until I hit those 'sealed class' cases.

The Rhino Mocks version:

        [TestMethod]
        public void TestLookupUniqueItemReturnsSingle()
        {
            MockRepository mocks = new MockRepository();
            ICustomSPQuery query = mocks.CreateMock<ICustomSPQuery>();
            ICustomSPList list = mocks.CreateMock<ICustomSPList>();
            ICustomSPListItemCollection expectedResults = mocks.CreateMock<ICustomSPListItemCollection>();
            ICustomSPListItem listItem = mocks.CreateMock<ICustomSPListItem>();

            int numberOfResultsToReport = 1;

            With.Mocks(mocks).Expecting(
                delegate
                    {
                        using (mocks.Unordered())
                        {
                            Expect.Call(query.Query).PropertyBehavior().IgnoreArguments();
                            Expect.Call(list.GetItems(query)).IgnoreArguments().Return(
                                expectedResults);
                            Expect.Call(expectedResults.Count).Return(numberOfResultsToReport).
                                Repeat.Any();
                            Expect.Call(expectedResults[0]).Return(listItem);
                        }
                    })
                .Verify(
                delegate
                    {
                        ListLookup lookup = new ListLookup(list, query);
                        ICustomSPListItem lookupResult = lookup.LookupUniqueItem("test", "test");
                        Assert.AreEqual(listItem, lookupResult);
                    }
                );
        }

And the TypeMock.NET version:

        [TestMethod]
        public void TestSingleItemFindsMatch()
        {
            MockManager.Init();
            ICustomSPList list = (ICustomSPList)RecorderManager.CreateMockedObject(typeof(ICustomSPList));
            ICustomSPQuery query = 
               (ICustomSPQuery)RecorderManager.CreateMockedObject(typeof(ICustomSPQuery));
            ICustomSPListItemCollection expectedResults = (ICustomSPListItemCollection)RecorderManager
                .CreateMockedObject(typeof(ICustomSPListItemCollection));
            ICustomSPListItem item = 
                (ICustomSPListItem)RecorderManager.CreateMockedObject(typeof(ICustomSPListItem));

            using (RecordExpectations recorder = new RecordExpectations())
            {
                query.Query = "";
                recorder.ExpectAndReturn(list.GetItems(null), expectedResults);
                recorder.ExpectAndReturn(expectedResults.Count, 1).RepeatAlways();
                recorder.ExpectAndReturn(expectedResults[0], item);
            }

            ListLookup listToLookup = new ListLookup(list, query);
            ICustomSPListItem result = listToLookup.LookupUniqueItem("FieldName", "MyValue");
            Assert.AreEqual(item, result);
            MockManager.Verify();
        }

There is one more point in favour of Rhino Mocks ... its author Oren Eini (known as Ayende) is possibly one of the most talented developers I know, has a real passion for good quality code, and a deep commitment to open source and providing great tools to other developers. That alone makes Rhino an excellent choice.

Fingers crossed!

 

Sunday, November 18, 2007 7:25:31 PM (GMT Standard Time, UTC+00:00)  #    Comments [7] -
C# | Design | Development | Sample Code | SharePoint | Testing

I've been trying to work out in my head how I can deal with SharePoint in an abstracted a way as possible on my current projects. Frankly the interfaces MS provided were less than useful, or to be precise, not only did they forget to include any interfaces, but they also decided to make all their classes sealed too (*). I'm sure there are more unfriendly things they could do to developers writing SharePoint code, but I'm struggling to think of anything right now.

* Edit 29/11/2007 - just pointed out to me, that 'all their classes sealed' was a bit of a generalisation (and me ranting and fuming). Actually only a few key ones are sealed, but they do have a habit of having no default constructors, have no interfaces, and frankly are damn impossible to mock properly (TypeMock.NET excepted) ... hence the need for all this stuff.

So my thinking at present is along the lines of "I'm gonna write me a whole damn abstraction layer to SharePoint, because it has to be faster than coding against SharePoint directly and dealing with lack of unit testing and any kind of decoupling"

The Interfaces

The first step was to start creating interfaces that mimicked the Microsoft.SharePoint API:

image

This was pretty much the minimum number of interfaces I had to create, and I expect many more. This set will let you do basic list operations, but for anything beyond that, expect a lot more typing (or cheat and use ReSharper to extract the interfaces from your decorated SP classes)

A typical interface looks like:

    public interface ICustomSPList
    {
        ICustomSPListItemCollection Items { get; }
        ICustomSPListItemCollection GetItems(ICustomSPQuery query);
    }

This is a BIG task. A REALLY BIG TASK! So my first steps were to only abstract the classes, properties and methods I was using in the first few tasks of the overall project. Obviously this reduces the up-front work considerably, but I am crossing my fingers that it doesn't hide a nasty problem down the line. I'm pretty sure MS has done som