Cost Effective C# IDE

What is the most cost effective way to develop C#?I use VS 2005 with R# when working with clients, but unfortunately that copy of VS 2005 is owned by my employer. The same setup at home would cost $1400+. I know there are free C# IDEs, but they all have flaws that are hard to overlook.What are you using to develop C# outside of your workplace?Looking for ideas.p.s.I wish the ALT.NET guys would start building the Ideal IDE 😉

Advertisements

RoR based MVC Web Frameworks – Friend or Foe?

Ruby on Rails has inspired a whole generation of MVC Web Frameworks. The RoR inspired frameworks follow the same basic design; Controllers whose public methods are web endpoints. So…Do RoR based MVC Web Frameworks encourage good design?

MonoRail and MS MVC are a part of the RoR generation.  

They must. Right? I show, in the code below, that RoR inspired frameworks can actually encourage bad design. I show, in the end, what I think is a better way.

The code presented here is written for MonoRail, but the same problems exist in MS MVC and RoR.  

Let’s start with a simple ProductsController. The index method of this controller is the implementation of http://whocares.com/products/<code&gt;. The code on the end of the URL is the code for a specific product (i.e. nj1287).

public class ProductsController : SmartDispatcherController{   public void Index(string code)   {      Product product = Product.FindByCode(code);      if(product == null)      {         PropertyBag["UnknownSearchTerm"] = code;         RenderView("common/unknown_quick_search");      }      PropertyBag["Product"] = product;      RenderView("display_product");   }}

CategoriesController is our next controller. The index method of this controller is the implementation of http://whocares.com/categories/<name&gt;. The name on the end of the URL is the name for a specific category (i.e. montiors).

public class CategoriesController : SmartDispatcherController{   public void Index(string name)   {      Category cat = Category.FindByName(name);      if(cat == null)      {         PropertyBag["UnknownSearchTerm"] = name;         RenderView("common/unknown_quick_search");      }      PropertyBag["Category"] = cat;      RenderView("display_category");   }}

The index method in both classes are basically the same. We can remove the duplication. Let’s extract an abstract class.

public abstract class SearchableController : SmartDispatcherController{   public void Index(string name)   {      ISearchable item = FindByName(name);      if(item == null)      {         PropertyBag["UnknownSearchTerm"] = name;         RenderView("common/unknown_quick_search");      }      PropertyBag["Item"] = item;      RenderView(IndexView);   }   protected abstract ISearchable FindByName(string name);   protected abstract string IndexView { get; }}public class ProductsController : SearchableController{   protected ISearchable FindByName(string name)   {      return Product.FindByCode(name);   }   protected string IndexView { get { return "display_product"; } }}public class CategoriesController : SearchableController{   protected ISearchable FindByName(string name)   {      return Category.FindByName(name);   }   protected string IndexView { get { return "display_category"; } }}

What do you think about our new DRY code?I don’t like it. Why?

  1. ProductsController and CategoriesController no longer “speak” to me.
  2. Inheritance. I really don’t like the template method pattern because of #1.

Can we fix this?We can use a DynamicAction in MonoRail. Let’s see that code.

Does RoR or MS MVC have a concept of a “DynamicAction”?  

public class IndexAction : IDynamicAction{   private ISearchableRepository repos;   private string indexView;   public IndexAction(      ISearchableRepository repos,      string indexView)   {      this.repos = repos;      this.indexView = indexView;   }   public void Execute(Controller controller)   {      string name = controller.Params["name"];      ISearchable item = repos.FindByName(name);      if(item == null)      {         controller.PropertyBag["UnknownSearchTerm"] = name;         controller.RenderView("common/unknown_quick_search");      }      controller.PropertyBag["Item"] = item;      controller.RenderView(indexView);   }}public class ProductsController : SmartDispatcherController{   public ProductsController()   {      DynamicActions["Index"] = new IndexAction(             new ProductsRepository(), "display_product");   }} public class CategoriesController : SmartDispatcherController{   public CategoriesController()   {      DynamicActions["Index"] = new IndexAction(             new CategoryRepository(), "display_category");   }}

I like this code better. We are no longer using inheritance to reuse code and the code “speaks” better to me. This code has two things that bug me.

  1. The controllers are really not doing much.
  2. DynamicActions are second class citizens in MonoRail.

How do we fix these issues? I don’t know how in the RoR inspired frameworks. I think we need another abstraction. Chris Ortman and I discussed the below code at HDC 07 (so he deserves at least part of the credit). I am not sure he agreed, but maybe this post will change his mind.

