Home > Blockchain >  How can I avoid repetitive code using reference types?
How can I avoid repetitive code using reference types?

Time:03-10

I've made a method to split address line into separate distinct categories like Region, City, Street and House which are represented by a single class. It follows relatively simple structure.

Address useOther(string Casual, string Other)
    {
        Address
            address = new Address();

        List<string>
            split = new List<string>();
        char[]
            separator = { ',' };
        split.AddRange(
            Casual.Split(
                separator, 
                StringSplitOptions.RemoveEmptyEntries));
        split.AddRange(
            Other.Split(
                separator, 
                StringSplitOptions.RemoveEmptyEntries));

        // Initialize parameters
        split = RemoveBannedTokens(split);

        for (int i = 0; i < split.Count; i  )
        {
            (address.Region, split[i]) = findRegionByName(split[i]);

            if (address.Region != null)
            {
                split[i] = split[i].Replace(address.Region.Name, "");
                break;
            }
        }

        if (address.Region == null)
        {
            address.Region = new Region(region);
        }

        split = ClearSplit(split);

        // Finding region
        for (int i = 0; i < split.Count; i  )
        {
            (address.City, split[i]) = findSityByName(split[i]);

            if (address.City != null)
            {
                split[i] = split[i].Replace(address.City.Name, "");
                break;
            }

        }
        if (address.City == null)
        {
            for (int i = 0; i < split.Count; i  )
            {
                (address.City, split[i]) = findCityByName(split[i], false);

                if (address.City != null)
                {
                    split[i] = split[i].Replace(address.City.Name, "");
                    break;
                }

            }
        }
        if (address.City == null)
            return address;
        split = ClearSplit(split);

        // Finding city
        for (int i = 0; i < split.Count; i  )
        {
            (address.Street, split[i]) = findStreetByName(split[i], address.City);

            if (address.Street != null)
            {
                split[i] = split[i].Replace(address.Street.Name, "");
                break;
            }
        }
        if (address.Street == null && 
            (address.Region.Code.Replace("/", "")   
             address.City.Code.Replace("/", "")).Length != 13)
            return address;
        split = ClearSplit(split);
        //Finding street

        int
            cityIndex = address.City.Index,
            streetIndex = address.Street.Index;

        for (int i = 0; i < split.Count; i  )
        {
            split[i] = split[i].Replace("б/н", "");
        }
        address.House = findNumbers(split.ToArray(), cityIndex, streetIndex);

        return address;
    }
    

If you can see repetition goes like this

for (int i = 0; i < split.Count; i  )
{
    (address.Something, split[i]) = findSomethingByName(split[i]);

    if (address.Something != null)
    {
        //do this thing
        break;
    }

}
if (address.Something == null)
    //try other thing
split = ClearSplit(split);

I want to avoid this repetition and have something of an array or foreach loop but couldn't find a clear way of making an array with reference values or a foreach reference loop that would work with null values properly. I have thought about making a function with specified inputs and outputs but decide it would only harm ability to read my code, which I'm trying to improve here.

CodePudding user response:

Let me try to demonstrate your problem and my proposal.

Assumptions

  1. Your class has several similiar properties, all with value of String.
  2. You have to keep the properties, because they may be required by other frameworks.
  3. You have repeative code to work with the properties.

OldAddress

public class OldAddress
{
    public string City { get; set; }
    public string Region { get; set; }
}

Old Program

public class Program
{

    static OldAddress oldAddress;

    public static string GetFromDataSource(string prop)
    {
        return null;//should return your real value
    }

    public static void AssignValueOldWay()
    {
        if (oldAddress.City != null)
        {
            oldAddress.City = GetFromDataSource("City");
        }
        if (oldAddress.Region != null)
        {
            oldAddress.Region = GetFromDataSource("Region");
        }
        // more...
    }
}

NewAddress

public class NewAddress
{
    public static string[] PropNames = { "City", "Region" };
    public NewAddress()
    {
        props = new Dictionary<string, string>();
        foreach (string prop in PropNames)
        {
            props.Add(prop, "");
        }
    }

    public string City
    {
        get
        {
            return GetProperty("City");
        }
        set
        {
            SetProperty("City", value);
        }
    }
    public string Region
    {
        get
        {
            return GetProperty("Region");
        }
        set
        {
            SetProperty("Region", value);
        }
    }

    private Dictionary<string, string> props;

    public void SetProperty(string prop, string value)
    {
        props[prop] = value;
    }

    public string GetProperty(string prop)
    {
        return props[prop];
    }

}

New Program

public class Program
{

    public static string GetFromDataSource(string prop)
    {
        return null;//should return your real value
    }

    static NewAddress newAddress;

    public static void AssignValueNewWay()
    {
        foreach (string prop in NewAddress.PropNames)
        {
            if (newAddress.GetProperty(prop) != null)
            {
                newAddress.SetProperty(prop, GetFromDataSource(prop));
            }
        }
    }
}

Note my code is just to demonstrate the idea, not optimized for runtime exceptions or bad styles such as public fields, or magic strings.

CodePudding user response:

After some thinking and looking on how I could manage this, I have decided to follow JAlex advise. For now I don't think this change is necessary, so I leave it be for now. What I will do is I would try make this more readable by using additional spaces and comments. As of for now my method looks something like this (after a bit of tweaking here and there) and I'm more or less happy with how readable it is

Address useOther(string Casual, string Other)
{
    Address address = 
        new Address();
    //Initialize address

    List<string> split = 
        new List<string>();
    char[] separator = 
    { 
        ',' 
    };
    //Initialize split and separators

    split.AddRange(Casual.Split(separator));
    split.AddRange(Other .Split(separator));
    RemoveBannedTokens(ref split);
    //Fill split



    for (int i = 0; i < split.Count; i  )
    {
        (address.Region, split[i]) = 
            findRegionByName(split[i]);

        if (address.Region != null)
            break;
    }
    //Trying to find region

    if (address.Region == null)
        address.Region = new Region(region);
    //If Region is not found

    ClearSplit(ref split);
    //Get rid of empty strings



    for (int i = 0; i < split.Count; i  )
    {
        (address.City, split[i]) = 
            findSityByName(split[i]);

        if (address.City != null)
            break;
    }
    //Trying to find city

    if (address.City == null)
    {
        for (int i = 0; i < split.Count; i  )
        {
            (address.City, split[i]) = 
                findSityByName(split[i], false);

            if (address.City != null)
                break;
        }
    }
    //Trying to find city with additional params

    if (address.City == null)
        return address;
    //If City is not found

    ClearSplit(ref split);
    //Get rid of empty strings



    for (int i = 0; i < split.Count; i  )
    {
        (address.Street, split[i]) = 
            findStreetByName(split[i], address.City);

        if (address.Street != null)
            break;
    }
    //Trying to find street

    string code =
        address.Region.Code.Replace("/", "")  
        address.City.Code  .Replace("/", "");
    //Initialize code

    if (address.Street == null && code.Length != 13)
        return address;
    //If Street is not found and address is not complete

    ClearSplit(ref split);
    //Finding street

    address.House = findNumbers(split);
    //Trying to find house

    return address;
}
  • Related