Click here to Skip to main content
15,885,546 members
Articles / Programming Languages / C# 4.0

Code Simplified!!

Rate me:
Please Sign up or sign in to vote.
3.05/5 (8 votes)
20 Jul 2012CPOL3 min read 25.8K   12   21
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 :-

C#
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:

C#
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

C#
public static MyEntity MapServiceEntityToMyEntity(ServiceEntity response) 

This is how it is called

C#
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 

C#
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.

C#
public static MyEntity Map(this ServiceEntity response)

This way you can achieve:-

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

You can make it even easier

C#
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:-

C#
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

C#
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)

C#
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
I have been working as a developer in SOA and SaaS based projects.
Have worked mainly on Asp.Net, ajax, jQuery,c#, .Net 3.5 and 4.0.
You can reach me on ip_28@yahoo.co.in

Comments and Discussions

 
GeneralMy vote of 1 Pin
Member 432723030-Jul-12 0:55
Member 432723030-Jul-12 0:55 
GeneralRe: My vote of 1 Pin
Indranil Pal3-Sep-12 8:41
Indranil Pal3-Sep-12 8:41 
QuestionNot an article Pin
R. Giskard Reventlov20-Jul-12 7:55
R. Giskard Reventlov20-Jul-12 7:55 
AnswerRe: Not an article Pin
Indranil Pal20-Jul-12 8:47
Indranil Pal20-Jul-12 8:47 
GeneralWhen I clicked on link next to "One good link is". Pin
Kiran Sonawane18-Jul-12 22:29
Kiran Sonawane18-Jul-12 22:29 
GeneralRe: When I clicked on link next to "One good link is". Pin
Indranil Pal19-Jul-12 7:27
Indranil Pal19-Jul-12 7:27 
GeneralMy vote of 3 Pin
Klaus Luedenscheidt18-Jul-12 19:22
Klaus Luedenscheidt18-Jul-12 19:22 
GeneralRe: My vote of 3 Pin
Indranil Pal19-Jul-12 8:02
Indranil Pal19-Jul-12 8:02 
GeneralRe: My vote of 3 Pin
gggustafson20-Jul-12 5:02
mvagggustafson20-Jul-12 5:02 
GeneralRe: My vote of 3 Pin
Indranil Pal20-Jul-12 6:44
Indranil Pal20-Jul-12 6:44 
GeneralRe: My vote of 3 Pin
Klaus Luedenscheidt20-Jul-12 19:08
Klaus Luedenscheidt20-Jul-12 19:08 
SuggestionSuggestions... Pin
Andrew Rissing18-Jul-12 11:11
Andrew Rissing18-Jul-12 11:11 
GeneralRe: Suggestions... Pin
James Hurburgh18-Jul-12 20:57
James Hurburgh18-Jul-12 20:57 
GeneralRe: Suggestions... Pin
Indranil Pal19-Jul-12 8:24
Indranil Pal19-Jul-12 8:24 
I agree with you, the generics types used in select and using select inside List constructor was for beginners to understand.

Also I will avoid using a var (I hope you have just given an example and didn't mean to actually use it Smile | :) )
GeneralRe: Suggestions... Pin
James Hurburgh19-Jul-12 13:10
James Hurburgh19-Jul-12 13:10 
GeneralRe: Suggestions... Pin
Indranil Pal19-Jul-12 21:07
Indranil Pal19-Jul-12 21:07 
GeneralRe: Suggestions... Pin
StockportJambo20-Jul-12 6:34
StockportJambo20-Jul-12 6:34 
GeneralRe: Suggestions... Pin
Indranil Pal20-Jul-12 6:46
Indranil Pal20-Jul-12 6:46 
GeneralRe: Suggestions... Pin
Indranil Pal19-Jul-12 8:12
Indranil Pal19-Jul-12 8:12 
GeneralRe: Suggestions... Pin
Andrew Rissing19-Jul-12 9:53
Andrew Rissing19-Jul-12 9:53 
GeneralRe: Suggestions... Pin
Indranil Pal19-Jul-12 21:08
Indranil Pal19-Jul-12 21:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.