vendredi 19 août 2022

Design Pattern: How to handle different version of class which has different properties?

My C# app reads json file which changes over time (weekly or monthly) and it has to support all the versions. For example,

Version 1
{firstname:"John", lastname:"Doe"}

Version 2
{firstname:"Tony", lastname:"Doe", address:{line1:"Xavier", line2:"California"}}

Version 3
{firstname:"Adam", lastname:"Wood", address:{line1:"13 House", line2:"Texas", pincode: 12345}}

My C# class which deserialise the json looks like below,

// Version 1
public class DetailsV1: IBase
{
    private string firstname;
    private string lastname;
}

// Version 2
public class DetailsV2: IBase
{
    private string firstname;
    private string lastname;
    private AddressV1 address;
}

// Version 3
public class DetailsV3: IBase
{
    private string firstname;
    private string lastname;
    private AddressV2 address;
}

From my brief search in Google, it says Strategy pattern is a good choice for this kind of problem. So, I created a context class like below,

public class Context
{
    private IBase details;
    private int version;

    public Context(int version, string path)
    {
        this.version = version;
        // TODO The version should be parsed from the file
        if (version == 1)
        {
            this.details = new DetailsV1(path);
        }
        else if (version == 2)
        {
            this.details = new DetailsV2(path);
        }
        else if (version == 3)
        {
            this.details = new DetailsV3(path);
        }
        else
        {
            throw new NotImplementedException();
        }
    }

    // To avoid unnecessary boilerplate, I believe the below functions should return only primitive types
    public int getPinCode()
    {
        if (version == 1)
        {
            throw new NotAvailableInThisVersionException();
        }
        if (version == 2)
        {
            throw new NotAvailableInThisVersionException();
        }
        if (version == 3)
        {
            var address = (this.details as DetailsV1).address;
            var pc = (address as AddressV2).pincode;
            return pc;
        }
        else
        {
            throw new NotImplementedException();
        }
    }
}

Below are my queries,

  • Is this correct design pattern or is there any other better design pattern for my usecase? My versions can grow upto 400+ and thus, my class also grows. I feel this if/else will look ugly (and error prone?).
  • If this is the correct design pattern, Is it correct to cast the address in getPinCode or this has to be handled inside the DetailsV3 class (i.e) DetailsV3 should have a method called getPinCode?
  • If this is the correct design pattern, then I presume these methods should provide only primitive types (or types I am sure going to be static forever). Am I right?

Aucun commentaire:

Enregistrer un commentaire