Meal Maker - getters and setters

Okay, I just finished Meal Maker after some real confusion and hours of beating my head against a wall. I still think I’m either missing something, or that the directions have superfluous steps. I was able to get the code to run, but I have three questions.
1)When do we want to use getters and setters exactly? It’s not clear to me yet.
2)We create getters and setters in this example, but I don’t see where they’re used. It seems to me that addDishToCourse(), getRandomDishFromCourse(), and generateRandomMeal() do all the work without ever making a call to the getters and setters we wrote? Am I missing something in the way this code executes, or are we creating unnecessary getters and setters just to confuse me? lol
3)Did I use the proper syntax on my setters? Would it be better to use a unique parameter name, or is it okay to use the same name as what I’m trying to assign to since the parameter only has method level scope?
Here is my code:

const menu = {
    _courses: {
      appetizers:[],
      mains:[],
      desserts:[]
    },
    get appetizers() {
      return this._courses.appetizers;
    },
    get mains() {
      return this._courses.mains;
    },
    get desserts() {
      return this._courses.desserts;
    },
    set appetizers(appetizers) {
      this._courses.appetizers = appetizers;
    },
    set mains(mains) {
      this._courses.mains = mains;
    },
    set desserts(desserts) {
      this._courses.desserts = desserts;
    },
    get courses(){
      return {
        appetizers: this.appetizers,
        mains: this.mains,
        desserts: this.desserts
      };
    },
    addDishToCourse(courseName, dishName, dishPrice) {
      const dish = {
        name: dishName,
        price: dishPrice,
      }
      return this._courses[courseName].push(dish)
    },
    getRandomDishFromCourse(courseName) {
        const dishes = this._courses[courseName];
        const randomIndex = Math.floor(Math.random() * dishes.length);
        return dishes[randomIndex];
    },
    generateRandomMeal() {
        const appetizer = this.getRandomDishFromCourse('appetizers');
        const main = this.getRandomDishFromCourse('mains');
        const dessert = this.getRandomDishFromCourse('desserts');
        const totalPrice = appetizer.price + main.price + dessert.price;
        return `Your meal is ${appetizer.name}, ${main.name}, and ${dessert.name}. The total price is ${totalPrice}.`;

    }


  };

  menu.addDishToCourse("appetizers", "salad", 4.00);
  menu.addDishToCourse("appetizers", "wings", 9.00);
  menu.addDishToCourse("appetizers", "nachos", 7.00);
  menu.addDishToCourse("appetizers", "cheese sticks", 5.00);
  menu.addDishToCourse("appetizers", "fries", 3.00);
  menu.addDishToCourse("mains", "steak", 17.50);
  menu.addDishToCourse("mains", "salmon", 14.50);
  menu.addDishToCourse("mains", "pizza", 12.00);
  menu.addDishToCourse("mains", "meatloaf", 10.50);
  menu.addDishToCourse("mains", "tacos", 9.00);
  menu.addDishToCourse("mains", "enchiladas", 10.50);
  menu.addDishToCourse("desserts", "tiramisu", 11.00);
  menu.addDishToCourse("desserts", "apple crisp", 8.00);
  menu.addDishToCourse("desserts", "molten chocolate cake", 12.50);

  const meal = menu.generateRandomMeal();
  console.log(meal);
1 Like

First my opinion: This project use getters and setters, but i don’t think they add much value, so its more confusing then helpful. So i will mostly focus on explaining getters and setters

getters and setters can be really useful. for example:

myObj = {
  _myArray: [],
  get myArray(){
    return this._myArray.join(' ');
  },
  set myArray(element){
    this._myArray.push(element);
  }
}

myObj.myArray = 3;
myObj.myArray = 4;
myObj.myArray = 5;
console.log(myObj.myArray);

Now the getter and setter have true value/meaning, they (getter and setter) do really change the behavior of the property

While the property (_myArray) is an array, the getter myArray returns a string. This could be useful to display nice output to the user.

the setter also changes the behavior, now assigning a value will push the value into the array (thanks to the setter)

Which is something you can do in mealmaker project:

    set appetizers(appetizer) {
      this._courses.appetizers.push(appetizer);
    },

i would make the parameter name single, given you only assign one dish at a time

which means, you can do assignment:

return this._courses[courseName] = dish

and the setter should handle pushing to array

