Builder Pattern – Creating a full set of exercise objects

Three things need to happen in order for me to have a full ModelExercise from the API:

  1. Muscle Groups need to be downloaded
  2. Exercises need to be downloaded
  3. An association table must be built between the two.

Normally I’d use Entity Framework for this sort of thing but with PCL at a time when I started the project, it had quite a lot of problems and SQLite.NET-PCL  was the recommended solution.
That is okay but it means I need to build everything myself so long:


public virtual List<Exercise> Exercises {get; set;}

I need to build this relationship myself, so first of a model class:


 public class MuscleExerciseAssosiation
 {
 public int MuscleId { get; set; }
 public int ModelExerciseId { get; set; }
 public string MuslceType { get; set; }
 }

How I get muscles and exercises you can see in my previous post the association is build:


public override List<MuscleExerciseAssosiation> AssosiationGet()
{
if (_wgerExercises.Count == 0 || _muscles.Count == 0)
{
return new List<MuscleExerciseAssosiation>();
}
foreach (var exercise in _wgerExercises)
{
foreach (var muscle in exercise.muscles)
{
_muscleAssosiations.Add(
new MuscleExerciseAssosiation
{
ModelExerciseId = exercise.id,
MuscleId = muscle,
MuslceType = "Primary"
}
);
}
foreach (var muscle in exercise.muscles_secondary)
{
_muscleAssosiations.Add(
new MuscleExerciseAssosiation
{
ModelExerciseId = exercise.id,
MuscleId = muscle,
MuslceType = "Secondary"
}
);
}
}
return _muscleAssosiations;
}

which I then simply load into the database:


private async Task FillMuscleExerciseAssosiations(AbstractSourceFactory factory)
{
List<MuscleExerciseAssosiation> assosiations = factory.AssosiationGet();
await _connection.InsertAllAsync(assosiations);
}

But it is private… so I cannot call it outside of the class… Thats where the builder pattern comes in, as mentioned at the top of the post all 3 things need to happen in a sequence and they all need to happen, hence a new public method:


public async Task BuildMuscleDatabase(AbstractSourceFactory factory)
{
await FillMusclesFromDataStore(factory);
await FillExercisesFromDataStore(factory);
await FillMuscleExerciseAssosiations(factory);
}

calling all 3 in a sequence with one call from the outside, we are always sure that we called are methods correctly, and with this method being part of the IWorkoutStore interface we opened another ease of work for the future.

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 ;).