Challenge: Solution Review

This lesson will explain the solution to the problem from the last coding challenge.

We'll cover the following

Solution #

function Assignment() {
this.make = function(builder){
builder.step1();
builder.step2();
builder.step3();
builder.step4();
return builder.get();
}
}
function AssignmentBuilder(subject,level,dueDate) {
this.assignment = null;
this.step1 = function() {
this.assignment= new Task();
};
this.step2 = function() {
this.assignment.addSubject(subject);
};
this.step3 = function(){
this.assignment.addLevel(level);
}
this.step4 = function(){
this.assignment.addDuedate(dueDate);
}
this.get = function() {
return this.assignment;
};
}
function Task() {
this.subject = null;
this.level = null;
this.dueDate = null;
this.addSubject = function(subject) {
this.subject = subject;
};
this.addLevel = function(level) {
this.level = level;
};
this.addDuedate = function(dueDate){
this.dueDate = dueDate;
}
this.announcement = function(){
console.log(`Your ${this.subject} assigment is ${this.level} and due on ${this.dueDate}.`)
}
}
var assignment = new Assignment();
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
var mathAssignment = assignment.make(assignmentBuilder);
mathAssignment.announcement();

Explanation #

You were given the following code:

var assignment = new Assignment();
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
var mathAssignment = assignment.make(assignmentBuilder);
mathAssignment.announcement(); 

You had to complete the code implementation of this program. From the first line, we know that we need to have a class Assignment that accepts no parameters. So let’s declare that first.

function Assignment() {
}
var assignment = new Assignment();
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
var mathAssignment = assignment.make(assignmentBuilder);
mathAssignment.announcement();

The code above code gives an error since some other functions/methods being used are still not defined. So let’s move on to the next line.

var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");

From the following line, we know that there is a class AssignmentBuilder which accepts the subject, the difficulty level, and the date of submission of assignment as parameters. This also means this class has these parameters defined in it, which are set when the corresponding arguments are passed to it.

function Assignment() {
}
function AssignmentBuilder(subject,level,dueDate) {
this.subject = subject;
this.level = level;
this.dueDate = dueDate;
}
var assignment = new Assignment();
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
var mathAssignment = assignment.make(assignmentBuilder);
mathAssignment.announcement();

Now, we get an error that the make function is not defined. Let’s understand what the make function is doing.

make is called on the assignment variable and accepts the assignmentBuilder as a parameter; meaning, it is defined in the Assignment class so let’s define it first.

function Assignment() {
this.make = function(builder){
}
}
function AssignmentBuilder(subject,level,dueDate) {
this.subject = subject;
this.level = level;
this.dueDate = dueDate;
}
var assignment = new Assignment();
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
var mathAssignment = assignment.make(assignmentBuilder);
mathAssignment.announcement();

We defined make and passed a builder parameter to it. In the example above, we are passing assignmentBuilder to it, which contains an object with the three properties: subject, level, and dueDate initialized to corresponding values.

function Assignment() {
this.make = function(builder){
}
}
function AssignmentBuilder(subject,level,dueDate) {
this.subject = subject;
this.level = level;
this.dueDate = dueDate;
}
var assignment = new Assignment();
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
console.log(assignmentBuilder)
//commneting the lines below to avoid error
//var mathAssignment = assignment.make(assignmentBuilder);
//mathAssignment.announcement();

From the variable name mathAssignment we can tell that the make function takes the AssignmentBuilder to create a math assignment specifically. So instead of returning an object AssignmentBuilder should return an assignment which the make will create. Let’s modify our code:

function Assignment() {
this.make = function(builder){
}
}
function AssignmentBuilder(subject,level,dueDate) {
let assignment = null;
this.subject = subject;
this.level = level;
this.dueDate = dueDate;
return assignment;
}
var assignment = new Assignment();
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
var mathAssignment = assignment.make(assignmentBuilder);
mathAssignment.announcement();

assignment should have the subject, level, and dueDate properties in it. For that to happen assignment should be an object containing these properties. How about we divide this task into two steps. Let’s create a Task class that contains these properties. An instance of this class can be stored in assignment. So let’s modify the code accordingly.

