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
 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, March 03, 2008

The problem

We currently develop software in a fairly piecemeal and disjointed fashion. The software we develop could also be fairly accurately described as monolithic.

There are many problems that come with monolithic code, it becomes hard to maintain, hard to evolve, hard to reuse, and hard to adapt to changing requirements.

Symptoms of a Rotting Design [1] include:

Rigidity

Rigidity is the tendency for software to be difficult to change, even in simple ways. Every change causes a cascade of subsequent changes in dependent modules.

Fragility

Closely related to rigidity is fragility. Fragility is the tendency of the software to break in many places every time it is changed. Often the breakage occurs in areas that have no conceptual relationship with the area that was changed.

Immobility

Immobility is the inability to reuse software from other projects or from parts of the same project. It often happens that one engineer will discover that he needs a module that is similar to one that another engineer wrote. However, it also often happens that the module in question has too much baggage that it depends upon.

Viscosity

Viscosity comes in two forms: viscosity of the design, and viscosity of the environment. When faced with a change, engineers usually find more than one way to make the change. Some of the ways preserve the design, others do not (i.e. they are hacks.) When the design preserving methods are harder to employ than the hacks, then the viscosity of the design is high. It is easy to do the wrong thing, but hard to do the right thing.

What kinds of changes cause designs to rot?

Changes that introduce new and unplanned for dependencies cause rotting designs. Each of the four symptoms mentioned above is either directly, or indirectly caused by improper dependencies between the modules of the software. It is the dependency architecture that is degrading, and with it the ability of the software to be maintained.

In order to forestall the degradation of the dependency architecture, the dependencies between modules in an application must be managed. This management consists of the creation of dependency firewalls. Across such firewalls, dependencies do not propagate.

Object Oriented Design is replete with principles and techniques for building such firewalls, and for managing module dependencies.

The goal

To avoid some of the problems we are currently encountering, we need to move towards software development based on good principles and practices. There is fundamentally little new in software development each year, but better refinement of common patterns and practices, and we should be leveraging those to provide a more stable and adaptable software codebase.

The approach

This document deals with a limited subset of the problem; specifically it is designed to explain the requirements for Castle Windsor and Castle DynamicProxy to be included in our code. As such it does touch on a number of principles that are only partially resolved by the Castle stack, it also omits many other good principles of software development – these can be left for another discussion.

There are a number of aspects of what we currently do that could be improved by better training, better practice, and better communication – but these will not be covered in detail here.

The objectives

So as our problem is relatively wide in scope, here are some specific principles that we should be aiming for in our code. These are fairly widely established principles within the industry, so none should be of any great surprise. Possibly the greater surprise will be that we are using almost none of these, at least not in any explicit or agreed upon method. This list is only a subset of a wider set or principles we should be aiming for.

Single Responsibility Principle (SRP) [2]

There Should Never Be More That One Reason for a Class to Change

Responsibilities should be considered as axis of change – if a class assumes more than one responsibility, then it has more than one possible reason to change, and becomes a weak point in the design. This coupling leads to fragile designs that break in unexpected ways.

This class level principle applies at a wider level, where it is commonly referred to as Separation of Concerns.

Separation of Concerns (SoC) [3]

The principle that software components should be broken to smaller parts that overlap in functionality as little as possible. Examples of SoC in practice would be adoption of design patterns such as Model-View-Presenter, or Service Oriented Architecture.

A concern at modular level could be considered the separation of display logic, from business logic. The separation of data access from data manipulation. Or at a lower level, the separation of configuration from processing logic.

By separating each of the concerns away from each other – you obtain the ability to alter each of those concerns independently, whether due to a change in the requirements, and evolution of the system, a bug fix, or for any other reason you may have for change.

Application of SoC allows you to create and evolve Loosely Coupled Systems, a primary objective of good software design.

The Dependency Injection Principle (DIP) [4]

A: High Level Modules Should Not Depend Upon Low Level Modules, Both Should Depend Upon Abstractions
B: Abstractions Should Not Depend Upon Details, Details Should Depend Upon Abstractions

By inverting the dependency structure we eliminate a common problem where a small change to environment or requirements cascades through our entire application. By using the DIP we isolate those changes.

Consider the most commonly written example, that of a class or component that requires configuration information – for the sake of this example let us refer to it as the DataService class.

