Skip to content

KatieLisabeth/behavior-strategy-implementation

Β 
Β 

Repository files navigation

Behavior, Strategy, Implementation

Be creative while inventing ideas, but be disciplined while implementing them.

In this module you will explore different ways to break down and solve coding challenges. Along with structured workflows for approaching challenges, you will learn the JavaScript you need to write clear and maintainable solutions including: reading and writing tests, higher order functions, arrays and object.

Behavior

What does the function do? What are it’s arguments and it’s return value? How could you use it in a program? Behavior is all about what your function looks like "from the outside", without caring about what is written inside.

Functions behavior is generally described using documentation, unit tests and use cases:

Documentation (JSDoc comment)
/**
 * repeats a string a specific number of times
 * @param {string} [text=''] - the string to repeat. defaults to empty string
 * @param {number} [repetitions=1] - how many times to repeat. defaults to 1
 *  repetitions cannot be negative, and must be an integer
 * @return {string} the text repeated as many times as repetitions
 */
Unit Tests (pass/fail assertions)
describe('repeats a string any number of times:', () => {
  describe('an empty string', () => {
    it('0 times', () => {
      expect(repeatString('', 0)).toEqual('');
    });
    it('10 times', () => {
      expect(repeatString('', 10)).toEqual('');
    });
    it('100 times', () => {
      expect(repeatString('', 100)).toEqual('');
    });
  });
  describe('zero repetitions', () => {
    it('"asdf"', () => {
      expect(repeatString('asdf', 0)).toEqual('');
    });
    it('"tommywalk"', () => {
      expect(repeatString('tommywalk', 0)).toEqual('');
    });
  });
  describe('standard use cases', () => {
    it('repeat a phrase 3 times', () => {
      expect(repeatString('go to school', 3)).toEqual(
        'go to schoolgo to schoolgo to school'
      );
    });
    it('phrases with punctuation', () => {
      expect(repeatString('"Go!", said Dr. Seuss?', 2)).toEqual(
        '"Go!", said Dr. Seuss?"Go!", said Dr. Seuss?'
      );
    });
    it('special characters', () => {
      expect(repeatString('\\ \n \t s', 2)).toEqual('\\ \n \t s\\ \n \t s');
    });
  });
  describe('default values', () => {
    it('repetitions default should be 1', () => {
      expect(repeatString('asdf')).toEqual('asdf');
    });
    it('text default should be an empty string', () => {
      expect(repeatString()).toEqual('');
    });
  });
});
Use Cases ("real-world" examples)
// repeating a string inside an I/O loop
let repeatedText = '';
while (true) {
  const userString = promptForSomething('input a string to repeat');
  const userRepetitions = promptForNumber('how many times to repeat it?');
  const repeatedInput = repeatString(userString, userRepetitions);
  const userConfirmed = confirm(`is this correct: "${repeatedInput}"`);
  if (userConfirmed) {
    repeatedText = repeatedInput;
    break;
  }
}
console.log(repeatedText);
// repeating a string from the DOM
const userString = document.getElementById('text-input').value;
const userRepetitions = document.getElementById('number-input').value;
const repeatedInput = repeatString(userString, userRepetitions);
document.getElementById('repeated-value-display').innerHTML = repeatedInput;

Strategy

How do you approach solving the problem? There are many strategies to solve the same problem! A way to practice strategy is to think of transforming the arguments to the return value in small steps, focusing on the data not the code. This is the realm of flow charts, diagrams, and pseudo-code.

One way to approach strategy is to solve the problem a few different ways by hand, writing what you expect to change in memory at each step. Like if you were the debugger and you couldn't see the source code. Using a pencil and paper is a the best way to go, pick a few test cases and see how you'd solve them manually.

Here are four possible strategies to approach repeating a string. Each one is written as block comment with step-by-step goals focusing on what should happen at each step, not how it will happen. This type of comment is helpful to include in your code:

Iterate until string is long enough
/* iterating until the new string's length is correct

  repeatString(text, repetitions) =>
    1. calculate the final length for the new string
    2. create a new string to fill with many text's
    3. iterate as long as the new string is too short
      a. check if the new string is long enough
        stop if it is, keep going if it is not
      b. append text to the new
      c. repeat
    return: the new repeated string

*/
Iteration with a stepper variable
/* iterating over the number of repetitions

  repeatString(text, repetitions) =>
    1. create a new string to fill with many text's
    2. create a stepper variable, starting at 0
    3. iterate from 0 to repetitions
      a. check if stepper is still less than repetitions
        keep going if it is, otherwise stop iterating
      b. append text to the new string
      c. increment the stepper
      d. repeat
    return: the new repeated string

*/
Recurse with base-case 0
/* recursion with base-case 0

  i'm using 0 as the base-case because that is the fewest possible repetitions
  zero repetitions is an empty string, so if repetitions is 0 it will return ''

  otherwise i'll need to combine the text with a string that has one fewer reptitions

  repeatString(text, repetitions) =>
    base-case: repetitions is 0
      return: an empty string
    recursive case: repetitions is greater than 0
      nextRepetitions = subtract one from repetitions
      recursedValue = recursively call repeatString with text and nextRepetitions
      return: text + recursedValue

*/
Native JS methods
/* use built-in .js methods

  repeatString(text, repetitions) =>
    1. make sure the data is the correct type and format for the method you're using
    2. use the method
    return: the result

*/

