Refactoring for the glory of Bob!

Bob  has shown us the way and we shall not stray!!!

So in my previous API example, I used Newtonsofts JsonConvert.DeserializeObject(content);


JsonConvert.DeserializeObject<Type>(content);

The problem was that I have more than one API node I wish to pull on meaning that I had to either use anonymous types which would make the code hard to read or create a separate object for both responses:


private class _exerciseResponse
{
public int count { get; set; }
public string next { get; set; }
public string previous { get; set; }
public List<_wgerExercise> results { get; set; }
}
private class _muscleResponse
{
public int count { get; set; }
public string next { get; set; }
public string previous { get; set; }
public List<_wgerMuscle> results { get; set; }
}

It’s kind of sloppy because the response only differs when it comes to the “results” variable, so I decided to after checking that the core of the app works to do a bit of refactoring:


private class reposnse<T>
{
public int count { get; set; }
public string next { get; set; }
public string previous { get; set; }
public List<T> results { get; set; }
}

Logically after I call the JSON deserialize I call it giving it a proper type:


var response = JsonConvert.DeserializeObject<reposnse<_wgerExercise>>(content);

var response = JsonConvert.DeserializeObject<reposnse<_wgerMuscle>>(content);

Good now that leaves this lump of old code:


ExercisesGet()
{
string next;
next = await ParseJSON();
while (next != null)
{
await ParseJSON(next);
}
return _exercises;
}
private async Task<string> ParseJSON(string url= null)
{
if (url == null)
{
url = _URL;
}
var content = await _client.GetStringAsync(_URL);
var response = JsonConvert.DeserializeObject<_response>(content);
var exercises = response.results;
foreach (var exercise in exercises)
{
_exercises.Add(
new ModelExercise
{
Id = exercise.id,
Name = exercise.name,
Description = exercise.description,
}
);
}
return response.next;

}

It’s refactoring time!

First of all lets make the Method ParseJSON() generic:


private async Task<List<T>> ParseJSON<T>(string url = null)
{
_next = null;
if (url == null)
{
url = _ExerciseURL;
}
var content = await _client.GetStringAsync(url);
var response = JsonConvert.DeserializeObject<_response<T>>(content);
var results = response.results;
_next = response.next;

return results;
}

But now instead of returning our final object it retuns a list of our dummy objects so we need to make changes in the ExercisesGet() 


public async override Task<List<ModelExercise>> ExercisesGet()
{

var exercises = await ParseJSON<_wgerExercise>();

while (_next != null)
{
exercises.AddRange(await ParseJSON<_wgerExercise>(_next));
}

foreach (var exercise in exercises)
{
_exercises.Add(
new ModelExercise
{
Id = exercise.id,
Name = exercise.name,
Description = exercise.description,
UserGenerated = false
}
);
}

return _exercises;
}

and to have show of it being worth it ExercisesGet()’s sister MuscleGet()


public async override Task<List<Muscle>> MuscleGet()
{
var content = await _client.GetStringAsync(_MuscleURL);
var muscles = await ParseJSON<_wgerMuscle>();
while (_next!=null)
{
muscles.AddRange(await ParseJSON<_wgerMuscle>(_next));
}
foreach (var muscle in muscles)
{
_muscles.Add(
new Muscle
{
Id = muscle.id,
Name = muscle.name
});
}
return _muscles;
}

The only block that I do not like still where I repeat myself is:


while (_next!=null)
{
muscles.AddRange(await ParseJSON<_wgerMuscle>(_next));
}

And I will figure out how to re-factor this just not now ;).

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s