A traditional approach to writing this might be to have the DataService class call the ConfigurationManager to get the settings it requires. At this point however, your class now depends upon the ConfigurationManager – it cannot be compiled if this manager is not present, it cannot execute if this class is not present, and it cannot have the source of its configuration information changed without a recompilation at least, and possibly a rewrite at worst.

Dependency Injection turns this concept upside down – quite literally. This is why this is commonly referred to as Inversion of Control (IoC) [5]

We now design our DataService class so that instead of it talking directly to a ConfigurationManager, it is given an abstraction of the ConfigurationManager by the code that created our class. The responsibility for the source and creation of the ConfigurationManager is no longer a concern of our DataService class, but of the thing that created it. So in our example we create an interface called IConfigurationManager, one implementation of which is our real ConfigurationManager. Now when we create our DataService, we tell it specifically which instance of IConfigurationManager it should use to get its configuration information.

This principle has multiple benefits, apart from helping achieve the primary objectives of maintainability, SoC and SRP, it also fulfils one other fundamental objective, it allows Unit Testing.

If a class like our original DataService is to be unit tested, we must have a ConfigurationManager in place. The ConfigurationManager must be the exact same version as will be used in our application, and it will bring with it all the dependencies it contains. In fact, you will probably have to put the DataService into a nearly fully implemented application, just to test a basic part of its behaviour.

After we have applied Inversion of Control we can now unit test the DataService independently of its configuration requirements. We can create a mock implementation of our IConfigurationManager that passes in a known configuration set, and therefore allows us to have a known outcome state after a request. We are no longer tied to tests that may break when someone changes the format of the configuration data, or changes the data store, and in the case of our DataService, we no longer require a database in place, just to see if the DataService correctly requests database information.

Unit Testing and Test Driven Development [6][7]

By using Inversion of Control we can now write valid unit tests. The qualification of “valid” is very important here, a poor unit test is one that tests more than it should – in much the same way as application of SRP, a unit test that tests more than one thing is fragile and prone to breaking for the wrong reasons.

A differentiation should also be drawn between a “unit test” and an “automated integration test”. While both may use a xUnit framework such as NUnit or MbUnit, there is a very important distinction. A unit test tests one thing and one thing only ... it tests a “unit” – an integration test tests more than one thing, hence it is not a unit test.

So back to our previous example, a unit test that tested a function of the DataService is desirable and should be our primary objective, but if it was to test the DataService that called the ConfigurationManager, it is now actually testing at least two components, and is possibly testing a few dozen more (all of the dependencies that ConfigurationManager has are being tested too). With IoC we can provide a mock IConfigurationManager and ensure we are only testing the DataService – a single unit. Changes to the ConfigurationManager implementation or one of its dependencies can no longer break our unit tests.

Not only that, but it is entirely possible in our example that we cannot unit test our DataService at all, as it requires infrastructure code and data that may not be present at test time. It is also highly likely that we will end up with a large and interdependent set of configuration sources within our tests to try and mimic all the possible permutations of configuration data we may expect, creating highly fragile and hard to understand tests.

One simple abstraction avoids all of this.

The solution

So Why Do We Need an Inversion of Control Container?

The example given so far is pretty easy to follow. We don’t access configuration within our DataService, but the code that creates the DataService also creates the ConfigurationManager implementation and passes it in.

However if you follow this all the way down the software stack, you will realise that at some point, there must be a concrete dependency ... something has to know how to create all these concrete dependencies, and therefore it has the dependencies itself.

This is where an IoC container such as Castle Windsor comes into play.

What Does Castle Windsor [8] Do?

Inversion of Control containers allow you to achieve loosely coupled designs and they handle dependency and configuration management when you, or a class in your system, request a service to say, send e-mails, you will get an instance ready to be used.

IoC containers favour reuse as they allow you to use a natural idiom to expose the component's dependencies. This allows components to be used with or without containers. Hence you quickly end up with a library of reusable components that can be shared among projects, as long as you apply the Separation of Concerns principle.

Castle Windsor allows components within the system to be registered with it, and when it receives requests for those objects, it is responsible for creating them, and maintaining their lifestyles. Where you require a singleton, it will provide that for you, and where you require a thread pooled object, it can provide that for you too – without any alteration of your codebase.