Implementation

Which language features and which lines of code can you use to make your strategy a reality? There are many ways to code the same strategy. let's look at multiple implementations for each strategy described above, all of these functions will pass the unit tests written in the Behavior section:

Iterate Until String is Long Enough

While loop, true and break
/* unconventional and pretty old-school
  there is a lot of reinventing the wheel
  while loops are designed to check conditions
  this is not the simplest solution to read or maintin
*/
const repeatString = (text = '', repetitions = 1) => {
  const finalLength = text.length * repetitions;
  let repeatedText = '';
  while (true) {
    if (repeatedText.length === finalLength) {
      break;
    }
    repeatedText = repeatedText + text;
  }
  return repeatedText;
};
While loop, logic in head
/* the cleanest implementation for this strategy
  it uses the language feature designed for this type of strategy
*/
const repeatString = (text = '', repetitions = 1) => {
  const finalLength = text.length * repetitions;
  let repeatedText = '';
  while (repeatedText.length < finalLength) {
    repeatedText += text;
  }
  return repeatedText;
};
For loop with only a condition check
/* not the best implementation, it's confusing to read
  this strategy does not use stepping, and for loops are designed for stepping
  implementing this strategy with a for loop is putting a square peg in a round hole

  when someone sees a for loop they expect it to be used like a for loop
  this implementation uses a for loop like a while loop
  the computer doesn't care, but the intention is confusing for other devs
*/
const repeatString = (text = '', repetitions = 1) => {
  const finalLength = text.length * repetitions;
  let repeatedText = '';
  for (; repeatedText.length < finalLength; ) {
    repeatedText += text;
  }
  return repeatedText;
};

Iteration with Stepper Variable

While loop, true and break
/* unconventional and pretty old-school
  there is a lot of reinventing the wheel
  while loops are designed to check conditions
  this is not the simplest solution to read or maintain
*/
const repeatString = (text = '', repetitions = 1) => {
  let repeatedText = '';
  let count = 0;
  while (true) {
    if (count === repetitions) {
      break;
    }
    repeatedText += text;
    count++;
  }
  return repeatedText;
};
While loop, condition in head
/* a better way to user the while loop since the condition is known
  easier to read and more conventional than the previous implementation
  maybe you find this easier to read than a for loop
*/
const repeatString = (text = '', repetitions = 1) => {
  let repeatedText = '';
  let count = 0;
  while (count < repetitions.length) {
    repeatedText = repeatedText + text;
    count++;
  }
  return repeatedText;
};
For loop
/* the cleanest implementation for this strategy
  it uses the language feature designed for stepping
*/
const repeatString = (text = '', repetitions = 1) => {
  let repeatedText = '';
  for (let count = 0; count < repetitions.length; count++) {
    repeatedText += text;
  }
  return repeatedText;
};

Recursion with Base-Case 0

Ternary Operator
// in all it's ES6 one-line glory
// some people find this easier to read than conditionals
const repeatString = (text = '', repetitions = 1) =>
  repetitions === 0 ? '' : text + repeatString(text, nextRepetitions - 1);
Conditional Statement
// good old fashioned conditional blocks
// some people find this easier to read than ternaries
const repeatString = (text = '', repetitions = 1) => {
  if (repetitions === 0) {
    return '';
  } else {
    const nextRepetitions = repetitions - 1;
    const oneRepetitionShort = repeatString(text, nextRepetitions);
    return text + oneRepetitionShort;
  }
};
Conditional Statement (tail-call recursion)
/* this implementation is "backwards compatible"
  that means that it has a different signature (the extra `repeated` parameter)
  but can still replace previous implementations without breaking anything
*/
const repeatString = (text = '', repetitions = 1, repeated = '') => {
  if (repetitions === 0) {
    return repeated;
  } else {
    const nextRepeated = repeated + text;
    const nextRepetitions = repetitions - 1;
    return repeatString(text, nextRepetitions, nextRepeated);
  }
};

Built-In JS Methods