function Assignment() {
this.make = function(builder){
}
}
function AssignmentBuilder(subject,level,dueDate) {
let assignment = new Task();
this.subject = subject;
this.level = level;
this.dueDate = dueDate;
return assignment;
}
//creating the Task class with relevant properties
function Task() {
this.subject = null;
this.level = null;
this.dueDate = null;
}
var assignment = new Assignment();
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
var mathAssignment = assignment.make(assignmentBuilder);
mathAssignment.announcement();

Now we need to set the properties for the assignment. So let’s define add functions for these properties in Task.

function Assignment() {
this.make = function(builder){
}
}
function AssignmentBuilder(subject,level,dueDate) {
//step 1
let assignment = new Task();
//step 2
this.assignment.addSubject(subject);
//step3
this.assignment.addLevel(level);
//step 4
this.assignment.addDuedate(dueDate);
return assignment;
}
//creating the Task class with relevant properties
function Task() {
this.subject = null;
this.level = null;
this.dueDate = null;
this.addSubject = function(subject) {
this.subject = subject;
};
this.addLevel = function(level) {
this.level = level;
};
this.addDuedate = function(dueDate){
this.dueDate = dueDate;
}
}
var assignment = new Assignment();
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
var mathAssignment = assignment.make(assignmentBuilder);
mathAssignment.announcement();

When run the code above, you get the following error:

"Cannot read property 'addSubject' of undefined"

Since Task initialized all properties to null you get this error. This is where we can utilize make. Recall make accepts an AssignmentBuilder object and creates a specific assignment. Keeping in mind that we are implementing the builder pattern we can change our code as follows:

function Assignment() {
this.make = function(builder){
//calling the steps for the builder object
builder.step1();
builder.step2();
builder.step3();
builder.step4();
}
}
//converting the steps to functions
function AssignmentBuilder(subject,level,dueDate) {
let assignment = null;
//step 1
this.step1 = function() {
this.assignment= new Task();
};
//step 2
this.step2 = function() {
this.assignment.addSubject(subject);
};
//step 3
this.step3 = function(){
this.assignment.addLevel(level);
}
//step 4
this.step4 = function(){
this.assignment.addDuedate(dueDate);
}
this.get = function(){
return this.assignment;
}
}
//creating the Task class with relevant properties
function Task() {
this.subject = null;
this.level = null;
this.dueDate = null;
this.addSubject = function(subject) {
this.subject = subject;
};
this.addLevel = function(level) {
this.level = level;
};
this.addDuedate = function(dueDate){
this.dueDate = dueDate;
}
}
var assignment = new Assignment();
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
var mathAssignment = assignment.make(assignmentBuilder);
mathAssignment.announcement();

We simply introduced steps in the form of functions in AssignmentBuilder. And then we called these steps in our make function. Next, we need to move the announcement function. From the code, we can see that it’s invoked on mathAssignment variable which is storing the output returned from the make function, i.e., the Task object. Hence, we will move it there.

function Assignment() {
this.make = function(builder){
builder.step1();
builder.step2();
builder.step3();
builder.step4();
return builder.get();
}
}
function AssignmentBuilder(subject,level,dueDate) {
this.assignment = null;
this.step1 = function() {
this.assignment= new Task();
};
this.step2 = function() {
this.assignment.addSubject(subject);
};
this.step3 = function(){
this.assignment.addLevel(level);
}
this.step4 = function(){
this.assignment.addDuedate(dueDate);
}
this.get = function() {
return this.assignment;
};
}
function Task() {
this.subject = null;
this.level = null;
this.dueDate = null;
this.addSubject = function(subject) {
this.subject = subject;
};
this.addLevel = function(level) {
this.level = level;
};
this.addDuedate = function(dueDate){
this.dueDate = dueDate;
}
this.announcement = function(){
console.log(`Your ${this.subject} assigment is ${this.level} and due on ${this.dueDate}.`)
}
}
var assignment = new Assignment();
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
var mathAssignment = assignment.make(assignmentBuilder);
mathAssignment.announcement();

And we’re done!!! The code produces the correct output.

Please note that this is just one of the ways to achieve this output using the builder pattern.


Let’s discuss the prototype pattern in the next lesson.