Refactoring for code duplicates sector

From Martin Fowler

Image we got below similar classes for data model:

public class ClassA
{
public string Name1 { get; set; } = string.Empty;
public string Name2 { get; set; } = string.Empty;
public string A1 { get; set; } = string.Empty;
}
public class ClassB
{
public string Name1 { get; set; } = string.Empty;
public string Name2 { get; set; } = string.Empty;
public string B1 { get; set; } = string.Empty;
}

Suppose we having some specific server to process business logic and insert to database under similar data flow as below:

public class XxxService
{
// injection data access with database relative info
DataAccess _dataAccess;
public XxxService(DataAccess dataAccess){// ...} public void ProcessX(class ClassA)
{
// do pre-processing before insert to database
// ...

_dataAccess.InsertToDB1(ClassA);

// do post-processing after insert to database
// ...
}

public void ProcessY(class ClassB)
{
// do pre-processing before insert to database
// ...

_dataAccess.InsertToDB2(ClassB);

// do post-processing after insert to database
// ...
}}

The above structure would be common approach to deal the different case(s) of diverse logic we used to.

You might observe that the method Process{_} having the similar data structure <Pre-processing> , [Insert] then <Post-processing>. We could get lots of duplicated code sections if <Pre-processing> and <Post-processing> are exactly same logic.

So we came out the new method that combined two ProcessX & ProcessY together, ProcessXY:

public class XxxService
{
// inject data access with database relative info
DataAccess _dataAccess;
// inject class repository
ClassRepo _repo;

public XxxService(DataAccess dataAccess, ClassRepo repo){// ...}
public void ProcessXY<T>(Action<T> insertDBAction)
{
// do pre-processing before insert to database
// ...

dynamic castModel = typeof(T).Name switch
{
nameof(ClassA) => _repo.GetClassA(...),
nameof(ClassB) => _repo.GetClassB(...),
_ => throw new Exception("InvalidType.")
};
insertDBAction(castModel);

// do post-processing after insert to database
// ...
}
}

Therefore, we could invoke the same flow as below:

PorcessXY<ClassA>(_dataAcess.InsertToDB1) or PorcessXY<ClassB>(_dataAcess.InsertToDB2)👊. More clean and more maintainable code comparing to previous.

Reference

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store