Sting.prototype.repeat
// short and sweet, no room for mistakes
const repeatString = (text = '', repetitions = 1) => text.repeat(repetitions);
Array.prototype.fill
// less clear and more complex, but still pretty clear to read
const repeatString = (text = '', repetitions = 1) => {
  const oneEntryPerRepetition = Array(repetitions).fill(text);
  const repeatedString = oneEntryPerRepetition.join('');
  return repeatedString;
};

Contents


Getting Started

You will need NPM and nvm on your computer to study this material

  1. Clone this repository:
    • git clone [email protected]:HackYourFutureBelgium/behavior-strategy-implementation.git (SSH)
    • git clone https://github.com/HackYourFutureBelgium/behavior-strategy-implementation.git (HTTPS)
    • gh repo clone HackYourFutureBelgium/behavior-strategy-implementation (GH CLI)
  2. cd into the repository
    • cd behavior-strategy-implementation

In the Browser

Using a browser with good DevTools will make your life easier: Chromium, FireFox, Edge, Chrome

  1. Install or update the study-lenses package globally
    • npm install -g study-lenses (if you do not have it already)
    • npm update -g study-lenses (if you already have it installed)
  2. Run the study command from your CLI
    • study
  3. The material will open in your default browser, you're good to go!
    • if a .test.js file does not work, you can manually check on tests from the config options

If you have a windows computer and get this error:

  • ... /study.ps1 cannot be loaded because running scripts ...

follow the instructions in this StackOverflow answer, that should take care of it ; )

In Node.js

The debugger built into VSCode is very good, it's all you'll need. Don't forget to set breakpoints!

  • Running files in .js (without .test):
    • debugger: open the file, select the debug option from your VSCode side-bar, choose the Current JS File (no tests) option, and click the triangle button. (hint you will need to use breakpoints)
    • console: node path/to/file.js, simple and easy
  • Running files ending in .test.js or .spec.js:
    • debugger: open the file, select the debug option from your VSCode side-bar, choose the Current JS File (with tests) option, and click the triangle button. (hint: you will need to use breakpoints)
    • console: files ending in .test.js or .spec.js must be run with npm run test -- path/to/file.test.js.

TOP


Study Tips

  • Don't rush, understand! Programming is hard.
    • The examples and exercises will still be there to study later.
    • It's better to fail tests slowly and learn from your mistakes than to pass tests quickly and not understand why.
  • Don't skip the examples! Understanding and experimenting with working code is a very effective way to learn programming.
  • Write lots of good comments, learn more about this in ./studying-javascript
  • Practice Pair Programming: two people, one computer.
  • Take a look through the Learning From Code guide for more study tips

Priorities

If you can't finish all the material in this repository, that's expected! Anything you don't finish now will always be waiting for you to review when you need it. These 3 emoji's will help you prioritize your study time and to measure your progress:

  • πŸ₯š :egg: - Understanding this material is required, it covers the base skills you'll need for this module and the next. You do not need to finish all of them but should feel comfortable that you could with enough time.
  • 🐣 :hatching_chick: - Do your best to start this material. you don't need to master it or finish it but getting the main idea will be helpful for taking the next steps.
  • πŸ₯ :hatched_chick: - Have you finished all the πŸ₯š's and started all the 🐣's? push yourself with these challenges.

Hashtags

There's sooo many examples and exercises in this repository, it's easy to forget of what you still need to finish or what you want to review again. Luckily VSCode is really good at searching through folders of code.

You can write hashtags in your comments while you're studying, then search for those hashtags later so you don't miss anything. Here's some ideas:

  • // #not-done, still a few blanks left - search for #not-done in VScode to find all the exercises you've started and not finished
  • // coercion is confusing, #review this again next week - search for #review to find the files you need to study again
  • ... anything goes! Find the hashtags that work for you

Module Project Boards

If you create a fork of this repository you can open a project board in your fork to track your progress through the module. Just 3 columns can be enough: Todo, Doing, Done.

TOP


Learning Objectives

What can you expect to learn in this module?

expand/collapse
  • Learning from Code
    • Reading & understanding other people's code
    • Making small, incremental experiments
    • Copying & modifying others' code
  • Reading and writing unit tests
    • describe
    • it
    • expect(actual).toEqual(expected)
  • TDD
    • Trust the tests!
    • Solving challenges one test at a time
  • Debugging
    • Stepping through tests in the debugger
    • Reading test results to debug code behavior
    • Interpreting assertion errors
  • Reading and writing documentation
  • Code review

TOP


Suggested Study

Helpful resources for this module

expand/collapse

study.hackyourfuture.be/javascript

