Saturday, May 7, 2016

Using namespaces to promote code reuse

A well defined namespace hierarchy promotes code reuse by exposing existing types through an IDE's Intellisense, without developers needing to know which namespaces to include or which types exist in which namespaces.

Software developers make use of namespaces when referencing code from others as well as when organizing their own code. Visual Studio defaults to a root namespace that is the same as the project name, and classes within sub-folders in the project receive a default namespace of ProjectName.FolderName.
using System;
using System.IO;

namespace ProjectName.FolderName
{
  public class Person
  {
    public int Id { get; set; }
  }
}
This is a perfectly logical approach, but can lead to disorganized namespaces within a solution if no thought is given to the resulting namespace hierarchy at the time the projects are created. Consider a product called RetailMe that provides inventory and accounting functionality for a retail business. The solution and project structure might look similar to this:

RetailMe.sln
  - Accounting.csproj
       - Vendor.cs
  - Common.csproj
       - IProduct.cs
  - Inventory.csproj
       - Bicycle.cs

The classes and interfaces will be defined in their project namespace and probably define using statements to more easily reference types in other namespaces.
namespace Common
{
  public interface IProduct
  {
    string Name { get; set; };
  }
}
using Common;
using Accounting;

namespace Inventory
{
  public class Bicycle : IProduct
  {
    public void Sell()
    {
      if (Bicycle.NumberInStock < 5)
      {
         Vendor v = Vendor.For(this);
         Vendor.Order(5);
      }
    }
  }
}
using Common;
using Inventory;

namespace Accounting
{
  public class Vendor
  {
    public void Order(int numberOfItems)
    {
       //call vendor service to order more
    }

    public static Vendor For(IProduct item)
    {
      //return something
    }
  }
}    
There is nothing incorrect with the solution/project structure shown above; however, changing the namespaces to a hierarchical structure can promote better code reuse among the projects in the solution. In the examples above, using statements for Common, Inventory, and Accounting are defined at the top of each class, which means the developer needed to know that IProduct is defined in the Common namespace.

Using a hierarchical namespace allows the shared or common items to be more easily exposed to developers. A common way of doing this is to start all the namespaces with CompanyName.ProductName. If we change the namespaces from the above example, the new namespace structure might look something like this:
namespace Acme.RetailMe
{
  public interface IProduct
  {
    string Name { get; set; };
  }
}
using Acme.RetailMe.Accounting;

namespace Acme.RetailMe.Inventory
{
  public class Bicycle : IProduct
  {
    public void Sell()
    {
      if (Bicycle.NumberInStock < 5)
      {
         Vendor v = Vendor.For(this);
         Vendor.Order(5);
      }
    }
  }
}
namespace Acme.RetailMe.Accounting
{
  public class Vendor
  {
    public void Order(int numberOfItems)
    {
       //call vendor service to order more
    }

    public static Vendor For(IProduct item)
    {
      //return something
    }
  }
}      
Defining the namespaces in this way eliminates the need to define a using statement for a "Common" project and the Acme.RetailMe.IProduct interface will automatically show up in Intellisense while developers are making changes in the Acme.RetailMe.Inventory and Acme.RetailMe.Accounting namespaces.

This becomes more important as the code base and number of developers grows because it becomes more difficult for developers to know about all of the existing types that can be reused. If the reusable types continually show up in Intellisense while the developers are working on other changes, they are more likely to know about them and use them in the future.

No comments:

Post a Comment