Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Refactoring Service Dependencies to Separated Interface

There are two factors which have a tremendous impact on a team's likelihood to abandon unit testing:

  • Fragile tests which break often and require regular maintenance; and
  • Slow tests which add excruciating seconds, if not minutes, to the total time of unit test runs.

I find that fragile tests are often those that depend on data within a database, which can become out of synch with the assertions in the unit test, and those that depend on external services.  I use the term "services" loosely to define anything that represents an external resource; examples include web services (including RESTful services), file repositories, databases, and remote procedure calls.  But these dependencies on services aren't just bad for keeping unit tests running fast and stable; they can often lead to maintenance problems due to tight coupling.  This post presents a common scenario wherein business logic is tightly coupled to a service and provides instruction for refactoring the concrete dependency to a more testable and loosely coupled configuration.

Separated Interface & Motivations for its Inclusion

The design pattern known as "Separated Interface" (coined by Martin Fowler; aka "Dependency Inversion" by Robert Martin) is a technique for reducing coupling to concrete dependencies; it achieves this by coding to the interface of the dependency while maintaining the implementation details of the dependency within a separate application layer.  You'll find that the trick of using separated interface, as with any design pattern, is knowing when to use it appropriately, rather than how to use it, as the underlying mechanism is rather straight forward.  I find it best to use on most external services, as defined earlier, but should still be considered on a case by case basis.  You should ask yourself if introducing Separated Interface will make the overall application more maintainable and testable while keeping complexity to a minimum.  When used appropriately, the benefits of this decoupling include:

  • Improving the ability to unit test "around" the dependency using mocks/stubs,
  • Greatly increasing the performance of domain oriented unit tests as a side effect of using mocks/stubs,
  • Consolidating dependency communication details to a separate tier,
  • Providing a plug-in architecture for external dependencies to be easily swapped without recompiling (e.g., when that 3rd party tool gets upgraded), and
  • Allowing developers to develop and compile the domain logic without having all the dependencies in place (e.g., not having to install 3rd party tools A, B, and C just to develop and compile unrelated code).

To illustrate, the following diagram shows two separate assemblies within the project solution.

  • The Project.Core assembly contains all of the domain logic for the application.  In addition to domain objects, such as Customer and Order, this example assembly also contains an interface to an external service; in this case, IOrderDao, which represents an interface to a data-access object.  Note that this is only the interface of that service; the domain logic has no idea (or dependency) on the underlying implementation details outside of its conformance to the interface.
  • The Project.Data assembly contains all of the implementation details for the interface and contains an assembly reference back to Project.Core.  This is the fundamental key to Separated Interface.  In most applications, the data communications and external dependencies are depended on by the business logic.  With Separated Interface, the reverse is true wherein the service implementation depends on the interfaces within the domain layer - the true core of the application.

Separated Interface