The code below is not apart of any framework. It is only an idea.  

public class IndexAction : SmartDispatcherAction{   private ISearchableRepository repos;   private string indexView;   public IndexAction(      ISearchableRepository repos,      string indexView)   {      this.repos = repos;      this.indexView = indexView;   }   public void Execute(string name)   {      ISearchable item = repos.FindByName(name);      if(item == null)      {         PropertyBag["UnknownSearchTerm"] = name;         RenderView("common/unknown_quick_search");      }      PropertyBag["Item"] = item;      RenderView(indexView);   }}

IndexAction is now a first class citizen of the framework. Actions have all the benefits that controllers have in MonoRail (parameter binding, …).How do we hook this action to a URL?

new Route("/products/<name>",    new IndexAction(new ProductRepository(), "display_product"));new Route("/categories/<name>",    new IndexAction(new CategoryRepository(), "display_category"));

Routing engines allow us to remove the “controller” completely. We don’t need a “controller” (at least not in the RoR framework form). What were our controllers doing? They were really just organizing our actions. Routing engines allow us to organize our actions without the “controller”.What do you think? I would really like some feedback on this topic. Does anyone else feel this pain with these frameworks?

Rumbster has Graduated to RubyForge

Thanks to Pat Courtney, Rumbster – The Fake Email Server has graduated to RubyForge!Rumbster is a fake email server, written in Ruby. Rumbster was designed to test web based email functionality with Watir. Rumbster facilitates email testing by publishing received emails to registered observers. Rumbster currently ships with two observers; FileMessageObserver and MailMessageObserver.FileMessageObserver dumps received email messages to a file in a defined message directory. The files are named "#{@system_time.current_time_in_seconds}_#{mail.to}.txt".MailMessageObserver appends all received email messages to a message list.

message_observer = MailMessageObserver.newserver = Rumbster.newserver.add_observer(message_observer)server.add_observer(FileMessageObserver.new('message_dir'))server.start# assert message_observer.messages has your email messagesserver.stop

How do I get Rumbster?gem install rumbstersvn co http://rumbster.rubyforge.org/svn/trunkHow do I learn more about Rumbster?Read the tests. Rumbster was written test first, so the tests should tell a good story. If you would like to contribute documentation, we would be happy to have it 😉

MS MVC – A MonoRail Perspective

Scott Guthrie gave us our first look at the the new Microsoft MVC framework at ALT.NET. I took special care, while watching the video, to answer one question.What, if anything, can MonoRail learn from MS MVC?

  1. Routing – RoR and MS MVC treat Routing as a first class citizen. Routing in MonoRail is an after thought and it shows.Why is first class Routing a big deal?
    • DRY – Tight integration between the routing engine and URL generation allows URLs to refactored easily and safely.
    • Testing – Testing routes, in MonoRail, requires an end-to-end test. If routes were first class objects, then routes could be tested in isolation.
  2. Typed PropertyBag – Typed PropertyBag is not the default behavior in MS MVC, but it is supported.Why is a Typed PropertyBag important?Contract – A Typed PropertyBag communicates the contract between the controller and view. Without this contract, refactoring anything in the view or the controller is difficult and error prone. We enforced a contract by implementing Advocates, but it would be nice if it were supported by MonoRail.

What are your thoughts?

No Dots

On my last project, James and I started the slogan “No Dots”. “No Dots” reminds us that templates/views are “documents with holes” and should contain a very minimum amount of logic.

I amended the slogan to be: “Zero or One Dot”. You will see why shortly. The amended version was an artifact of using NVelocity. 

The example below is the reason behind the slogan.

Note: This example is in NVelocity, but it really applies to any template engine. 

#if(person.Age > 10)<div class="discount">Team</div>#end#if(person.Age > 20)<div class="discount">Network</div>#end#if(person.Age > 30)<div class="discount">World</div>#end

Is this code bad? Not really. The logic in the view is minimal.I say this view might be acceptable in a small project. The problem occurs when a project gets large. Why? Testing any logic in the view is hard and therefore does not get tested throughly. This under-tested logic is a breading ground for new bugs.James and I created a solution to this problem that James coined as the Advocate pattern.

Does this “pattern” have another name? 

What is an Advocate?The advocate is a “plain old object”, living outside the view, that answers questions about a model or models for a specific view.Enough with the definition, we want to see the code.PersonAdvocate

