Xamarin, Web & Mobile Software Developer/Engineer

Menu

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:

C#

1

2

3

4

5

6

7

8

9

10

classStoreCartManager

publicstaticvoidUpdateProductInCart(intproductNo,intamountTotal)

publicstaticvoidDeleteProductInCart(intproductNo)

publicstaticStoreCart GetCart()

publicstaticvoidCopyCartAcrossToLogin(intloginId)

publicstaticGuid?GetGuidQueryString()

privatestaticint?GetWebLogonIdQueryString()

privatestaticvoidSetWebLogonIdQueryString(intid)

privatestaticStoreCart GetCartByGuid(Guid guid)

privatestaticStoreCart GetCartByClientId(intwebLogonId)

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:

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

classStoreCartProducts

publicvoidUpdateProductInCart(intproductNo,intamountTotal)

publicvoidDeleteProductInCart(intproductNo)

classStoreCartLogonActions

publicvoidCopyCartAcrossToLogin(intloginId)

privatevoidSetWebLogonId(intid)

classStoreCartLocator

publicStoreCart GetCart()

privateStoreCart GetCartByGuid(Guid guid)

privateStoreCart GetCartByClientId(intwebLogonId)

classMembership

privateint?GetWebLogonId()

classStoreCartFactory

/* 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:

C#

1

2

3

4

5

6

7

8

9

classAuthentication

publicoverrideeventEventHandler LoggedIn;

publicvoidLogon(stringuser,stringpassword)

{

if(LoggedIn!=null)

LoggedIn(this,newEventArgs());

}

And subscribe to that event from the LogonActionClass

C#

1

2

3

4

5

classStoreCartLogonActions

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

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.