furthermore, setters can be really useful to do validation.

So this project is showing you getters and setters, but not using them to their full potential

The stupid thing is, that we can still mutate the properties directly, its a shame JS doesn’t block accessing/mutating the property directly when getters and setters are used.

2 Likes

Okay, thank you. That actually helps a little.

2 Likes

I’ve been trying to push “dish” into the array using a setter but it’s not working. Here is my code:

const menu={

  _courses:{

    appetizers:[],

    mains:[],

    desserts:[]

  },

  get appetizers(){

    return this._courses[appetizers];

  },

  set appetizers(appetizerIn){

    this._courses[appetizers].push(appetizerIn);

  },

  get mains(){

    return this._courses[mains];

  },

  set mains(mainIn){

    this._courses[mains].push(mainIn);

  },

  get desserts(){

    return this._courses[desserts];

  },

  set desserts(dessertIn){

    this._courses[desserts].push(dessertIn);

  },

  get courses(){

   return{

     appetizers: this.appetizers,

     mains: this.mains,

     desserts: this.desserts

   };

  },

 

  addDishToCourse(courseName,dishName,dishPrice){

     const dish={

       name: dishName,

       price: dishPrice

     };

     this.appetizers=dish;

     this.mains=dish;

     this.desserts=dish

  },

getRandomDishFromCourse(courseName){

  const dishes=this._courses[courseName];

  const randomIndex=Math.floor(Math.Random()*dishes.length);

  return dishes[randomIndex];

  },

generateRandomMeal(){

  const appetizer= this.getRandomDishFromCourse('appetizers');

  const main= this.getRandomDishFromCourse('mains');

  const dessert= this.getRandomDishFromCourse('desserts');

  const totalPrice= appetizer.price + main.price + dessert.price;

  return `You ordered ${appetizer}, ${main} and ${dessert}, totalling ${totalPrice}`;

  }

}

menu.addDishToCourse('appetizers','Banana',500);

menu.addDishToCourse('appetizers','Orange',50);

menu.addDishToCourse('appetizers','Watermelon',500);

menu.addDishToCourse('mains','Fried rice and chicken',1000);

menu.addDishToCourse('mains','Jollof rice and goat',1200);

menu.addDishToCourse('mains','Egusi soup, poundo and goat',1500);

menu.addDishToCourse('desserts',' Vanilla ice cream',200);

menu.addDishToCourse('desserts',' Milk shake',1000);

menu.addDishToCourse('desserts',' Cup cake',350);

console.log(menu.generateRandomMeal());

i get an error for your setter:

  set appetizers(appetizerIn){
    
    this._courses[appetizers].push(appetizerIn);

  },

appetizers is undefined. Where did you define appetizers?

That’s what I’m confused about. I don’t understand how to implement the setter and getter here. Could you show me how and explain?

The getters and setters don’t add much value I think. You do understand getters and setters in general?

You seem to understand some of implementation, by adding the getters and setters to menu object, we can do:

console.log(menu.appetizers)

even though the actual properties are nested in courses object

as for your error, you can either access the properties using the dot notation:

this._courses.appetizers

if you want to use the associative array notation (with the square brackets) the key should be as string

Yeah I do understand getters and setters in general. Thank you for helping me figure out my mistake. Turns out it was because of the lack of proper call of properties using associative array notation. I had to add the quotes later on specifying it was a string.

Sorry but I have another question totally different from this project. It’s about printing elements in an array with their frequencies. What’s the best way to do that? Please explain :pray:

This question is totally unrelated, you can make a new topic for that

Thank you stetim94, your example is a much clear use of getters and setters.

In the Meal Maker project i get the exact same output with without using the getters and setters. As you said this means they are not very useful here. Without the getters and setters in the code i guess i’m directly accessing and mutating the properties, is this correct ? In this particular project is there any reason why i shouldn’t be doing that ?

My main question is do we actually need the getters and setters for this project ? Or in a real-world scenario you would have coded this without them ?

Thanks

1 Like

i second rabiolas’ question, and particularly confused about the getter courses() - it doesn’t seem to be called at all in the exercise?

1 Like

Actually, doing this:

const menu = {
    _courses: {
      appetizers:[],
      mains:[],
      desserts:[]
    },
    get appetizers() {
      return this._courses.appetizers;
    },
    get mains() {
      return this._courses.mains;
    },
    get desserts() {
      return this._courses.desserts;
    },
    set appetizers(appetizers) {
      this._courses.appetizers = appetizers;
    },
    set mains(mains) {
      this._courses.mains = mains;
    },
    set desserts(desserts) {
      this._courses.desserts = desserts;
    },
    get courses(){
      return {
        appetizers: this.appetizers,
        mains: this.mains,
        desserts: this.desserts
      };
    },
}

isn’t a bad idea. We could now access the appetizer directly through the getter (menu.appetizers) even though the actual property is nested within the _courses object.

we could also do the actual .push() action in the setter. Then we change the default behavior of the property, adding more value of the setter.

JS also has the problem that there is no way to enforce using getters and setters. We can still mutate the property directly.

1 Like

Ok, i see. Still more work then it’s worth i think, and not a good way to teach getters and setters.

For those of you still having trouble understanding getters and setters this video really helped:

1 Like
//Meal Maker Project Using Setters and Getters to Push in Dish Object 

const menu={

  _courses:{

    appetizers:[],

    mains:[],

    desserts:[]

  },

  get appetizers(){

    return this._courses.appetizers;

  },

  set appetizers(appetizerIn){

    this._courses.appetizers.push(appetizerIn);

  },

  get mains(){

    return this._courses.mains;

  },

  set mains(mainIn){

    this._courses.mains.push(mainIn);

  },

  get desserts(){

    return this._courses.desserts;

  },

  set desserts(dessertIn){

    this._courses.desserts.push(dessertIn);

  },

  get courses(){

   return{

     appetizers: this.appetizers,

     mains: this.mains,

     desserts: this.desserts

   };

  },

 

  addDishToCourse(courseName,dishName,dishPrice){

     const dish={

       name: dishName,

       price: dishPrice

     };

     if(courseName==='appetizers'){

     this.appetizers=dish;

      }

      if(courseName==='appetizers'){

     this.mains=dish;

     }

      if(courseName==='appetizers'){

     this.desserts=dish

      }

  },

getRandomDishFromCourse(courseName){

  const dishes=this._courses[courseName];

  const randomIndex=Math.floor(Math.random()*dishes.length);

  return dishes[randomIndex];

  },

generateRandomMeal(){

  const appetizer= this.getRandomDishFromCourse('appetizers');

  const main= this.getRandomDishFromCourse('mains');

  const dessert= this.getRandomDishFromCourse('desserts');

  const totalPrice= appetizer.price + main.price + dessert.price;

  return `You ordered ${appetizer.name}, ${main.name} and ${dessert.name}, totalling ${totalPrice}`;

  }

}

menu.addDishToCourse('appetizers','Banana',500);

menu.addDishToCourse('appetizers','Orange',50);

menu.addDishToCourse('appetizers','Watermelon',500);

menu.addDishToCourse('mains','Fried rice and chicken',1000);

menu.addDishToCourse('mains','Jollof rice and goat',1200);

menu.addDishToCourse('mains','Egusi soup, poundo and goat',1500);

menu.addDishToCourse('desserts',' Vanilla ice cream',200);

menu.addDishToCourse('desserts',' Milk shake',1000);

menu.addDishToCourse('desserts',' Cup cake',350);

console.log(menu.generateRandomMeal());

yes, what about this code?

That’s the code that makes the setter and getter functions a bit useful as I have used the setter functions to push in the dish object to the array values of the respective property of “’_courses”

set appetizers(data) {
this._courses.appetizers = data;

So by doing it this way, is that the right way to access this method?

if (courseName === ‘appetizers’) {
this.appetizers.push(dish);
} else if (courseName === ‘mains’) {
menu.mains.push(dish)
} else if (courseName === ‘desserts’) {
menu.desserts.push(dish)
}

So what in this case algorithm will be? Does that mean we call push method on appetizers setter method? Where’s a parameters for setter in here? Because dish is parameter for push method

in the code you posted, this.appetizers will use the getter, and then simply .push() the value into the array.

setters are used when we do assignment:

someObj.prop = 'new value'

so, if you want to use the setters, use .push() within the setter, and then use assignment.

Now it does make sense, thank you.
I think all of this same names for Setters and getters, and also same properties names make it confusing.
May be would me easier to differ the names a little bit like:

set appetizersSetter(data) {},
get appetizersGetter() {}