public class PersonAdvocate{    private Person person;    public PersonAdvocate(Person person)    {        this.person = person;    }    public void IList<Discount> Discounts    {        get        {            IList<Discount> discounts = new List<Discount>();            if(person.Age > 10) discounts.Add(new Discount("Team"));            if(person.Age > 20) discounts.Add(new Discount("Network));            if(person.Age > 30) discounts.Add(new Discount("World"));        }    }}

NVelocity Template

#foreach($Discount in $PersonAdvocate.Discounts)<div class="discount">$Discount.Name</div>#end

The above template code is an example of “One Dot”. Allowing “One Dot” means that only one object needs to be put into the template’s context. Sticking to “No Dots’ would force one object in the context per hole in the template. I am willing to allow “One Dot”, but no more.

The new version of the template is less complicated and more resistant to change. The decisions about what discounts to display are encapsulated in PersonAdvocate. Moving the logic from the template to the advocate made it easier to test and refactor. Advocates allowed us to fix buggy view logic that finally stayed fixed.

MonoRail: Dynamic Actions; The better way to implement actions?

We are finishing up our eight month development effort on sothebyshomes.com. Knowing what we do now, “What would we do different?”.I think most of my team would say; Dynamic Actions. What are Dynamic Actions?

Dynamic Actions are a way to associate code with a name in runtime.

What exactly does that mean? An example might help explain.

public ListingController(){    DynamicActions["ImageSlideShow"] =        new ImageSlideShowAction(new ListingContext());    DynamicActions["FullSizeImageSlideShow"] =        new FullSizeImageSlideShowAction(repository);}

After these actions are added, listing/imageslideshow.rails and listing/fullsizeimageslideshow.rails are mapped to the actions defined in ImageSlideShowAction and FullSizeImageSlideShowAction respectively.How does one implement a Dynamic Action?

public class FullSizeImageSlideShowAction : IDynamicAction{    public void Execute(Controller controller)    {        string identifier = controller.Params["identifier"];        Listing listing = FindByListingNumber(identifier);        controller.PropertyBag["Listing"] = listing;        controller.RenderSharedView("fullsizeimageslideshow");    }}

Why would we want to use Dynamic Actions? I will let Hammett answer this question.

DynamicActions offers a way to have an action that is not a method in the controller. This way you can “reuse an action” in several controllers, even among projects, without the need to create a complex controller class hierarchy.

The most important part of Hammett’s answer is “reuse an action … without the need to create a complex controller class hierarchy”. In the beginning or our project, we use inheritance to “reuse actions”. This turned out to be a bad decision, for all the obvious reasons. At the time, we overlooked Dynamic Actions; I think partially because the Dynamic Action documentation was buried in the advanced section of the MonoRail documentation.Our code has two main use cases that are shared among eight different domain models. We currently use one base controller to implement the use cases with hooks to allow the subclasses to customize its behavior. This has made (as you can imagine) unclear and hard to maintain code. I would never again use inheritance as a way to share actions across controllers.Has anyone else overlooked Dynamic Actions?Any advice on implementing Dynamic Actions? Any pitfalls?

Gotcha – Sending Emails with MonoRail

Update: James did not think my original post was very clear (and I agreed). I hope that this new version is easier to read and understand.

We use the technique described in MonoRail: Sending Emails to send emails from our controllers. Our emails, in some cases, have many recipients in the to, cc and bcc. The lists are formatted like the following in our datastore:

mail1@mydomain.com,mail2@mydomain.com,mail3@mydomain.com

MonoRail requires that email addresses be separated by semicolons when sending emails as described by MonoRail: Sending Emails (The RFC 2822 says email addresses should be separated by a comma). Given this requirement, we then turned our lists into the following:

mail1@mydomain.com;mail2@mydomain.com;mail3@mydomain.com

The emails were sent correctly while using MonoRail RC2.After our first release of sothebyshomes.com, we upgraded MonoRail to the latest good build on the trunk. After upgrading, sending emails would fail with the following exception message.

The specified string in not in the form required for an email address.

I found the following note on the bottom of the MailMessage Constructor documentation.

NOTE: You cannot use the semi-colon for the delimiter. You must use the commaor the constructor will throw a System.Format exception. You will see thefollowing message: " The specified string in not in the form required for an email address. "

The upgraded version of MonoRail uses the new .NET 2.0 way of sending emails (RC2 did not). System.Net.Mail is more strict than the old .NET 1.1 way. This error took me an hour or so to track down, so hopefully this post will save you some time.