software architecture

Software Architecture: Increasing Cohesion and Decreasing Coupling

This is an old blog post that I never posted, I found it while cleaning up some files. It’s not perfect but lessons are still valid for current software architectures.

Increasing Cohesion

Starting with a common class you might find in a standard application:

1
2
3
4
5
6
7
8
9
10
class StoreCartManager
    public static void UpdateProductInCart(int productNo, int amountTotal)
    public static void DeleteProductInCart(int productNo)
    public static StoreCart GetCart()
    public static void CopyCartAcrossToLogin(int loginId)
    public static Guid? GetGuidQueryString()
    private static int? GetWebLogonIdQueryString()
    private static void SetWebLogonIdQueryString(int id)
    private static StoreCart GetCartByGuid(Guid guid)
    private static StoreCart GetCartByClientId(int webLogonId)

NB* StoreCart is a data entity doesn’t contain any business logic

The ‘Manager’ suffix is an instant code smell for low cohesion. Sometimes they start small, but it’s easy for this ‘Manager’ class to grow out of control because you can basically fit most new code under the ‘Manager’ title. An easy way to end up with a big ball of mud.

The Wikipedia definition of cohesion is ‘degree to which the elements of a module belong together’. It’s easy too see that our manager class doesn’t meet the definition of of cohesion.

In order to improve cohesion let’s try to break these down into more specific classes. Here’s a breakdown of the different things we are doing
1) Updating the products in the cart
2) Migrating carts during a login (which is currently tightly coupled to login class)
3) Locating, creating and returning the appropriate the cart

Here’s our improved class model:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class StoreCartProducts
    public void UpdateProductInCart(int productNo, int amountTotal)
    public void DeleteProductInCart(int productNo)
 
class StoreCartLogonActions
    public void CopyCartAcrossToLogin(int loginId)
    private void SetWebLogonId(int id)
 
class StoreCartLocator
    public StoreCart GetCart()    
    private StoreCart GetCartByGuid(Guid guid)
    private StoreCart GetCartByClientId(int webLogonId)
 
class Membership
    private int? GetWebLogonId()
 
class StoreCartFactory
/* to create our new objects */

 

 

Decoupling

The Wikipedia definition of coupling: “In software engineering, coupling or dependency is the degree to which each program module relies on each one of the other modules.”

There’s many ways to decouple software systems, the two I use most commonly are abstraction(c# interfaces) and events. In this post I’m going to show you an example with events.

In this example the CopyCartAcrossToLogin and SetWebLogonId are both called directly from our login class. Essentially this tightly couples the Authentication and the eCommerce functionality. It would be better if they didn’t depend on each other, the authentication system shouldn’t need to know about the eCommerce implementation.

Here’s our improved class model:

1
2
3
4
5
6
7
8
9
class Authentication
 
    public override event EventHandler LoggedIn;
 
    public void Logon(string user, string password)
    {
        if(LoggedIn != null)
            LoggedIn(this, new EventArgs());
    }

And subscribe to that event from the LogonActionClass

1
2
3
4
5
class StoreCartLogonActions
    StoreCartLogonActions(WebClientBase wc)
    {
        m_wc.LoggedIn += m_wc_LoggedIn;
    }

Looks better, but this architecture can still be improved because StoreCartLogonActions is still coupled to the Authentication class. To further improve the coupling you could implement a PubSub engine.

 

Dependency Injection

Now we’ve separated the modules but it’s still a little verbose to have objects passed around everywhere within the code. That’s where dependency injection can come in handy. Now before I can continue you should be aware dependency injection is not the only solution for decoupling, it just makes it alot easier to manage and forces you to think about coupling in your system. A good overview for DI can be found on wikipedia http://en.wikipedia.org/wiki/Dependency_injection

There’s many frameworks for DI but in the case I have used Autofac as it works very well within asp.net

Here’s a technical introduction of using autofac within asp.net
https://code.google.com/p/autofac/wiki/MvcIntegration

After installing Autofac from nuget the web.config is updated and it’s ready to go.
The basic setup:

1) Decouple your code and use interfaces and set any dependencies in either the constructor or on properties.

As an example the StoreCartProducts class had a dependency on StoreCartLocator and StoreCartRepository.

So in the constructor of StoreCartProducts we need to specify the dependencies and Autofac takes care of the dependencies for us.

1
2
3
4
5
6
7
8
private IStoreCartLocator m_locator;
private IStoreCartRepository m_cartRepo;
 
public StoreCartProducts(IStoreCartLocator locator, IStoreCartRepository cartRepo)
{
    m_locator = locator;
    m_cartRepo = cartRepo;
}

2) Create your module classes which specify the dependencies the application requires. A module class allows you to register, basically you register the interface and the implementation class that’s matched to it. Then when Autofac finds a constructor with that type it will take care of injecting the dependency.

Here’s an example:

1
2
3
4
5
6
7
8
9
public class StoreCartModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<StoreCartLogonActions>().As<IStoreCartLogonActions>().InstancePerDependency();
        builder.RegisterType<StoreCartRepository>().As<IStoreCartRepository>().InstancePerDependency();
        builder.RegisterType<StoreCartLocator>().As<IStoreCartLocator>().InstancePerDependency();
    }
}