Meal Maker - Using getters & setters

I was stuck on this a bit and while looking through the forums I noticed most of the posts are solutions without the use of the getters/setters or are wondering why the getter/setters are needed.

So here is my attempt at using the getters/setters for this project.

From what I gather is that using getters/setters is kind of like an added layer of security… to check that the data we’re setting is in the correct format/data type and the data we’re pulling exists or is not empty? If there are errors, we can throw that to the user so they know what’s going on? or is there more to it?

I guess i could’ve added a check to make sure that whatever the user adds is of type ‘string’ and is either a ‘meal’, ‘appetizer’, or ‘dessert’?

const menu = {
  _courses: {
    appetizers: [],
    mains: [],
    desserts: [],
  },

  get courses() {
    return {
      appetizers: this.appetizers,
      mains: this.mains,
      desserts: this.desserts,
    }
  },
  
  get appetizers() {
    if (this._courses.appetizers.length !== 0) {
      return this._courses.appetizers;
    } else {
      return 'There are no appetizers';
    }    
  },

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

  get mains() {
    if (this._courses.mains.length !== 0 ) {
      return this._courses.mains;
    } else {
      return 'There are no mains';
    }    
  },

  set mains(mainIn) {
    this._courses.mains.push(mainIn);
  },

  get desserts() {
    if (this._courses.desserts.length !== 0) {
      return this._courses.desserts;
    } else {
      return 'There are no desserts';
    }
  },

  set desserts(dessertsIn) {
    this._courses.desserts.push(dessertsIn);
  },

  addDishToCourse(courseName, dishName, dishPrice) {
    const dish = {
      name: dishName,
      price: dishPrice,
    };

    this[courseName] = 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}, ${dessert.name}. The price is $${totalPrice}.`;
  }
}

console.log(menu.courses)
/*
LOGS 

{
  appetizers: 'There are no appetizers',
  mains: 'There are no mains',
  desserts: 'There are no desserts' 
}
*/

menu.addDishToCourse('appetizers', 'calamari', 8);
menu.addDishToCourse('appetizers', 'fries', 5);
menu.addDishToCourse('appetizers', 'chips', 5);

menu.addDishToCourse('mains', 'fish & chips', 15);
menu.addDishToCourse('mains', 'cheese burger', 10);
menu.addDishToCourse('mains', 'double cheese burger', 13);

menu.addDishToCourse('desserts', 'chocolate lava cake', 8);
menu.addDishToCourse('desserts', 'tiramisu', 8);
menu.addDishToCourse('desserts', 'ice cream', 4);

console.log(menu.courses)
/* 
LOGS 

{ 
  appetizers: 
   [ { name: 'calamari', price: 8 },
     { name: 'fries', price: 5 },
     { name: 'chips', price: 5 } ],
  mains: 
   [ { name: 'fish & chips', price: 15 },
     { name: 'cheese burger', price: 10 },
     { name: 'double cheese burger', price: 13 } ],
  desserts: 
   [ { name: 'chocolate lava cake', price: 8 },
     { name: 'tiramisu', price: 8 },
     { name: 'ice cream', price: 5 } ] 
}
*/

let meal = menu.generateRandomMeal();

console.log(meal);
/*
LOGS

Your meal is calamari, fish & chips, tiramisu. The price is $31.
 */

so…when the desserts array is empty, there are 21 desserts?

console.log(menu.desserts.length)

assignment and appending are pretty different things, maybe what you meant is to have a method for adding a main course?


this would prevent modification to the _courses object, but not to the arrays


without a strategy for error handling, being able to detect errors doesn’t help much. you could crash, this would be an improvement over silently failing because at least then it is something that can be discovered

in general I suggest staying away from getters and setters unless it solves a problem that you can point at and explain

tutorials love including them, typically with an example where they don’t help out. it’s the same thing with classes and switches, and if you try to google any of these things you’ll find a whole lot of vague and/or circular arguments and become no wiser.

https://en.wikipedia.org/wiki/Cargo_cult_programming

1 Like

Hey thanks!

so…when the desserts array is empty, there are 21 desserts?

Not sure what you mean here? There are 21 desserts? I’m checking if the desserts array is empty. If it’s not empty, then get the dishes in the desserts array. If it is empty, then let the user know that there are no desserts.

assignment and appending are pretty different things, maybe what you meant is to have a method for adding a main course?

I’m using a set method to push a dish into the mains array. The set method is called in the addDishtoCourse method.

When missing you return something that has a length of 21. How is the caller supposed to know that you suddenly returned a string instead?

If you do assignment, then appending is wrong. That’s not what assignment means.
If you for example do this:

menu.desserts = menu.desserts

then what happens? as far as assignment goes, this is reasonable.
this matches what is done:

menu.addDessert('cake')

When missing you return something that has a length of 21. How is the caller supposed to know that you suddenly returned a string instead?

Oh I see what you’re saying. The length of 21 is from the string that’s returned when the desserts array is empty. I guess I didn’t think that the way you (the caller) would check if there were any desserts or not was by checking the length of the array.

console.log(menu.desserts);

my assumption was that you would check by logging the get desserts method and the caller would see the returned string ^^^ which I thought provided more context.

  get desserts() {  
      return this._courses.desserts;  
  }

So should I have just done it like that ^^ then? Then it would’ve returned 0 if you checked the length of the array.

If you do assignment, then appending is wrong. That’s not what assignment means.

So what is the correct way?

Cause I was basically following this example from the MDN docs below.

const language = {
  set current(name) {
    this.log.push(name);
  },
  log: []
}

language.current = 'EN';
console.log(language.log); // ['EN']

language.current = 'FA';
console.log(language.log); // ['EN', 'FA']

The intention of that example is likely more about demonstrating a setter than it is about what a setter is good for.

If your object should have some behaviour for adding a course, then you’d make a method for that, something like addDessert

It technically doesn’t matter. But it’s saying the wrong thing. You could similarly make your object iterable, and this would have the effect of printing a string representation of your object, and result in 0 iterations.

// print out the menu:
for (let whatever of menu);

You can do this. But it’s saying the wrong thing.

const menu = {
  [Symbol.iterator]: function * () {
    console.log('hello yes this is the menu.')
  }
}

for (const _ of menu) {
  console.log("uhm. I'm iterating through the menu... I think?")
}

I found it very confusing as well.
Why add setters and getters if they are absolutely pointless in this example. This does not help to absorb the material and makes more harm than good.
Please fix.