Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Code Simplified!!

0.00/5 (No votes)
20 Jul 2012 1  
This article focuses on improving the maintainability of your code thus decreasing the cyclomatic complexity and lines of code, using existing features of .NET.

Introduction

Today, any software implementation is talking to external or internal systems (e.g., SOA), there are lots of entities, lot of code and of course lot of mappings. This article focuses on improving the maintainability of your code thus decreasing the cyclomatic complexity and lines of code, using existing features of .NET.

Background

Few days ago I was implementing a new functionality wherein I found the existing code consumes loads of entities and has huge code for just one to one mapping. I ran the code metrics (from VS 2010) and found the code is not maintainable. If this code is so difficult to read and understand for me as a developer then what about the person who will maintain it later?

This made me to search about few small tweaks to improve the code quality.

Beauty of code

There are many simple ways (which we usually forget or ignore) while coding which can make our code look beautiful and maintainable. 

  1. Inline Initialization

So instead of :-

PersonalInfo entity = new PersonalInfo();
AddressEntity nameAndAddress = new AddressEntity();
nameAndAddress.DayPhone = Convert.ToString(orderEntity.dely_phone_day);
nameAndAddress.EveningPhone = Convert.ToString(orderEntity.dely_phone_eve);
nameAndAddress.AddressLine1 = orderEntity.dely_address1;
nameAndAddress.AddressLine2 = orderEntity.dely_address2;
nameAndAddress.AddressLine3 = orderEntity.dely_address3;
nameAndAddress.AddressLine4 = orderEntity.dely_address4;
nameAndAddress.AddressLine5 = orderEntity.dely_address5;
nameAndAddress.ZipCode = orderEntity.Postcode;
nameAndAddress.FirstName = orderEntity.NickName;
nameAndAddress.Title = orderEntity.dely_address_no.ToString();
entity.Address = nameAndAddress;

We can write:

AddressEntity nameAndAddress = new AddressEntity()
{
    DayPhone = Convert.ToString(orderEntity.dely_phone_day),
    EveningPhone = Convert.ToString(orderEntity.dely_phone_eve),
    AddressLine1 = orderEntity.dely_address1,
    AddressLine2 = orderEntity.dely_address2,
    AddressLine3 = orderEntity.dely_address3,
    AddressLine4 = orderEntity.dely_address4,
    AddressLine5 = orderEntity.dely_address5,
    ZipCode = orderEntity.Postcode,
    FirstName = orderEntity.NickName,
    Title = orderEntity.dely_address_no.ToString()
}; 

 This way you can achieve:-

  • Better readability
  • Better maintainability
  • While calculating code metrics this will be considered as one single line.So, this will reduce the lines of code  (for this example from 13 lines of code to 1)
  • Will prevent duplicate assignment (for entities with large no. of properties this will be very useful) 
  • Faster to code

    2.  Mapping Functions

When we do one to one mapping, what's the first thing we do? We write a method, something like this

public static MyEntity MapServiceEntityToMyEntity(ServiceEntity response) 

This is how it is called

ServiceEntity response = GetServiceResponse(params); 
MyEntity entity = Mapper.MapToMyEntity(response);  

The mapper class gradually grows and grows. 

The problem comes when there are multiple developers working on same piece of code and one of your peers while implementing a new functionality is not able to find this function properly and decides to write his own mapping method. Something like this 

public static  MyEntity MapToMyEntity(ServiceEntity response) 

What happens next? The code complies and the mapping also works. But this increases lines of code, it has duplicate code and most importantly, the person who will maintain this code will pray for your death

What can we do about it? Always remember one simple thing. When you convert a Type "A" to Type "B" then your mapping class/method should always have one and only one function doing this. We can ensure this by creating extension methods. Also we can agree upon a naming convention for it.

I chose to overload all functions in the name of "Map". So my "Mapper.cs" contains all methods named as "Map". Below is one example.

 public static MyEntity Map(this ServiceEntity response)  

This way you can achieve:-

  • Prevent duplication of mapping functions
  • Easy to code
ServiceEntity response = GetServiceResponse(params);
MyEntity entity = response.Map();  

You can make it even easier

MyEntity entity = GetServiceResponse(params).Map();

  • Reduce lines of code 
  3. Mapping Lists [this section requires knowledge of Linq and PLinq] 

When we map a list, I have seen many doing something like:-

List<AddressEntity> listOfAddresses = new List<AddressEntity>();
foreach (ServiceResponse serviceAddress in response)
{
    AddressEntity address = new AddressEntity();
    address.DayPhone = serviceAddress.DayPhone;
    address.EveningPhone = serviceAddress.EveningPhone;
    address.HouseNumber = serviceAddress.HouseNo;
    address.Road = serviceAddress.Road;
    address.City = serviceAddress.City;
    address.Country = serviceAddress.Country;
    address.ZIpCOde = serviceAddress.ZipCode;
    listOfAddresses.Add(address);
}

We can straightaway improve this by using Linq

List<AddressEntity> listOfAddresses = 
  new List<AddressEntity>(response.Select<ServiceResponse,AddressEntity>(serviceAddress =>
                new AddressEntity()
{
    DayPhone = serviceAddress.DayPhone,
    EveningPhone = serviceAddress.EveningPhone,
    HouseNumber = serviceAddress.HouseNo,
    Road = serviceAddress.Road,
    City = serviceAddress.City,
    Country = serviceAddress.Country,
    ZipCOde = serviceAddress.ZipCode
}));

If the internal mapping requires some heavy operations (like calculating total or checking a property) and you are not bothered about the order of the elements in the list. You can further use parallel Linq or PLinq (remember-make sure the operations/variables/methods used under parallel loop are all thread safe)

List<AddressEntity> listOfAddresses = 
  new List<AddressEntity>(response.AsParallel().Select<ServiceResponse,AddressEntity>(serviceAddress =>
new AddressEntity()
{
    DayPhone = serviceAddress.DayPhone,
    EveningPhone = serviceAddress.EveningPhone,
    HouseNumber = serviceAddress.HouseNo,
    Road = serviceAddress.Road,
    City = serviceAddress.City,
    Country = serviceAddress.Country,
    ZipCOde = serviceAddress.ZipCode
}));

More on parallel programming - http://msdn.microsoft.com/en-us/library/ff963553.

When you refactor your code  this way make sure that the performance is intact. Though it is out of scope of this article, but I would suggest do some performance tweaks especially on loops and use the best possible option (for, foreach, Linq,Plinq, Parallel for and foreach) for a particular logic. 

One good link is - http://www.codeproject.com/Articles/6759/FOREACH-Vs-FOR-C  

Another very useful link - http://geekswithblogs.net/BlackRabbitCoder/archive/2010/08/26/c.net-five-little-wonders-that-make-code-better-1-of.aspx

 

 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here