Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refactoring methods that use the same code but different methods inside

Tags:

c#

asp.net

I have some methods that are the same except one row (i call different methods on the object client). I will have more methods like this.

Is there any solution to this except using Reflection ?

 private void initClerks(Client client)
            {
                string[] pks = client.ClerksPKS.Trim(','). Split(',');

                foreach (string pk in pks)
                {
                    string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();

                    client.addClerk(JsonConvert.DeserializeObject<Clerk[]>(data)[0]);

                }

            }


private void initManagers(Client client)
            {
                string[] pks = client.ManagerPK.Trim(',').Split(',');



                foreach (string pk in pks)
                {
                    string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();
                    client.addManager(JsonConvert.DeserializeObject<Manager[]>(data)[0]);

                }

            }
like image 807
Maxim Toyberman Avatar asked Dec 14 '22 09:12

Maxim Toyberman


2 Answers

You can do this by passing an action into a method. Something like

private void actOnData(Client client, string[] pks, Action<Client, string> addThing)
{
    foreach (string pk in pks)
    {
        string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();
        addThing(client, data);
    }
}

private void initClerks(Client client)
{
    string[] pks = client.ClerksPKS.Trim(',').Split(',');
    actOnData(client,pks,(c,d) => { c.addClerk(JsonConvert.DeserializeObject<Clerk[]>(d)[0]); });
}

private void initManagers(Client client)
{
    string[] pks = client.ManagerPK.Trim(',').Split(',');
    actOnData(client, pks, (c, d) => { c.addManager(JsonConvert.DeserializeObject<Manager[]>(d)[0]); });
}
like image 87
Paul D'Ambra Avatar answered May 06 '23 06:05

Paul D'Ambra


Taking into account this is not external legacy lib I would suggest refactoring Client class as well to simplify its API (I would change more but let's stop at some point)

pseudocode:

// taking into account Client, manager all are workers
class Client
{
    // further whenever you need filter out managers use LINQ OfType<>
    List<Workers> workers;

    public void Add<T>(T worker) where T: Worker
    {
        workers.Add(client);
    }
}

See Extract method approach,

private void Initialize<T>(Client client, string[] pks)
{
    foreach (string pk in pks)
    {
        string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();
        client.Add(JsonConvert.DeserializeObject<T[]>(data)[0]);    
    }
}

private void initClerks(Client client)
{
    string[] pks = client.ClerksPKS.Trim(',').Split(',');
    Initialize<Clerk>(client, pks);
}

private void initManagers(Client client)
{
    string[] pks = client.ManagerPK.Trim(',').Split(',');
    Initialize<Manager>(client, pks);           
}

And going forward thsoe two intiClerks/initmanagers looks redundant, just inline calls to Initialize (surely if entire code base not more complex than you shown here)

like image 35
sll Avatar answered May 06 '23 06:05

sll