More importantly, it is capable of resolving all sub-dependencies that a class has. So back to our example, we don’t need to create an instance of the IConfigurationManager, and an instance of the DataService, or create any instances of all the other things that DataService may depend upon – Windsor knows all of this and will do this work for us.

So when we ask Windsor to give us the DataService, it will create all dependency objects too, pull configuration from an external source if we have specified that, and return us back a single fully constructed object graph. This avoids the problems of fragile code, as a change to the dependencies of our DataService is now transparent to all the code that uses our DataService.

Windsor also brings additional benefits far beyond the basics of object creation and management. As it contains the ability to create interceptors, it becomes very easy to add functionality that exposes cross cutting concerns such as logging. When we request our DataService now, Windsor knows that our configuration says Windsor should attach a logger to our methods, and it will do all the work needed to create the classes to manage those objects. This functionality can be extended to allow for many other cross cutting concerns such as authentication, authorization, and extension of existing business logic.

The critical part of Windsor for us in many respects is that it is highly extensible; almost any scenario you can envisage with regards to object creation or management is a simple step to configure or to extend.

What is Castle Windsor?

Castle Windsor is a component part of the Castle open source project that has been in existence since 2003, and was built upon lessons learned from the Java community and earlier .Net projects.

Most recently, part of the Castle stack, MonoRail has been a major factor in Microsoft moving towards MVC development under ASP.NET, with contributors to MonoRail being asked for their views on the development direction by the team developing ASP.NET MVC

Castle Windsor could also be said to have been a major influence in Microsoft creating their own Inversion of Control container, Unity. Unity is currently only under CTP, but will be released, as Castle Windsor is, with an open licence and source code available. There are a number of differences between Windsor and Unity, this document does not discuss them, and instead recommends Windsor initially, with an option to move to Unity should that need become apparent or viable in future – at present Unity does not solve many of the scenarios we wish to cover.

Licensing for Castle Windsor

It is released under the terms of Apache Software Foundation License 2.0 [9], which is possibly the most open of all licences. The Apache License (versions 1.0, 1.1, and 2.0) requires preservation of the copyright notice and disclaimer, but it is not a copyleft license — it allows use of the source code for the development of free and open source software as well as proprietary software. Although lawyers can give you a legal list of restrictions this imposes, it fundamentally comes down to “do what you want with it as long as the copyright notice remains”

What is the Support Behind Castle Windsor?

As an open source project, Castle Windsor could be said to be one of the most mature and continually developed projects around. Although officially at RC3 for a large number of months so far, this is mainly due to a project requirement that version 1.0 will not be released until the external API can be guaranteed to be stable.

On a daily basis, Castle Windsor can be considered highly stable, and is being constantly developed. The few bugs that are present are resolved rapidly, and there is commercial support available should that be a requirement – though with full access to the source code this would appear unnecessary.

[1] Robert C Martin :
http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf
[2] Robert C martin :
http://www.objectmentor.com/resources/articles/srp.pdf
[3] Wikipedia :
http://en.wikipedia.org/wiki/Separation_of_concerns
[4] Robert C Martin :
http://www.objectmentor.com/resources/articles/dip.pdf
[5] Wikipedia :
http://en.wikipedia.org/wiki/Inversion_of_control
[6] Wikipedia :
http://en.wikipedia.org/wiki/Unit_testing
[7] Wikipedia :
http://en.wikipedia.org/wiki/Test-driven_development
[8] Castle :
http://www.castleproject.org/container/gettingstarted/index.html
[9] Wikipedia :
http://en.wikipedia.org/wiki/Apache_license

 

Monday, March 03, 2008 10:15:37 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
Agile | Castle | Design
 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
 Friday, December 21, 2007

Early in the new year my current client has asked me to present to the senior management on two areas they feel they can currently improve in, their RUP project management process, and their development processes overall.

Attached are two presentations in their early form, in PowerPoint 2003 format.

Missing from the presentations are the notes (which I will add once I am happy with the overall structure) but you should be able to figure out what I am intending to say for each slide/bullet point.

Both of these presentations will evolve over the next few weeks. Feel free to comment either by the comment option or directly to me, and if you think they will be helpful to you for a presentation, also feel free to use them and modify them as you see fit.

Agile.ppt (80.5 KB)