This pattern typically presents two challenges.  The first is, how does the domain logic get passed a reference to the actual concrete dependency if all it knows about is an interface?  The dependency can get passed to the domain object via its constructor or a setter either manually or with an IoC container, such as Castle Windsor or Ninject.  (See http://www.codeproject.com/KB/architecture/DependencyInjection.aspx for an example of doing so.)  The second and more challenging problem is, how can we get the external resource to depend on our domain layer interface when it's a third party tool?  Recall that we want the service to depend on the domain, not the other way around.  In these cases, it's appropriate to create a facade which wraps the complicated details of communicating with the dependency; then, we simply add an interface for the facade to our domain layer.  The following example will walk through looking at a real world smell of a concrete dependency on a third party API - exposed as a RESTful service - and making appropriate modifications to introduce Separated Interface.

Real World Example (aka "the smell")

To set the appropriate context, assume that (smelly) code has been developed to fulfill the following user story:  On a nightly basis, the application will download any new Observations added during the previous day, input into ExternalApp, so that they may be copied locally.  (An "observation" is the domain name of the record we're retrieving.)  The idea is that an external application exists, aptly called ExternalApp, which exposes a RESTful service to retrieve newly added records.  Our nightly process ties into the service, retrieves the appropriate records, parses the response, and copies the appropriate information locally.

Our application currently has three tiers:

  • The MySynch.Tests assembly contains unit tests to verify these processes.  (No, of course we didn't call it "MySynch," but that'll work for now.)
  • The MySynch.Core assembly contains all of the business logic for communicating with the RESTful service and processing the results.  Assume it contains one object called ObservationMigrator which encapsulates this logic.
  • The MySynch.Console application which is the nightly process, which we won't concern ourselves with here.

The following unit tests, found in the folder MySynch.Tests/Core, verify that the records can be retrieved and that the data migration is successful:

 

[TestFixture]
public class ObservationMigratorTests
{
    [Test]
    public void CanRetrieveObservationRecords() {
        ObservationMigrator migrator = new ObservationMigrator();
        IList<Observation> observations = migrator.GetNewObservations();
        Assert.That(observations.Count, Is.GreaterThan(0));
    }
    [Test]
    public void CanMigrateObservationRecords() {
        ObservationMigrator migrator = new ObservationMigrator();
        Result result = migrator.MigrateRecords();
        Assert.That(result.CompletedSuccefully);
    }
}

 

The first test is really verifying if the communications with the RESTful service - the third party tool - are successful.  The second test is verifying if the data migration occurs successfully, assuming the communications with the RESTful service are successful.  Without even looking at the underlying code, these tests are already unveiling a number of smells:

  • It's obvious that the ObservationMigrator isn't adhering to the Single Responsibility Principle (SRP).  It's providing means to communicate with the service, via GetNewObservations, and it's responsible for migrating those records to whatever destination.  Consequently, it's likely that it's inherently complex and that it's likely to be touched often during maintenance for different reasons.
  • The second test is really just trying to make sure that the migration occurs successfully without necessarily wanting to retest proper communications to the RESTful service; that was what the first test was doing.  The problem with this is that if the service goes down, in addition to breaking the first test, it'll start breaking the second test which is really domain-oriented in nature.  It would be great if we could test the migration process without having to retest the communications to the service.
  • Finally, communicating with any external resource via unit tests, especially web-based services, adds seconds to running the unit tests.  This can add minutes with hundreds of unit tests.  Again, if all we really want to test in the second test is the domain logic for completing the migration, then we shouldn't be reconfirming communications are working and adding wasted time to running the tests.

Indeed, if we look under the covers at the ObservationMigrator class, we confirm our concerns with respect to SRP and HTTP requests embedded into the business logic:

 

public class ObservationMigrator
{
    public IList<Observation> GetNewObservations() {
        WebClient webClient = new WebClient();
        byte[] response = webClient
            .DownloadData("http://www.example.com/RESTfulServiceToRetrieveRecords");
        string responseContent = Encoding.ASCII.GetString(response);
        IList<Observation> observations = new List<Observation>();
        // Lots of complicated parsing...like, crazy complicated
        return observations;
    }
    // Result is a DTO which let's the caller know if everything succeeded
    public Result MigrateRecords() {
        IList<Observation> observations = GetNewObservations();
        foreach (Observation observation in observations) {
            // Migrate each observation to the appropriate repository
        }
        return new Result(...);
    }
}

 

Refactoring Mechanics

In refactoring this code, we'll want to follow the steps below to reduce the amount of work done between tests and to minimize the amount of breaking code in the system at any given point in time.  Our goal is to always be very close to a check-in...the "don't anybody check anything out for the next two days" won't fly here.

  1. Refactor with Extract Class to pull the RESTful communication and parsing logic into it's own class.  This extracted class becomes the facade to the underlying RESTful API.
  2. Refactor with Extract Interface to create an interface for the new API facade.
  3. Refactor with Introduce Constructor Injection to replace the creation of the dependency with a constructor parameter.
  4. Refactor with Introduce Stub Object to modify the testing of the migration test to focus on the domain logic rather than on retesting communications with the API.
  5. Refactor Architecture by Tiers to move the implementation details to a separate tier.

Step 1:  Extract Class

So without further ado, let's start with step 1, extracting a class to act as a facade to the underlying RESTful API.  As always, we begin with a test; let's do so by adding a new test as follows:

 

[TestFixture]
[Category("ExternalApp Integration")]
public class ObservationRetrieverTests
{
    [Test]
    public void CanRetrieveRecordsToImport() {
        ObservationRetriever observationRetriever = new ObservationRetriever();
        IList<Observation> observations = observationRetriever.GetNewObservations();
        Assert.That(observations.Count, Is.GreaterThan(0));
    }
}

 

Note that we've added this fixture to a category called "ExternalApp Integration."  Doing so, we're able to conveniently turn off this slow-running category of unit tests while we're working on other areas of the application.  Compiling this breaks, so the next step is to add just enough code to MySynch.Core to get the test to compile:

 

public class ObservationRetriever
{
    public IList<Observation> GetNewObservations() {
        throw new NotImplementedException();
    }
}

 

You should now be able to run the test and see it fail with a NotImplementedException.  Yes, you want it to fail...a failing test is your next goal to fix.  So now let's write enough code to get it to pass by copying the GetNewObservations() method from ObservationMigrator into ObservationRetriever:

 

public class ObservationRetriever
{
    public IList<Observation> GetNewObservations() {
        WebClient webClient = new WebClient();
        byte[] response = webClient
            .DownloadData("http://www.example.com/RESTfulServiceToRetrieveRecords");
        string responseContent = Encoding.ASCII.GetString(response);
        IList<Observation> observations = new List<Observation>();
        // Lots of complicated parsing...like, crazy complicated
        return observations;
    }
}

 

All the unit tests should now be passing again.  But we've introduced a problem...the smell of duplicated code.  We can remove this smell by replacing the ObservationMigrator.GetNewObservations() method with the creation of an ObservationRetriever object and the invocation of the method therein:

 

public class ObservationMigrator
{
    public Result MigrateRecords() {
        ObservationRetriever observationRetriever = new ObservationRetriever();
        IList<Observation> observations = observationRetriever.GetNewObservations();
        foreach (Observation observation in observations) {
            // Migrate each observation to the appropriate repository
        }
        return new Result(...);
    }
}

 

You'll need to drop ObservationMigratorTests.CanRetrieveObservationRecords() to get it to compile; but all the tests should still be passing.  We've officially completed step 1 by extracting a class from the ObservationMigrator class into a facade class which only concerns itself with communicating with the RESTful API and parsing the results.

Step 2:  Extract Interface

Step 2 is introducing the interface to our service.  Instead of creating a new test, we simply modify the ObservationRetrieverTests.CanRetrieveRecordsToImport() method to invoke GetNewObservations() via an interface rather than the concrete object itself:

 

[TestFixture]
[Category("ExternalApp Integration")]
public class ObservationRetrieverTests
{
    [Test]
    public void CanRetrieveRecordsToImport() {
        // Note the "I" that's been introduced below
        IObservationRetriever observationRetriever = new ObservationRetriever();
        IList<Observation> observations = observationRetriever.GetNewObservations();
        Assert.That(observations.Count, Is.GreaterThan(0));
    }
}

 

Since a quick compilation shows that this isn't compilable (and it shouldn't be), let's add an interface to MySynch.Core which reflects the method on our facade class, and have ObservationRetriever then implement that interface.  First, the interface that we need to add to MySynch.Core:

 

public interface IObservationRetriever
{
    IList<Observation> GetNewObservations();
}

 

Then, simply have the ObservationRetriever class implement this interface:  public class ObservationRetriever : IObservationRetriever { ...

All unit tests should be passing again...oh, happy days again.

Step 3:  Introduce Constructor Injection

The ObservationMigrator class still has a concrete dependency on the ObservationRetriever...damn that concrete dependency!!  So let's now introduce constructor injection to remove this tight coupling.  Guess where we're going to start...that's right, back in a unit test.  But here again, we don't need to add a new test, we simply need to alter an existing one, ObservationMigratorTests.CanMigrateObservationRecords().  The modified test should be as follows:

 

[Test]
public void CanMigrateObservationRecords() {
    IObservationRetriever observationRetriever = new ObservationRetriever();
    ObservationMigrator migrator = new ObservationMigrator(observationRetriever);
    Result result = migrator.MigrateRecords();
    Assert.That(result.CompletedSuccefully);
}

 

All we're intending to do here is to pass an instance of IObservationRetriever to the migration utility rather than having it create its own.  Tying to compile breaks the build, so now let's write just enough code to get this puppy to compile...usually we'd write just enough to compile and then just enough to pass, but I'm getting tired of writing, so we'll combine the two here:

 

public class ObservationMigrator
{
    public ObservationMigrator(IObservationRetriever observationRetriever) {
        // Let's do a design-by-contract (DbC) check to make sure we're not 
        // given a null service dependency. For more about this, see 
        // http://devlicio.us/blogs/billy_mccafferty/archive/2006/09/22/Design_2D00_by_2D00_Contract_3A00_-A-Practical-Introduction.aspx
        Check.Require(observationRetriever != null, 
            "observationRetriever may not be null");
        this.observationRetriever = observationRetriever;
    }
    public Result MigrateRecords() {
        IList<Observation> observations = observationRetriever.GetNewObservations();
        foreach (Observation observation in observations) {
            // Migrate each observation to the appropriate repository
        }
        return new Result(...);
    }
    private IObservationRetriever observationRetriever;
}

 

With these changes, everything should now compile and the tests should be passing again.

Step 4:  Introduce Stub Object

As mentioned in the previous gripes against the original code, the ObservationMigratorTests.CanMigrateObservationRecords() test shouldn't be worried about communicating with the RESTful service; it should only be concerned with ensuring the migration occurs assuming the RESTful service is working as expected.  The ObservationRetrieverTests.CanRetrieveRecordsToImport() test is already verifying that the service is working, so it's just adding extra time and complexity to the ObservationMigratorTests.CanMigrateObservationRecords() test.  Therefore, let's now introduce a stub object to simulate communications with the RESTful service.  Keep in mind that this modification isn't being done to test new functionality; instead, it's a refactoring to an existing unit test to properly focus the test's attention on the domain logic.  Accordingly, the ObservationMigratorTests now reflects the following:

 

[TestFixture]
public class ObservationMigratorTests
{
    [Test]
    public void CanMigrateObservationRecords() {
        IObservationRetriever observationRetriever = new ObservationRetrieverStub();
        ObservationMigrator migrator = new ObservationMigrator(observationRetriever);
        Result result = migrator.MigrateRecords();
        Assert.That(result.CompletedSuccefully);
    }
    private class ObservationRetrieverStub : IObservationRetriever
    {
        public IList<Observation> GetNewObservations() {
            IList<Observation> observations = new List<Observation>();
            observations.Add(new Observation(...));
            observations.Add(new Observation(...));
            observations.Add(new Observation(...));
            return observations;
        }
    }
}

 

In the unit test above, a stub object has been created which implements IObservationRetriever and fakes communications with the external service to retrieve three new Observation records.  The ObservationMigrator.MigrateRecords() method happily uses this stub, not knowing that it's actually not talking to the external RESTful service.  We're now focusing this unit test on testing the domain logic, outside of communicating with the RESTful service.  Again, the ObservationRetrieverTests fixture of tests is already testing the communications with this service and related parsing functionality...no need to retest it here.

In such a simple case, where the interface only has one method to implement, a stub is perfectly adequate.  But we're passing three observations to the migration step without verifying that all three were processed...we might as well have just passed one, or none at all for that matter.  This test could be extended in two ways to verify the underlying migration processed each and every Observation appropriately.  The first is that we could include the status of how many observations were migrated within the Result object returned from the migration step.  The other way is to use a mock object, instead of a stub, which can verify that the expected behavior is occurring under the scenes.  Although mocking is beyond the scope of this post, I encourage you to take a look at http://xunitpatterns.com/ and Rhino Mocks for more information.

Step 5:  Refactor Architecture by Tiers
(i.e., add the "Separated" part of "Separated Interface")

After all of this, we're finally at the point of culmination:  the introduction of the Separated Interface.  But by now, it's rather anticlimactic as the hard work has already been done.  Nonetheless...on with the anticlimactic conclusion!  A problem with the solution as it stands is that the service facade still physically resides in the MySynch.Core assembly.  Consequently, there's nothing we can do to prevent developers from bypassing our elegant interface and go straight to the ObservationRetriever class itself.  This is a wonderful side benefit of introducing Separated Interface; it forces developers to adhere to certain design decisions.  To mitigate this concern, and to remove all coupling from MySynch.Core to the implementation details of ObservationRetriever, we'll refactor the architecture itself to move the implementation details to a separate tier.  Let's head back to the tests assembly and add a new folder called ExternalAppIntegrator; recall that "ExternalApp" is the name of our 3rd party tool which exposes the RESTful service.  Now move the ObservationRetrieverTests class to this new folder.  This new folder represents the new class library that we'll be introducing.  The ObservationRetrieverTests class should then be modified to reflect the change in namespace and a using statement to pull in the class library which we have not yet created (remember...write the test and then write the code to get the test to pass):

 

using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using System.Collections.Generic;
// The compiler will throw an error on the following line since 
// the ExternalAppIntegrator.Core class library doesn't exist yet
using ExternalAppIntegrator.Core;
namespace Tests.ExternalAppIntegrator.Core
{
    [TestFixture]
    [Category("ExternalApp Integration")]
    public class ObservationRetrieverTests
    {
        [Test]
        public void CanRetrieveRecordsToImport() {
            IObservationRetriever observationRetriever = 
                new ObservationRetriever();
            IList<Observation> observations = 
                observationRetriever.GetNewObservations();
            Assert.That(observations.Count, Is.GreaterThan(0));
        }
    }
}

 

We've introduced some work for us here, but we will overcome!  Firstly, create a new class library called "ExternalAppIntegrator.Core" and add a reference to it from our MySynch.Tests assembly.  Next, move the class MySynch.Core/ObservationRetriever.cs to the ExternalAppIntegrator.Core class library...be sure you move it completely by deleting the original.  Ack...a new problem now!  We've moved the class but it depended upon IObservationRetriever.  Fear not!  Simply add a reference to MySynch.Core to the ExternalAppIntegrator.Core class library.  Since we've removed all other dependencies to the ObservationRetriever from MySynch.Core, all the unit tests will still pass.  As a matter of fact, we're done!

But wait, how do we know it's working?  Although not necessary, since the unit testing has proven that all of the inner workings are in order, we can make sure our Separated Interface is working as expected with the rest of the migration process by going back to ObservationMigratorTests.CanMigrateObservationRecords() and replacing the creation of the stub object with our concrete implementation:  IObservationRetriever observationRetriever = new ObservationRetriever();  With that said, I'd quickly change it back to using the stub so that we can keep that unit test focused on the domain rather than communications with the RESTful service.

In Conclusion

We've taken some rather smelly dependencies and moved them to a dedicated class library which concerns itself with the management of a facade over the external API.  We finished by having this facade implement an interface found without our domain layer so that the domain layers could communicate to the external API without having a direct, concrete dependency on the implmentation details.  The hope is that this has made our code more testable, less coupled, and more maintainable down the road.  The cost has been the introduction of increased complexity.  Accordingly, care should be taken before the introduction of any design pattern to ensure that the pattern itself is "pulling its weight," so to speak.

I have found immense value from this design pattern; it has been particularly handy for removing direct dependencies on data access objects.  The sample code that comes along with S#arp Architecture has a full example of just such an instance.  Happy coding!

Billy McCafferty


Posted 10-30-2008 6:06 PM by Billy McCafferty

[Advertisement]

Comments

Reflective Perspective - Chris Alcock » The Morning Brew #213 wrote Reflective Perspective - Chris Alcock &raquo; The Morning Brew #213
on 10-31-2008 4:32 AM

Pingback from  Reflective Perspective - Chris Alcock  &raquo; The Morning Brew #213

Ruprict wrote re: Refactoring Service Dependencies to Separated Interface
on 10-31-2008 6:24 AM

Mate,

Great post.  This is the kind of stuff I pass on saying "This articulates all the stuff I mean to say but can't b/c I am crappy communicator"

Billy McCafferty wrote re: Refactoring Service Dependencies to Separated Interface
on 10-31-2008 8:43 AM

Heh, thanks Ruprict!  Give yourself more credit man...we're all just fumbling towards geekstacy. ;)

Arjan`s World » LINKBLOG for October 31, 2008 wrote Arjan`s World &raquo; LINKBLOG for October 31, 2008
on 10-31-2008 4:36 PM

Pingback from  Arjan`s World    &raquo; LINKBLOG for October 31, 2008

Kevin Pang wrote re: Refactoring Service Dependencies to Separated Interface
on 11-02-2008 6:33 PM

Great post as always Billy.  I'm in the process of putting together a presentation for work to demonstrate the advantages of separation of concerns and dependency injection (we depend heavily on web services).  This will be a great piece to refer to.

Billy McCafferty wrote A Gem of a Lesson from Rails
on 11-11-2008 8:09 PM

For the past few months, I&#39;ve gotten the privilege to develop a good sized, production Ruby on Rails

Community Blogs wrote A Gem of a Lesson from Rails
on 11-11-2008 8:27 PM

For the past few months, I&#39;ve gotten the privilege to develop a good sized, production Ruby on Rails

Steve wrote re: Refactoring Service Dependencies to Separated Interface
on 11-12-2008 10:52 AM

Hi Billy, good write up!

I have used this system as well since reading about it in your NHibernate Best practice article awhile back.

Funny thing is, today I was looking at something by David Hayden at codebetter.com/.../Another-Inversion-of-Control-Example-With-Infrastructure-and-DAO-Components.aspx

In the comments, Scott Bellware makes a case against this separation saying

"Why was it necessary to put the interfaces into a separate component?  This would more or less de-contextualize the interfaces from the classes in the component that needs it, and ultimately tend to obscure the intention and locality of the concern represented by the interface.

I would have expected the IBlogDAO client interface to live with the component that houses the classes that it serves.  In the case of your project, I would have expected it to be in BlogEngine.Core since it is the data access client interface for Blog."

So  :)  What is the response to this outside of 'sure, go ahead then'  :)

Linkopedia November 2008 : From the Editor of Methods & Tools wrote Linkopedia November 2008 : From the Editor of Methods &amp; Tools
on 11-12-2008 11:03 AM

Pingback from  Linkopedia November 2008 : From the Editor of Methods &amp; Tools

Billy McCafferty wrote re: Refactoring Service Dependencies to Separated Interface
on 11-12-2008 11:16 AM

@Steve,

If the implementation classes are put into the same assembly as their interfaces, then there's nothing to stop a developer from bypassing the interface and going directly to the concrete dependency.  Yes, we should trust our developers; but we should also make it as easy as possible to avoid shooting themselves in the foot.

Morten Haug wrote re: Refactoring Service Dependencies to Separated Interface
on 12-03-2008 7:26 AM

@Steve & @Billy

Seems Scott is asking why the interfaces is in a totally separate project, apart from the classes that USES them. These are most often bundled together. They should of course not be together with their IMPLEMENTATIONS which would not be anything like Separated Interface at all (which was not what Scott was saying either).

DotNetKicks.com wrote Refactoring Service Dependencies to Separated Interface
on 12-31-2008 1:47 PM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Jolly-zhang wrote 转:[MVC]融合思想:深入探索S#arp架构
on 11-13-2009 3:57 AM

开发Web应用程序是痛苦的。无论是组织与测试AJAX脚本,还是在无状态环境下模拟状态,开发Web应用程序需要在计划和开发的各个阶段中,全神贯注,专心致志。Web开发人员还要面对开发中的诸多挑战,例如对...

Billy McCafferty wrote Message-Based Systems for Maintainable, Asynchronous Development
on 03-02-2010 2:35 AM

Preface (you know it’s good if there's a preface) In Architectural Paradigms of Robotic Control

Billy McCafferty wrote Message-Based Systems for Maintainable, Asynchronous Development
on 03-02-2010 2:39 AM

Preface (you know it’s good if there's a preface) In Architectural Paradigms of Robotic Control

devlicio.us wrote re: Refactoring Service Dependencies to Separated Interface
on 06-20-2011 6:06 AM

Refactoring service dependencies to separated interface.. Amazing :)

gi63 porn video pq8p wrote re: Refactoring Service Dependencies to Separated Interface
on 07-02-2011 9:22 PM

Refactoring service dependencies to separated interface.. Awesome :)

social bookmarks wrote re: Refactoring Service Dependencies to Separated Interface
on 03-14-2013 3:22 PM

oVDisi Hey, thanks for the post.Really thank you! Really Great.

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)