Functional Programming – Javascript Exercise

Learning Goals

  • Software design approaches and patterns, to identify reusable solutions to commonly occurring problems
  • Apply an appropriate software development approach according to the relevant paradigm (for example object oriented, event driven or procedural)

Programs Used

Apples

Create a new Javascript project, and add the following code to main.js

function pickApples(amount) {
  let colourIndex = 1;
  let poisonIndex = 7;
  let priceInPenceIndex = 4;

  const output = [];
  for (let i = 0; i < amount; i++) {
    output.push(new Apple(getColour(colourIndex), poisonIndex % 41 === 0, priceInPenceIndex % 51 + 1))
    colourIndex += 5;
    poisonIndex += 37;
    priceInPenceIndex += 23;

  }
  return output
}

function getColour(colourIndex) {
  if (colourIndex % 13 === 0 || colourIndex % 29 === 0) {
    return "Green";
  }

  if (colourIndex % 11 === 0 || colourIndex % 19 === 0) {
    return "Yellow";
  }

  return "Red";
}

class Apple {
  constructor(colour, poisoned, priceInPence) {
    this.colour = colour;
    this.poisoned = poisoned;
    this.priceInPence = priceInPence;
  }

  toString() {
    return `${this.colour} apple priceInPence ${this.priceInPence}p${this.poisoned ? " (poisoned!)" : ""}`;
  }
}

const apples = pickApples(10000);

Exercises

The above code generates a specified number of apples with different prices. Some of them have been poisoned. It is intentionally rather obtuse. Use both an anonymous function and an arrow function to answer the following questions about the first 10,000 apples:

  1. How many apples are poisoned?
  2. How many yellow apples are poisoned?
  3. If you pick a green apple, how many times will the next apple also be green?
  4. How much do all the green apples cost?
  5. What is the index of the last occurring red poisoned apple that costs 32 pence?

Revisit the above questions, and look to see how this code can be made reusable by replacing the inline anonymous/arrow functions with named functions.

A “Functional” Gilded Rose

There is an established refactoring exercise called The Gilded Rose. We have made a slightly custom version of the exercise for you to complete. The original version is here.

Firstly, fork and clone the starter repo here to your machine and follow the instructions in the README. Your task is to follow a functional approach for rewriting the code. The requirements for the Gilded Rose can be found in your repo in the file gilded_rose_requirements.md.

The repository includes a “golden master” test, which is a simple snapshot test to check that your refactor hasn’t broken anything. It also includes a simple example test that can be used as a pattern if you want to implement more targeted unit tests. The initial version of the example test has been written to fail, so you will need to fix that.

You can run the tests with npm test.

Things you might want to consider improving:

  • The structure of the Gilded Rose class is very OOP currently, how could we convert that to be fundamentally more functional?
    • E.g. could we convert the update_quality function to be a “pure” function?
    • This may require changing the tests to follow the new pattern
  • Could we split up the handling of the quality & sell_in properties to be separate?
  • Could we reduce (or even eliminate!) any “assignment” operations (x = y) where state is being handled?
  • Could we ensure that any remaining assignments only ever assign to const values?
  • Could we split the logic to be more readable?