The Translator/Mapper Pattern

#Patterns

Posted by admin on September 01, 2019

This week while working on a project for work, I came across the need to take data from one object and map this to another similar object, not the same type of object but similar attributes.

I have come across this problem all to many times, where i have had needed to perform this task and then simply, without thinking copy and pasted the mappings between the two objects in multiple locations.. Granted this works.. So 'Life is good' but we could do better... Welcome the Translator Pattern.

So I decided to take my recently gathered knowledge from a course i had just been on and set about creating something that would help me in the long run and maximise code reuse, after all - is that not what we all set out to achieve..??

So I came up with the following interface called ITranslator (remember all - GOF 'Program to interface')

/// Provides a common interface to allow us to translate between two objects.
/// The mapping should be done within the translator.
/// 
/// Object you want to map
/// Object you want to map
public interface ITranslator
{
    /// 
    /// Maps  to 
    /// 
    // The domainObject is he object that you want to map from
    // Returns The object you want to return
    TDomainObjectB Translate(TDomainObjectA domainObject);
    /// 
    /// Maps  to 
    /// 
    ///
<param name="domainObject" />The object that you want to map from
    /// The object you want to return
    TDomainObjectA Translate(TDomainObjectB domainObject);
}

This interface allows you to map between domain object A and domain object B and vice versa. Example below, notice the difference in surname and lastname.. an all too common problem with naming conventions in objects holding personal details.

public class StudentStaffTranslator : ITranslator
{
    #region ITranslator Members
    public StaffMockObject Translate(StudentMockObject domainObject)
    {
        StaffMockObject staff = new StaffMockObject();
        staff.Forename = domainObject.Forename;
        staff.Surname = domainObject.Lastname;
        return staff;
    }
    public StudentMockObject Translate(StaffMockObject domainObject)
    {
        StudentMockObject student = new StudentMockObject();
        student.Forename = domainObject.Forename;
        student.Lastname = domainObject.Surname;
        return student;
    }
    #endregion
}

To implement this Create an instance of your new translator and then just call the interface. - Remember to always call the interface as that is the only way you can insure the signature of the object you are calling.

[TestClass]
public class ITranslatorTests
{
    public void TestOne(StaffMockObject staff)
    {
        ITranslator translator = new StudentStaffTranslator();

        // I really need an instance of the student object to carry on working...
        // A member of staff can be a student.. so i will just translate across..
        // with our funky new translator and let that deal with all my wierd translations.
        StudentMockObject student = translator.Translate(staff);
    }
}

From this it is clear to see the benefits..

You have abstracted the translation code in to its separate classes. Abstraction == GOOD You have followed the Gang of Four by programming to Interface. You have followed good Object orientated programming by implementing interfaces and increasing the reuse of your program.