Exercises & Practice

  • Separate Repositories
    • πŸ₯š,🐣,πŸ₯: Solution Write-Ups Learn to solve coding challenges by studying other people's solutions.
      1. Fork the repository
      2. Clone your fork
      3. Push your work regularly so others can study it
    • 🐣: document-and-pass: write your own solutions and documentation to some coding challenges. Practice debugging and using testing libraries in VSCode
    • 🐣: practice-code-review (coming soon for week 3)
  • In this Repo
    • πŸ₯š: ./about-testing: A quick introduction to describe, it, and expect
    • πŸ₯š: ./array-methods: Learn array methods by first understanding the strategies they are designed for.
    • 🐣 ./hoisting: That famous thing about JS! It's not so bad once you get it, the key to understanding hoisting is to understand the program life-cycle: creation phase and execution phase. This chapter is more abstract, hoisting is something "invisible" about JavaScript program execution. These exercises will help you see hoisting by exploring the debugger at different points in program execution.
    • 🐣: ./parsons-problems: Explore behavior, strategy and implementation by reconstructing different solutions to coding challenges.
    • 🐣: ./function-design: Learn a structured approach to understanding and solving coding challenges
  • πŸ₯: More Practice:

Are we missing a great set of exercises? Send a PR!

About Testing

Higher-Order Functions

Array Methods

Arrays of Objects

Recursion


TOP


Week 1

The best problem solvers don't start from nothing, they've seen many similar problems before and have learned to adapt other people's code to fit their programs.

This week take your first step to becoming an expert problem solver by studying the many ways people before you have solved common problems.

expand/collapse

Before Class

  • Fork solution-write-ups
    • Read through the README, this will be your main exercise for the week.
    • create a new folder called add-up-the-numbers-from-a-single-number
    • create a README.md file in this folder using the write-up-template.md
    • create an empty javascript file called sandbox.test.js
  • Read through ./about-testing/examples to be familiar with the syntax for describe, it, and expect
  • Create an account on Edabit

During Class

In class you will practice writing tests and analyzing solutions using a challenge from Edabit:

Before Break

Description, Syntax, Test Cases and Use Cases.

  • All together:
    • look through the examples at the beginning of this README. What is behavior, strategy and implementation?
    • go over the README from solution-write-ups
    • read through the first 4 sections in the example from solution-write-ups
  • In small groups:
    • Complete the first 4 sections of the writeup for Add up the Numbers ...
    • You can use the most popular solution solution by _sir to write your tests:
      function addUp(num) {
        return (num * (num + 1)) / 2;
      }

After Break

Strategy, Implementation and Possible Refactors.

  • All together:

  • In small groups:

    • practice writing up 2-3 solutions to the Add up the Numbers ... challenge (be sure to test them all!)

    • here's a few suggestions to study:
      // _sir
      function addUp(num) {
        return (num * (num + 1)) / 2;
      }
      
      // Gabriel
      function addUp(num) {
        let sum = 0;
        for (let i = 1; i <= num; i++) {
          sum += i;
        }
        return sum;
      }
      
      // 범두
      function addUp(num) {
        var a = 0;
        for (var i = num; i > 0; i--) {
          a += i;
        }
        return a;
      }
      
      // doodledob
      function addUp(num) {
        x = 0;
        while (num >= 0) {
          x += num;
          num--;
        }
        return x;
      }

After Class

Take your time this week to explore other people's code. In the past modules you've studied only a small part of what JS, now you're in the wild! You'll come across all sorts of JS features and new coding styles.

Complete as many write-ups as you can. No need to rush ahead! Take your time studying solutions at your level. It's more helpful to study a variety of solutions than to study a few hard ones:

Here's two important JS concepts you should study while doing your write-ups:

These exercises will help you understand test cases, and be important for next week:

While these are great for when you need a little break:


TOP


Week 2

Learn to write unit tests and to write your own solutions one step at a time.

expand/collapse

Before Class

Read through the steps of Function Design and study the example

During Class

Before Break

After Break

After Class

Continue writing Solution Write-Ups. To help you gain a deeper understanding of how to write your own solutions, take some time to study these exercises:

Just like last week, there's no reason to rush yourself. You can learn how to write tests and how to design functions with simple challenges just as well as with hard challenges. So find your level, settle in, and study as many problems as you can.


TOP


Week 3

Code Review! Practice reviewing

expand/collapse

Before Class

During Class

Before Break

After Break

After Class

group exercises

practice-code-review (coming soon)

Checklist


TOP


Class Recordings

  • Students: Here you can find recordings of this module from past classes. Enjoy!
    • Do you have a favorite? Send a PR giving it a πŸ‘
  • Coaches: When sending your PR's with links please ...
    • Indicate which class you were teaching
    • Which week it was (if the module is more than 1 week)
    • Give your name
    • and a helpful description

class-9-10

Charles, Sali & Evan

  1. Week 1:
  2. Week 2:
  3. Week 3:

class-11-12

Evan, Thibault, Joel

  1. Week 1
  2. Week 2 - server crash :(
  3. Week 3: Objects Pt. 1, Objects Pt. 2, Project Intro

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 100.0%