This is intended to give a very high level view of Agile, to a group of senior managers who practice almost none of these things at present, and who are not 'tech savy'. This is fundamentally a 'get to know you' kind of presentation, to encourage aspects of Agile to be adopted, rather than any specific methodology or practice.

Development.ppt (80.5 KB)

This is intended to be presented to a similar level group, but the audience members may overlap to some degree with the previous presentation, and some may not. At the moment it is more likely that these people are closer to the ground and more 'tech focused'.

It is intended to give some key practices that can help improve the development processes the client currently has, again without forcing a wholesale shift to a specific Agile methodology on to them.

Oh, and Merry Xmas (or whichever thing you celebrate at this time of year!)

 

Friday, December 21, 2007 8:39:32 AM (GMT Standard Time, UTC+00:00)  #    Comments [4] -
Design | Agile | alt.net
 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 something really dumb somewhere to prevent this working, but so far so good.

The Decorators

Then there was a need to create decorators for each of the SharePoint objects we are abstracting, and delegating all calls through to the Microsoft.SharePoint classes:

The decorator class for the ICustomSPList looks like this:

    public class CustomSPList : ICustomSPList
    {
        private readonly Microsoft.SharePoint.SPList _list;

        public ICustomSPListItemCollection Items
        {
            get { return new CustomSPListItemCollection(_list.Items);}
        }
        public CustomSPList(Microsoft.SharePoint.SPList list)
        {
            _list = list;
        }

        
        public ICustomSPListItemCollection GetItems(ICustomSPQuery query)
        {
            Microsoft.SharePoint.SPQuery tempQuery = new Microsoft.SharePoint.SPQuery();
            tempQuery.Query = query.Query;
            return new CustomSPListItemCollection(_list.GetItems(tempQuery));
        }
    }

Basic Usage

We now have a basic way to perform SharePoint operations without being tied into the Microsoft.SharePoint dependency:

    ICustomSPWeb web = properties.OpenWeb();
    ICustomSPList registryList = web.Lists["Registry"];
                    
    ICustomSPQuery query = new SPQuery();
    query.Query = "<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>My Title</Value>
                   </Eq></Where>";

    ICustomSPListItemCollection regList = registryList.GetItems(query);

The Next Step

We have our basic abstraction in place now, and with a little magic from an IoC container like Windsor we can write the core of our application safe in the knowledge that we aren't heading down a dead end of a coupled system. We also have a system that, although it is using the SharePoint API, could be switched to a different persistence medium should the need arise.

But that is only half the story, and in fact the really important part ... we can now properly mock and unit test our code.

 

Sunday, November 18, 2007 7:12:47 PM (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET | C# | Design | Development | SharePoint | Testing
 Wednesday, October 10, 2007

It is amazing how much time you have to think while painting a house. Painting is tedious, repetitive, and one lapse of concentration leads to a mess that takes a lot of effort to sort out. In fact, whilst painting it occurred to me there were a lot of parallels with software development.

Firstly, preparation. Doing your groundwork first saves time in the long run, makes for a much better job overall, and prevents "unforeseen eventualities". In software that means making sure you have your requirements established, have your processes in place, have your team up to speed on the technologies you will be using, and in general have a plan of attack.

Secondly, attention to detail. It is so tempting to just skip a bit, not paint right up to the edge, use only one coat when two are really needed. After all - who would notice? Likewise with software, the temptation is always there to skip proper exception handling, not check values passed to your function, assume that the developer that uses your class won't care if you don't use meaningful method names. Short term gain, for long term pain.

And satisfaction value ... a job well done is one you can be proud of, that makes you feel all fuzzy and warm inside. So it has some plus points even if it takes a little longer and takes a little more care.

On the plus side, the hallway is nearly finished, shiny new white woodwork, deep luxurious 'sienna sun' walls (brown to the uninitiated).

 

Technorati Tags:
Wednesday, October 10, 2007 4:47:04 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
Design | Development | rants
Navigation
Archive
<July 2008>
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2008
Casey Charlton
Sign In
Statistics
Total Posts: 41
This Year: 13
This Month: 0
This Week: 0
Comments: 27
Themes
Pick a theme:
All Content © 2008, Casey Charlton
DasBlog theme 'Business' created by Christoph De Baene (delarou)