Constructor over-injection smell – follow up

This is a follow up to my article: “Constructor over-injection anti-pattern”.  I’ve title this a bit differently because as with any heuristic, there are degrees of goodness and smelliness.  Constructor over-injection, therefore, is a code smell, I believe.  Without concrete do’s and don’ts, I believe it doesn’t deserve the explicit title of “anti-pattern”.

I have expanded the code sample (and it is available as a zip or tar file here).

I’ve modified the OrderProcessor as shown here.  I believe this is more egregious and is more of an obvious example.  Small samples get so trivial, that the pain show doesn’t seem like a problem at all, but when injected constructor arguments increase (think 5, 10, 20), the pain is greater.

   1:  namespace DIAntiPattern
   2:  {
   3:      public class OrderProcessor : IOrderProcessor
   4:      {
   5:          private readonly IOrderValidator _validator;
   6:          private readonly IAccountsReceivable _receivable;
   7:          private readonly IRateExchange _exchange;
   8:          private readonly IUserContext _userContext;
   9:   
  10:          public OrderProcessor(IOrderValidator validator,
  11:                                IAccountsReceivable receivable,
  12:                                IRateExchange exchange, IUserContext userContext)
  13:          {
  14:              _validator = validator;
  15:              _receivable = receivable;
  16:              _exchange = exchange;
  17:              _userContext = userContext;
  18:          }
  19:   
  20:          public SuccessResult Process(Order order)
  21:          {
  22:              bool isValid = _validator.Validate(order);
  23:              if (isValid)
  24:              {
  25:                  Collect(order);
  26:                  IOrderShipper shipper = new OrderShipperFactory().GetDefault();
  27:                  shipper.Ship(order);
  28:              }
  29:   
  30:              return CreateStatus(isValid);
  31:          }
  32:   
  33:          private void Collect(Order order)
  34:          {
  35:              User user = _userContext.GetCurrentUser();
  36:              Price price = order.GetPrice(_exchange, _userContext);
  37:              _receivable.Collect(user, price);
  38:          }
  39:   
  40:          private SuccessResult CreateStatus(bool isValid)
  41:          {
  42:              return isValid ? SuccessResult.Success : SuccessResult.Failed;
  43:          }
  44:      }
  45:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Notice specifically that IRateExchange is NOT a dependency of OrderProcessor at all.  It is actually needed by an aggregate root, Order, so that it can do the price conversion based on exchange rates and prices.  This particular design attempted put put that logic as close to the domain model as possible (inside an aggregate).  This code works, but it requires the caller to pass through the dependency.  Here is the Order class:

   1:  using System;
   2:   
   3:  namespace DIAntiPattern
   4:  {
   5:      public class Order
   6:      {
   7:          public DateTime Placed { get; set; }
   8:          public string OtherInfo { get; set; }
   9:          public Price GetPrice(IRateExchange exchange, IUserContext userContext)
  10:          {
  11:              User currentUser = userContext.GetCurrentUser();
  12:              Currency currency = userContext.GetSelectedCurrency(currentUser);
  13:              int priceInSelectedCurrency = exchange.Convert(GetPrice(), currency);
  14:              var price = new Price{Currency = currency, Value = priceInSelectedCurrency};
  15:              return price;
  16:          }
  17:   
  18:          private int GetPrice()
  19:          {
  20:              //do work to aggregate prices from line items, and total up order.
  21:              return 1000;
  22:          }
  23:      }
  24:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

There are plenty of options to fix this code, and I’m sure you will comment on the one you prefer.  The SMELL here is constructor over-injection.  The injected dependency isn’t a dependency, and another dependency is sometimes a dependency of a particular supported operation of a class.

However you fix this example, IRateExchange does not deserve to be constructor-injected into OrderProcessor.  Next, LineItem will need a dependency to calculate something, and then the dependency has to flow through from an object that is managed by the IoC container.

IoC containers are just tools, but we still have to be careful of constructor over-injection. 

I welcome the comments, and don’t forget to download the code (and fork it to post about your own counter example). 

Constructor over-injection anti-pattern

Check out http://jeffreypalermo.com/blog/constructor-over-injection-smell-ndash-follow-up/ for a follow-up

I’m interested in structure.  We hear lots of talk about convention over configuration.  I’m all for structure over convention (over configuration).  This post is about laying out some code that is an anti-pattern.  It uses 100% constructor injection.  This code makes it easy for a container to bootstrap the construction of the objects, but let’s take a look at why this specific scenario is an anti-pattern and what design would be better.

Example

I have an order processing application that gets 10 orders at a time and tries to process them to shipping.  There are some validation steps, and then there is some work to ship the order.  Here is our Main() method:

   1:  public static void Main()
   2:  {
   3:      DateTime startTime = DateTime.Now;
   4:      Console.WriteLine("Begin: " + startTime.TimeOfDay);
   5:      IEnumerable<Order> orders = GetNextTenOrders();
   6:   
   7:      foreach (var order in orders)
   8:      {
   9:          IOrderProcessor processor =
  10:              ObjectFactory.GetInstance<IOrderProcessor>();
  11:          SuccessResult successResult = processor.Process(order);
  12:          if (successResult == SuccessResult.Success)
  13:          {
  14:              RecordSuccess(order);
  15:              continue;
  16:          }
  17:   
  18:          ReportFailure(order);
  19:      }
  20:      DateTime endTime = DateTime.Now;
  21:      Console.WriteLine("End:   " + endTime.TimeOfDay);
  22:      Console.WriteLine("Total time: " + endTime.Subtract(startTime));
  23:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Let’s just run it:

image

Hmm.  This little example code took over 7 seconds to run.  Given that I’ve stubbed out all implementations, it should just breeze through.  Here is the code of OrderProcessor, which is the class that is wired up to IOrderProcessor.

   1:  public class OrderProcessor : IOrderProcessor
   2:  {
   3:      private readonly IOrderValidator _validator;
   4:      private readonly IOrderShipper _shipper;
   5:   
   6:      public OrderProcessor(IOrderValidator validator, IOrderShipper shipper)
   7:      {
   8:          _validator = validator;
   9:          _shipper = shipper;
  10:      }
  11:   
  12:      public SuccessResult Process(Order order)
  13:      {
  14:          bool isValid = _validator.Validate(order);
  15:          if (isValid)
  16:          {
  17:              _shipper.Ship(order);
  18:          }
  19:   
  20:          return CreateStatus(isValid);
  21:      }
  22:   
  23:      private SuccessResult CreateStatus(bool isValid)
  24:      {
  25:          return isValid ? SuccessResult.Success : SuccessResult.Failed;
  26:      }
  27:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Ok.  Standard constructor injection.  The anti-pattern is that one of these constructor arguments is really not a class dependency.  The problem is that the constructor of OrderProcessor is too greedy.  It doesn’t need IOrderShipper all the time, but it requires it ALL THE TIME.  In fact, this company finds that 30% of orders are not valid the first time around.  This particular implementation if IOrderShipper is a little bit expensive to create (like ISessionFactory of NHibernate is expensive to create).  Forcing the creating when the false branch of the IF statement would render it useless is the smell.

Just for transparency, here is OrderShipper:

   1:  public class OrderShipper : IOrderShipper
   2:  {
   3:      public OrderShipper()
   4:      {
   5:          Thread.Sleep(TimeSpan.FromMilliseconds(777));
   6:      }
   7:   
   8:      public void Ship(Order order)
   9:      {
  10:          //ship the order
  11:      }
  12:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

If you are truly coupling yourself to an abstraction (the interface), you should now care how the abstraction is implemented.

You might say:  “What?  Just move that long-running work to the Ship()

method!”

I would agree with that if you were designing the OrderShipper class.  That only puts very elusive semantic coupling on all your classes.  What you are really assuming is:  I will code to interfaces. . . AND. . . as long as all of the implementations have constructors that don’t do much work, my whole application should work. 

I am not decrying constructor injection as a useful method.  In fact, we at Headspring do more constructor injection that abstract factory resolution.  However, constructor arguments are API artifacts that shout loudly: “I can do NOTHING unless you pass these things in.”  If that isn’t true, then don’t make the constructor announce a lie.

Cleaning up the smell

We can modify OrderProcessor to use an abstract factory and only require an IOrderShipper if the order is valid.  Here is the new run:

image

Down from 7 seconds to less than 1.  Why?  Because the invalid order did not need to be shipped. 

Here is the new OrderProcessor:

   1:  public class OrderProcessor : IOrderProcessor
   2:  {
   3:      private readonly IOrderValidator _validator;
   4:   
   5:      public OrderProcessor(IOrderValidator validator)
   6:      {
   7:          _validator = validator;
   8:      }
   9:   
  10:      public SuccessResult Process(Order order)
  11:      {
  12:          bool isValid = _validator.Validate(order);
  13:          if (isValid)
  14:          {
  15:              IOrderShipper shipper = new OrderShipperFactory().GetDefault();
  16:              shipper.Ship(order);
  17:          }
  18:   
  19:          return CreateStatus(isValid);
  20:      }
  21:   
  22:      private SuccessResult CreateStatus(bool isValid)
  23:      {
  24:          return isValid ? SuccessResult.Success : SuccessResult.Failed;
  25:      }
  26:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Because we don’t require any implementation of IOrderShipper (line 15) unless the order is valid, our code is simpler.  The class itself has 1 fewer class-level dependency, and only one method has the extra dependency.  We employ a new type, OrderShipperFactory  to keep the Inverted Control where OrderProcessor still doesn’t know the concrete implementation.  There is one more step because factories need start-up configuration.  If you are currently using an IoC container, you are familiar with start-up configuration because you configure the container’s global factory at start-up time.  Here is the code for the factory:

   1:  public class OrderShipperFactory
   2:  {
   3:      public static Func<IOrderShipper> CreationClosure;
   4:      public IOrderShipper GetDefault()
   5:      {
   6:          return CreationClosure();//executes closure
   7:      }
   8:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

And here is the method that configures this factory at start-up time:

   1:  private static void ConfigureFactories()
   2:  {
   3:      OrderShipperFactory.CreationClosure =
   4:          () => ObjectFactory.GetInstance<IOrderShipper>();
   5:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Notice that the IoC container is still in control over creating the concrete implementations, but the abstract factories keep the production code dependencies inverted without being greedy toward optional dependencies.

Counter Argument

Ok, well, then I’ll just create ONE factory like this and use it everywhere:

   1:  public class GenericFactory
   2:  {
   3:      public static Func<object> CreationClosure;
   4:      public T GetDefault<T>()
   5:      {
   6:          return (T) CreationClosure();//executes closure
   7:      }
   8:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

This factory will ONLY work with an IoC container that has the same semantics as the one you are currently using.  For instance, you still need to unit test the code that uses the factory, so you will have to implement a stub for the factory (and unit tests don’t have expensive dependencies like IoC containers).  Bottom line:  this API is hard to implement by coding by hand.  Any API that is hard to implement is a bad API.  You want factories to be explicitly, and a method or class that can create anything????

Hmm.  Isn’t that Activator.CreateInstance()?  But even that is limited because it doesn’t do constructor argument chaining. 

Bottom Line

Architecture and structure are agnostic of tools.  IoC containers are just tools.  Your design should be robust with or WITHOUT them.  Taking away the IoC container should not make the structure of the application crumble.

Why do we use an IoC container, then?  Because of the DRY Principle.  It keeps us from having to write lots of abstract factory implementations that are essentially the same except for one line.  It keeps each class from having a factory call from the no-arg constructor passing in the dependency to the greedy constructor.  IoC containers have limited the need for hand-coded factories, but they have not eliminated the need.

The inspiration for this article came while I was sitting in a workshop where Matt Hinze was teaching a class about Inversion of Control (one of the public workshops that Headspring puts on each month).  I thought about the response to Robert Martin’s recent blog post (which I quite like).  Then a student in the class recalled a project where constructor injection was used everywhere.  They felt the pain that is sure to come from this constructor over-injection anti-pattern.

One final word:  Don’t be in a hurry to agree or disagree with me.  Take the time to ponder.

UPDATE: Good discussion below.  I’ve expanded the code sample in an attempt to make this code smell more obvious (because in reality, we don’t fret over 2 constructor arguments.  We fret about 5, 10, 20).  New post here: http://jeffreypalermo.com/blog/constructor-over-injection-smell-ndash-follow-up/

Headspring MVC Boot Camp review

Jimmy Bogard taught the last installment of Headspring’s ASP.NET MVC Boot Camp training class last week.  Charlie Solomon wrote a thorough review of the class.  It was a very interesting read.  Here is an excerpt:

“Great training, I would highly recommend anything these guys offer. I enjoy a fast pace, hands on (lots of programming exercises) style of training, and that’s what I got. Jimmy is a good teacher… I already knew that, since I’ve been reading his blog for the past year or so and I’ve picked up a lot a good pointers to things that help me in my work. He is also a good communicator teaching in front of a room full of diverse programmers. If you are new to MVC like I am, this course is great for introducing concepts that may be new to web forms programmers… but like the MVC book that Jimmy co-authored, the class goes way beyond the introduction by showing how they leverage some of the features in MVC (ActionFilters and ResultFilters, HtmlTemplates, Model binding and validation…) to build applications quickly that are easier to maintain. We used the release candidate of ASP.Net MVC 2 in class.”

DVCS (Distributed Version Control System): support for agile?

Glenn Block began an interesting thread on the public “altnetseattle” email list on Thursday:

“Hi guys

I know we just finished a nice thread about GIT, whether it’s hot and why.
We also talked about alternatives like Bazzar, Mercurial, etc…

A different question I have is do these tools (regardless of which one you
use) actually support Agile development? Would you consider them an integral
part of the agile shop of the future, or is it just "the way" to do it
regardless. What I am really asking is are there specific benefits for those
doing agile development?

Thanks
Glenn
” – Glenn Block

Now, Glenn is one of those really smart guys.  You can learn more from someone not by listening to what answers he gives; but by what questions he asks.

The thread has some great discussion, but here is my answer that I posted:

“Every VCS supports agile.  Agile is the way the team works with the VCS, not the other way around.  DVCS systems make branch-per-developer seamless.  With Subversion, it is easy to have multiple people working off the trunk, and the merging is great.  Tools like JetBrains TeamCity will do auto-patch-upload and run the private build remotely at any time so you have build-per-developer without waiting for the local machine.

TFS and VersionManager need more work in order to have multiple people making changes to the same files simultaneously, but agile teams still use them.

Also, the VCS features have a lot more to do with supporting a team SIZE, not a team PROCESS or PHILOSOPHY.  A BDUF team of 2 and an agile team of 2 will probably have similar experiences in wide range of VCS’s.  BDUG teams of 10 and agile teams of 10 will have VERY different experiences based on the VCS in place.

I think the essence of the situation is providing the most versioned "levels of undo" possible.  In John Maeda’s The Laws of Simplicity book, he talks about how putting "undo" everywhere makes the experience of using a product seem simpler.  It may not be simpler, but the impression is that it IS simpler.  With Git (the only DVCS I have experience with),:

  1. I can revert a local commit
  2. I can revert a push to my fork
  3. I can revert a pull to the master
  4. I can revert a commit on the master
  5. I can revert a push to the master

With a centralized system, I can only revert a commit to the centralized branch (along with roll-your-own branch commits and merges).

We need only look at some of the large, fast-moving projects hosted with Git to see that is "supports" whatever it is that we are labeling "agile" these days.  http://git-scm.com/

Best regards,
Jeffrey Palermo
”

Charlie Poole, a lead committer on the NUnit open source project, weighed in early and posted something so profound, I just have to share it.

Charlie has so much experience in software that when he speaks, I listen intently.  I have had the please of meeting him at several Alt.Net conferences.  Here is his first post on the thread:

“Hi Glenn,

I consider DVCS to be agile on a philosophical and practical level.

Philosophically, agile is supposed to be *not* so much about tools. DVCSs
remove many of
the restrictions imposed by centralized tools. Most of them work well in
either mode, so a team
can set up it’s own practices and not be limited by what the tool can do.

One proof of this is that some shops forbid DVCSs because they don’t give
enough central
control over developers – a very non-agile viewpoint.

In practical terms, a DVCS allows me to work how and where I want, creating
a feature
branch if I need to, or keeping a common personal branch for small changes.
I can work
quickly on a spike, throwing it all away or merging it in as I like. This is
something I used
to do with multiple workspaces under SVN or CVS, but when I wanted to merge
two
different workspaces without touching the repository, I had to do it
manually.

So I’d say that DVCSs are a win no matter how you develop, but are a
particularly
good fit for agile development.

Charlie”

Charlie has undoubtedly used twice as many Version Control Systems than I have, so when he compares a DVCS to all the others in his past and calls it a “win”, that’s a pretty strong endorsement.

My experience with Git (the only DVCS I’ve used so far) has been positive.  I use it for MvcContrib and for working on the manuscript for ASP.NET MVC 2 in Action.

Subversion seems to be losing favor among version control users

I haven’t done a study, but Subversion is a very popular Version Control System, but it is centralized.  Centralized VCSes have the notion of a “patch” since you can’t share source without submitting it to the central Version Control server.  Decentralized version control systems are proving to scale much better and actually be more usable in the process.  Git and Mercurial are two of the distributed version control systems that seem to be proving themselves among their customer base.  I have experience with Git, and at Headspring, we are considering running a pilot project on it since we have successfully moved one of our sponsored open-source projects onto the system (MvcContrib).

The point of this post isn’t to point to any single product and say “use this product”.  It is merely to recognize what I see as a shift toward distributed version control.  Because every developer has a cloned repository, the only operations that require a network connection are push and pull (this probably differs a bit).  Conceptually, the advantages of distribution of version control is that it is fast, really fast, to show logs, commit, roll back – because you don’t have to wait for the network to do so. 

With the distributed workflow, you perform the following steps:

  1. Clone the remote repository
  2. Modify some of the source
  3. Commit your changes locally
  4. Do some more modifications and commit
  5. Perhaps roll back some of your modifications
  6. More modifications and commit
  7. “Pull” from the remote repository (merge remote changes to your local repository)
  8. Run your private build to ensure the software is stable
  9. “Push” changes to the remote repository (now the rest of the team can get your changes)

You still go through this cycle very quickly, but it adds another level of being able to describe discreet changes.

We’ll see where the industry goes with distributed vs. centralized version control systems. 

MVC 2 in Action book conducting public reviews

If you’d like to get an early glimpse of ASP.NET MVC 2 in Action, you can participate on the public email list at http://groups.google.com/group/mvc2inaction-discuss.  The first bit of the manuscript is ready to review, and it consists of chapter 23, Data Access with NHibernate.  You can also access every bit of code, text, and image at the book’s GitHub repository.  With the first book, ASP.NET MVC in Action, Manning conducted an Early Access Program (MEAP).  Manning will still conduct it, but our program is a early, early access program.  In other words, you can have access to the unedited, perhaps dirty, manuscript and help as it drives forward to polish and completion.

As each piece of the manuscript is complete, we will post it to this list and ask for feedback.  Anyone who gives us constructive feedback on the list WILL be thanked in the acknowledgements section at the front of the book when it goes to print.  Also, you will have influence in shaping this book so that it is as good as it can be.

Our hope is that this book serves the .Net community that is working ASP.NET MVC 1 and ASP.NET MVC 2 applications.

The author team consists of:

If this book project interests you, and if you know people who should be involved, please blog, tweet, and otherwise post a link to this announcement.

Latest release of Cropper works great on Windows 7 x64

Cropper is still alive and well and has a new release on November 27, 2009.  It works great on Windows 7 x64 Ultimate.  I use the built-in Snipping Tool, but Cropper is just more friendly to use because it automatically drops captures into a defined folder.  When writing articles, books, and blog posts, I can grab my shots and pick them up later.  Here is a shot of the MvcContrib GitHub page:

CropperCapture[1]

And Here is a shot of the download section on the CodePlex.com project site:

CropperCapture[2]

AltNetConf email list is back!

Today, December 2009 is roughly 2 years after the AltNetConf list was changed to “cli_dev”, effectively killing the list.  Just look at the graph of activity for this list:

image

The AltNetConf in October of 2007 kicked off a flurry of discussion about ALT.NET.  The discussion was essentially talk about best practices for .Net.  You can see that this list has been completely dormant since April of 2008.

Jeff Atwood’s recent post about OSS parenting got me thinking about this list.  I started it for the AltNetConf and announced it during the conference (which as largely led by Scott Bellware and David Laribee).  I have largely neglected this list and let spam remain.  I went through the work of cleaning the list of lots of spam and banning the spammers.  I’ve also put moderation in place to prevent spammers from joining, and now the list is groomed and ready to resume serving the community.

As with open-source, I expect the community to vote with its feet.  Either this list will bustle with activity again, or this post will be the only mention of it.  Either way, I’ll try to be a good parent, Mr. Atwood.

You can find the AltNetConf list here: http://tech.groups.yahoo.com/group/altnetconf/

What is the purpose of the list now?  The purpose is stated in the group description, and it is as follows:

“This groups serves as a hub of discussion about ALT.NET conferences, user group meetings, meet-ups, and other "conferencing" of people around the topic of ALT.NET.
This list has a colorful history, and if you have time, please read the archives. It started during the original AltNetConf in October of 2007 and now serves as a way to collaborate on future ALT.NET conferences and the like.”

CodeCampServer Call for Participation

I just posted this message to the discussion list.

Right now on http://codecampserver.com/, there are two active user groups
that are hosted with the platform: http://www.adnug.org/, and
http://www.c4mvc.net/.  CodeCampServer is a multi-tenant application, and
the routing handles knowing which user group the data is for.

We need volunteers in two main areas:

   1. Expanding and maintaining CodeCampServer.com
      – Evangelizing CodeCampServer.com
      – Onboarding new .Net user groups
      – Production server monitoring
   2. Creating and driving CcsContrib (CodeCampServer-Contrib).
      – Organizing and moderating this new open-source project
      – Producing builds that can be deployed with CodeCampServer.com
      – Evaluating and accepting patches to this project.

Overall, we have two companies who have pledged ongoing funding for
CodeCampServer:
ORCSWeb <http://www.orcsweb.com/> is maintaining a dedicated server on which
CodeCampServer runs.  They have graciously donated this server so that .Net
user group might have a website hosted for them for free.
Headspring Systems <http://headspring.com> is maintaining the core
multi-tenant application.  Headspring will continually enhance the core as
well as the CcsContrib plugin model, which is MvcContrib’s Portable
Areas<http://www.lostechies.com/blogs/hex/archive/2009/11/01/asp-net-mvc-po…>.
In this way, CcsContrib will contain perhaps many portable areas that add
lots of new functionality on top of the CodeCampServer core.

If you are interested in contributing either as a CcsContrib developer or a
project manager/facilitator, please reply here.  Based on replies and
interest, I will schedule a conference call to discuss the formation of a
CodeCampServer committee.  All the interest in CodeCampServer has been
organic, and I want to somewhat get out of the way so that the community can
get the most out of this project.

Best regards,
Jeffrey Palermo