├── .gitignore
├── schedule
├── code-excerpts
│ ├── bad-code.md
│ ├── routes.md
│ └── geiger-counter.md
├── w2.md
├── w3.md
├── w4.md
├── w7.md
└── questions
│ ├── w2
│ ├── w2b.md
│ └── w2a.md
│ ├── w3
│ ├── w3a.md
│ └── w3b.md
│ ├── w7
│ ├── w7b.md
│ └── w7a.md
│ └── w4
│ ├── w4a.md
│ └── w4b.md
├── documents
└── default-email.txt
├── README.md
└── pairs.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | yarn.lock
3 | curriculum-stash
4 | dist
5 |
--------------------------------------------------------------------------------
/schedule/code-excerpts/bad-code.md:
--------------------------------------------------------------------------------
1 | # Bad Code
2 |
3 | ``` ruby
4 | class CommentsController < ApplicationController
5 | def users_comments
6 | posts = Post.all
7 | comments = posts.map(&:comments).flatten
8 | @user_comments = comments.select do |comment|
9 | comment.author.username == params[:username]
10 | end
11 | end
12 | end
13 | ```
14 |
--------------------------------------------------------------------------------
/schedule/code-excerpts/routes.md:
--------------------------------------------------------------------------------
1 | # Routes
2 |
3 | ```
4 | GET /cats
5 | GET /cats/:id
6 | GET /cats/new
7 | POST /cats
8 | GET /cats/:id/edit
9 | PATCH /cats/:id
10 | PUT /cats/:id
11 | DELETE /cats/:id
12 | GET /cats/:cat_id/tricks
13 | POST /cats/:cat_id/tricks
14 | DELETE /cats/:cat_id/tricks/:id
15 | POST /cats/:cat_id/upvote
16 | DELETE /cats/:cat_id/upvote
17 | ```
18 |
--------------------------------------------------------------------------------
/schedule/w2.md:
--------------------------------------------------------------------------------
1 | # Week 2
2 |
3 | ** ONLY READ THE QUESTIONS THAT YOU ARE ASSIGNED TO ASK. **
4 |
5 | ## Assignments
6 |
7 | * If you are student A, go [here][student-a].
8 | * If you are student B, go [here][student-b].
9 |
10 | ## Grading Sheet
11 |
12 | [Here][grading-sheet] is a link to the grading sheet.
13 |
14 | [student-a]: ./questions/w2/w2a.md
15 | [student-b]: ./questions/w2/w2b.md
16 | [grading-sheet]: https://docs.google.com/spreadsheets/d/17KhZzPX8oysrbw7a4z4Z8huayaaTStUWjdRle3nmLC0/edit?usp=sharing
17 |
--------------------------------------------------------------------------------
/schedule/w3.md:
--------------------------------------------------------------------------------
1 | # Week 3
2 |
3 | ** ONLY READ THE QUESTIONS THAT YOU ARE ASSIGNED TO ASK. **
4 |
5 | ## Assignments
6 |
7 | * If you are student A, go [here][student-a].
8 | * If you are student B, go [here][student-b].
9 |
10 | ## Grading Sheet
11 |
12 | [Here][grading-sheet] is a link to the grading sheet.
13 |
14 | [student-a]: ./questions/w3/w3a.md
15 | [student-b]: ./questions/w3/w3b.md
16 | [grading-sheet]: https://docs.google.com/spreadsheets/d/17KhZzPX8oysrbw7a4z4Z8huayaaTStUWjdRle3nmLC0/edit?usp=sharing
17 |
--------------------------------------------------------------------------------
/schedule/w4.md:
--------------------------------------------------------------------------------
1 | # Week 4
2 |
3 | ** ONLY READ THE QUESTIONS THAT YOU ARE ASSIGNED TO ASK. **
4 |
5 | ## Assignments
6 |
7 | * If you are student A, go [here][student-a].
8 | * If you are student B, go [here][student-b].
9 |
10 | ## Grading Sheet
11 |
12 | [Here][grading-sheet] is a link to the grading sheet.
13 |
14 | [student-a]: ./questions/w4/w4a.md
15 | [student-b]: ./questions/w4/w4b.md
16 | [grading-sheet]: https://docs.google.com/spreadsheets/d/17KhZzPX8oysrbw7a4z4Z8huayaaTStUWjdRle3nmLC0/edit?usp=sharing
17 |
--------------------------------------------------------------------------------
/schedule/w7.md:
--------------------------------------------------------------------------------
1 | # Week 7
2 |
3 | ** ONLY READ THE QUESTIONS THAT YOU ARE ASSIGNED TO ASK. **
4 |
5 | ## Assignments
6 |
7 | * If you are student A, go [here][student-a].
8 | * If you are student B, go [here][student-b].
9 |
10 | ## Grading Sheet
11 |
12 | [Here][grading-sheet] is a link to the grading sheet.
13 |
14 | [student-a]: ./questions/w7/w7a.md
15 | [student-b]: ./questions/w7/w7b.md
16 | [grading-sheet]: https://docs.google.com/spreadsheets/d/17KhZzPX8oysrbw7a4z4Z8huayaaTStUWjdRle3nmLC0/edit?usp=sharing
17 |
--------------------------------------------------------------------------------
/documents/default-email.txt:
--------------------------------------------------------------------------------
1 | Hi all,
2 |
3 | Below you will find the link to today’s whiteboarding questions. Click the link that is in the column that has your name.
4 |
5 | Spend ten minutes reviewing the questions you will ask. Each candidate should have about 35 minutes to answer both questions. Give yourself about 5 to 10 minutes to fill out the scorecard.
6 |
7 | Whiteboarding should be finished around 11:00am. If you happen to finish early, feel free to get started on the day’s work.
8 |
9 | Here are the assignments:
10 |
11 | Whiteboarding Assignments
12 |
13 | Here is the whiteboarding grading sheet:
14 |
15 | Whiteboarding Grading Sheet
16 |
17 | Have fun!
18 |
19 | Louis
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **NOTE** : This is a deprecated repo. See [whiteboarding](https://github.com/appacademy/whiteboarding) for an updated whiteboarding curriculum.
2 |
3 | # Curriculum Whiteboarding
4 |
5 | This repository exists to organize the whiteboard questions that
6 | students are given during the first nine weeks of the curriculum.
7 |
8 | ## Schedule
9 |
10 | There are four whiteboarding sessions that occur during the curriculum.
11 |
12 | * [Week 2][w2] (W2D2)
13 | * [Week 3][w3] (W3D2)
14 | * [Week 4][w4] (W4D3)
15 | * [Week 7][w7] (W7D3)
16 |
17 | [w2]: ./schedule/w2.md
18 | [w3]: ./schedule/w3.md
19 | [w4]: ./schedule/w4.md
20 | [w7]: ./schedule/w7.md
21 |
22 | ## Instructors
23 |
24 | Instructor can view the old Google Drive [here][google-drive].
25 |
26 | [google-drive]: https://drive.google.com/drive/u/1/folders/0B2GA4obf3HcmbkUyU2d0RVRGdjA
27 |
--------------------------------------------------------------------------------
/schedule/questions/w2/w2b.md:
--------------------------------------------------------------------------------
1 | # Week 2
2 |
3 | ## Student B
4 |
5 | Below are the two questions that you will be asking student A.
6 |
7 | ### Fibonacci – Two Ways
8 |
9 | #### Prompt
10 |
11 | Write a method, `fibs(num)` which returns the first `num` elements from
12 | the Fibonacci sequence, given `num`.
13 |
14 | Solve it both iteratively and recursively.
15 |
16 | #### Solution
17 |
18 | Iterative Solution:
19 |
20 | ```ruby
21 | def fibs(num)
22 | return [] if num == 0
23 | return [0] if num == 1
24 |
25 | fibs = [0, 1]
26 | while fibs.count < num
27 | fibs << fibs[-1] + fibs[-2]
28 | end
29 |
30 | fibs
31 | end
32 | ```
33 |
34 | Recursive Solution:
35 |
36 | ```ruby
37 | def fibs(num)
38 | return [] if num == 0
39 | return [0] if num == 1
40 | return [0, 1] if num == 2
41 |
42 | prev_fibs = fibs(num - 1)
43 | prev_fibs << prev_fibs[-1] + prev_fibs[-2]
44 |
45 | prev_fibs
46 | end
47 | ```
48 |
49 | ### Agile
50 |
51 | #### Prompt
52 |
53 | Define "Test-Driven Development" and "Continuous Integration." Also,
54 | what are their benefits?
55 |
56 | #### Solution
57 |
58 | Test-Driven Development follows the pattern of writing tests first,
59 | watching them fail, writing the code to make them pass, and then
60 | watching the tests pass.
61 |
62 | Continuous Integration is the practice of integrating newly developed
63 | code back into a main branch multiple times a day.
64 |
65 | A benefit of Test-Driven Development is that it allows for clear
66 | expectations of the code to be written. Another benefit is that it
67 | allows for safer refactoring. After refactoring, a developer can be much
68 | more certain that the refactoring did not introduce any bugs.
69 |
70 | A benefit of Continuous Integration is that it prevents the need to
71 | reconcile massive merge conflicts, which can be fairly common if
72 | multiple developers work on multiple feature branches simultaneously.
73 |
--------------------------------------------------------------------------------
/schedule/questions/w3/w3a.md:
--------------------------------------------------------------------------------
1 | # Week 3
2 |
3 | ## Student A
4 |
5 | Below are the two questions that you will be asking student B.
6 |
7 | ### OOP – Jukebox
8 |
9 | #### Prompt
10 |
11 | Design a musical jukebox using object-oriented principles.
12 |
13 | #### Solution
14 |
15 | Here are some answers to questions the interviewee might ask:
16 |
17 | ##### Is the jukebox physical or virtual?
18 |
19 | Assume the jukebox is virtual or computer-simulated.
20 |
21 | ##### Does the jukebox accept currency?
22 |
23 | Assume the jukebox operates free of charge.
24 |
25 | Here is the skeleton of a potential solution:
26 |
27 | ```ruby
28 | class Jukebox
29 | attr_accessor :user
30 | attr_reader :current_track
31 |
32 | def initialize(player, user)
33 | @player = player
34 | @user = user
35 | @current_track = nil
36 | end
37 | end
38 |
39 | class Player
40 | attr_accessor :album, :playlist
41 |
42 | def initialize(album, playlist)
43 | @album = album
44 | @playlist = playlist
45 | end
46 |
47 | def play_track(track)
48 | # Begin playing...
49 | end
50 | end
51 |
52 | class Playlist
53 | def initialize
54 | @queue = []
55 | end
56 |
57 | def add_track(track)
58 | @queue.push(track)
59 | end
60 |
61 | def shift
62 | @queue.shift
63 | end
64 | end
65 |
66 | class Album
67 | # Information about the album
68 | end
69 |
70 | class Track
71 | # Information about the track, including album
72 | end
73 |
74 | class User
75 | # Information about the user.
76 | end
77 | ```
78 |
79 | ### SQL – Employees
80 |
81 | #### Prompt
82 |
83 | In a SQL db, you have two tables, an employees table and a departments
84 | table. Employees belong to only one department. Write a SQL query that,
85 | given a department name, finds all the employees in that department.
86 |
87 | #### Solution
88 |
89 | ```sql
90 | SELECT
91 | employees.*
92 | FROM
93 | employees e
94 | JOIN
95 | departments d ON e.department_id = d.id
96 | WHERE
97 | d.name = ?
98 | ```
99 |
--------------------------------------------------------------------------------
/schedule/code-excerpts/geiger-counter.md:
--------------------------------------------------------------------------------
1 | # Geiger Counter
2 |
3 | ```js
4 | import React from 'react';
5 |
6 | class GeigerCounter extends React.Component {
7 | constructor() {
8 | this.state = {
9 | counts: [false],
10 | probability: 50,
11 | maxCountsSize: this.props.maxCountsSize || 30,
12 | };
13 | }
14 |
15 | componentDidMount() {
16 | this.startCounter();
17 | }
18 |
19 | startCounter() {
20 | setInterval(() => {
21 | this.updateCounts();
22 | }, 1000);
23 | }
24 |
25 | updateCounts() {
26 | const booleanVal = this.generateBoolean();
27 |
28 | const newCounts;
29 |
30 | if (this.state.counts.length < this.state.maxCountsSize) {
31 | newCounts = this.state.counts.concat(booleanVal);
32 | } else {
33 | newCounts = this.state.counts.slice(1).concat(booleanVal);
34 | }
35 |
36 | this.setState({ counts: newCounts });
37 | console.log(this.state.counts.length);
38 | }
39 |
40 | generateBoolean() {
41 | const floatProbability = this.state.probability / 100.0;
42 | const randFloat = Math.random();
43 |
44 | return randFloat < floatProbability;
45 | }
46 |
47 | geigerValue() {
48 | const { length } = this.state.counts;
49 |
50 | let trueCount = 0;
51 |
52 | for (let i = 0; i < length; i++) {
53 | if (this.state.counts[i]) trueCount++;
54 | }
55 |
56 | return trueCount / length;
57 | }
58 |
59 | updateProbability(value) {
60 | const newValue = this.state.probability + value;
61 | if (newValue >= 0 && newValue <= 100) {
62 | this.setState({ probability: newValue });
63 | }
64 | }
65 |
66 | render() {
67 | return (
68 |
69 |
70 | The radiation level is currently: {this.geigerValue()}
71 |
72 |
73 | The current radiation level is at {this.state.probability}%
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | );
82 | }
83 | }
84 | ```
85 |
--------------------------------------------------------------------------------
/schedule/questions/w2/w2a.md:
--------------------------------------------------------------------------------
1 | # Week 2
2 |
3 | ## Student A
4 |
5 | Below are the two questions that you will be asking student B.
6 |
7 | ### Recursive Sum
8 |
9 | #### Prompt
10 |
11 | Write a function that takes an array of integers and returns their sum.
12 | Use recursion.
13 |
14 | #### Solution
15 |
16 | ```ruby
17 | def sum_rec(nums)
18 | return 0 if nums.empty?
19 | nums[0] + sum_rec(nums.drop(1))
20 | end
21 | ```
22 |
23 | ### Ruby – Contrast and Compare
24 |
25 | #### Prompt
26 |
27 | Ruby is a dynamic, reflective language that lends itself to
28 | object-oriented programming. What are some benefits and drawbacks of
29 | dynamic languages? What are some benefits and drawbacks of reflection
30 | and object-oriented programming?
31 |
32 | #### Solution
33 |
34 | This question has a wide variety of potential answers.
35 |
36 | Benefits of dynamic languages:
37 |
38 | * Allows for execution of code at compile time
39 | * Potentially more abstraction and less code
40 | * Dynamic typing allows for flexibility
41 |
42 | Drawbacks of dynamic languages:
43 |
44 | * Dynamic typing means that errors are often encountered at run time
45 | * Run time evaluation decreases execution speed
46 |
47 | Benefits of reflection:
48 |
49 | * It allows for much of metaprogramming
50 | * Create custom methods on the fly
51 |
52 | Drawbacks of reflection:
53 |
54 | * Code can be very confusing/hard to reason about
55 |
56 | Benefits of object-oriented programming:
57 |
58 | * Inheritance lends itself to easy reusability of code
59 | * Encapsulation offers a system for organization of code
60 | * Information hiding ensures that objects have enough information to
61 | perform what they need to do without making that information public to
62 | external objects
63 |
64 | Drawbacks of object-oriented programming:
65 |
66 | * The preference for data over functions can result in more code
67 | * Polymorphism and inheritance can make it difficult to determine what
68 | the result of a method call will be
69 | * Reliance on side effects can make it difficult to reason about the
70 | correctness of code (to work out correctly, methods might need to be
71 | called in a certain order or objects might need to be in some certain
72 | state)
73 |
--------------------------------------------------------------------------------
/pairs.js:
--------------------------------------------------------------------------------
1 | const FIRST = 'FIRST';
2 | const SECOND = 'SECOND';
3 | const ODD = 'ODD';
4 | const EVEN = 'EVEN';
5 |
6 | const getPodWrappers = () => {
7 | const podWrappers = document.querySelectorAll('section.pod-tables');
8 | return Array.from(podWrappers);
9 | }
10 |
11 | const getPairNameWrappers = (parent = document) => {
12 | const nameWrappers = parent.querySelectorAll('figure.pair-selects');
13 | return Array.from(nameWrappers);
14 | }
15 |
16 | const getAllStudents = (parent = document) => {
17 | const studentNameWrappers = parent.querySelectorAll('h4.student-name');
18 | return Array.from(studentNameWrappers);
19 | }
20 |
21 | const getAllStudentNames = (n) => {
22 | const pairNameWrappers = getPairNameWrappers();
23 | let names = [];
24 | pairNameWrappers.forEach((wrapper) => {
25 | const nameStrings = getAllStudents(wrapper).map((el) => {
26 | return el.innerHTML.trim();
27 | });
28 | nameStrings.forEach((name) => {
29 | names.push(name);
30 | });
31 | if (nameStrings.length < 2) {
32 | names.push('empty');
33 | }
34 | });
35 | const filteredNames = names.filter((val, idx) => {
36 | if (n === ODD) {
37 | return idx % 2 !== 0;
38 | } else if (n === EVEN) {
39 | return idx % 2 === 0;
40 | }
41 | })
42 | const namesString = filteredNames.join('\n');
43 |
44 | return namesString;
45 | }
46 |
47 | const getStudents = (index) => {
48 | const allStudentNames = getAllStudentNames();
49 | let studentNames;
50 | switch (index) {
51 | case FIRST:
52 | studentNames = getAllStudentNames(EVEN);
53 | console.log(studentNames);
54 | return;
55 | case SECOND:
56 | studentNames = getAllStudentNames(ODD);
57 | console.log(studentNames);
58 | return;
59 | default:
60 | throw 'Invalid Index';
61 | };
62 | }
63 |
64 | // Use this script to get the first row of names
65 | const getFirstStudents = () => {
66 | const students = getStudents(FIRST);
67 | }
68 |
69 | // Use this script to get the second row of names
70 | const getSecondStudents = () => {
71 | const students = getStudents(SECOND);
72 | }
73 |
74 | // Use this script to get the pods
75 | const getPodNames = () => {
76 | const podWrappers = getPodWrappers();
77 | let result = '';
78 | podWrappers.forEach((pod) => {
79 | const name = pod.querySelector('h2').innerHTML.trim();
80 | const numPairs = getPairNameWrappers(pod).length;
81 | for (let i = 0; i < numPairs; i += 1) {
82 | result += `${name}\n`;
83 | }
84 | });
85 | console.log(result);
86 | }
87 |
88 | // INSTRUCTIONS:
89 | //
90 | // Get all the first students with `getFirstStudents()`.
91 | // Get all the second students with `getSecondStudents()`.
92 | // Get their pod names with `getPodNames()`.
93 | //
94 | // Like as follows:
95 | //
96 | // getFirstStudents();
97 | // getSecondStudents();
98 | // getPodNames();
99 |
--------------------------------------------------------------------------------
/schedule/questions/w7/w7b.md:
--------------------------------------------------------------------------------
1 | # Week 7
2 |
3 | ## Student B
4 |
5 | Below are the two questions that you will be asking student A.
6 |
7 | ### Redux
8 |
9 | #### Prompt
10 |
11 | I want a simple social media app that will store posts.
12 | I would like you to use Redux to store the front-end state.
13 | Each post should have a body, title, and id.
14 | Users should be able to post new posts.
15 | They should also be able to delete old posts and edit existing posts.
16 | Please describe how you would store and work with posts on the front-end
17 | using Redux. In particular,
18 |
19 | * Describe the Redux state shape you would implement
20 | * Describe the reducers and action creators you would use
21 |
22 | #### Solution
23 |
24 | The state should look something like this:
25 |
26 | ```js
27 | {
28 | todos {
29 | 1: {
30 | id: 1,
31 | title: 'A Post',
32 | body: 'It\'s body'
33 | },
34 | 2: {
35 | id: 2,
36 | title: 'Another Post',
37 | body: 'It also has a body'
38 | },
39 | }
40 | }
41 | ```
42 |
43 | In particular, the posts should be stored in an object nested under its
44 | Id. They should not be stored in an array (because we will want constant
45 | time lookup).
46 |
47 | The action creators should look something like this:
48 |
49 | ```js
50 | export const ReceivePosts = posts => ({
51 | type: RECEIVE_POSTS,
52 | posts
53 | });
54 |
55 | export const ReceivePost = post => ({
56 | type: RECEIVE_POST,
57 | post
58 | });
59 |
60 | // This action creator should NOT take post as an argument
61 | // The id is enough to identify the post to be deleted, and we always
62 | // want our actions to cary the smallest possible payload
63 | export const DeletePost = id => ({
64 | type: DELETE_POST,
65 | id
66 | });
67 | ```
68 |
69 | We will only need one reducer.
70 | The following reducer would work with the above actions:
71 |
72 | ```js
73 | // It is important to remember the default state, in this case: {}
74 | export default function(state = {}, action) {
75 | Object.freeze(state);
76 | switch (action.type) {
77 | case RECEIVE_POSTS:
78 | return action.posts;
79 | case RECEIVE_POST:
80 | // Make sure the post is nested under its Id before merging with state
81 | return Object.assign({}, state, { [action.post.id]: action.post });
82 | case DELETE_POST:
83 | let newState = Object.assign({}, state);
84 | delete newState[action.id];
85 | return newState;
86 | default:
87 | return state;
88 | }
89 | }
90 | ```
91 |
92 | ### React – Virtual DOM
93 |
94 | #### Prompt
95 |
96 | What is React’s virtual DOM and why is it used? How does the diffing
97 | algorithm work?
98 |
99 | #### Solution
100 |
101 | The virtual DOM is a simpler and faster abstraction of the HTML DOM.
102 | While it might be more expensive to manage two DOMs in some respects,
103 | being able to traverse and perform operations on the virtual DOM saves
104 | React from having to have costly interactions with the real one, only
105 | updating it when it absolutely needs to.
106 |
107 | When rendering, React creates a tree of React elements. When state or
108 | props update, React then renders a tree of potentially different
109 | elements. The diffing algorithm figures out how to efficiently update
110 | the DOM, removing old DOM nodes and replacing them only when necessary.
111 | We give unique HTML elements unique IDs so the diffing algorithm can
112 | tell them apart.
113 |
114 | This algorithm solves the problem of generating the fewest number of
115 | operations needed to manage re-rendering. The React diffing algorithm
116 | manages to run in O(n) time (where n is the number of HTML elements)
117 | using a series of rules to determine when a node will need to be
118 | updated.
119 |
--------------------------------------------------------------------------------
/schedule/questions/w4/w4a.md:
--------------------------------------------------------------------------------
1 | # Week 4
2 |
3 | ## Student A
4 |
5 | Below are the two questions that you will be asking student B.
6 |
7 | ### Routes
8 |
9 | #### Prompt
10 |
11 | What code would you have to write to generate the following routes?
12 | Also, which controller actions will each route be matched to by default?
13 |
14 | ```
15 | GET /cats
16 | GET /cats/:id
17 | GET /cats/new
18 | POST /cats
19 | GET /cats/:id/edit
20 | PATCH /cats/:id
21 | PUT /cats/:id
22 | DELETE /cats/:id
23 | GET /cats/:cat_id/tricks
24 | POST /cats/:cat_id/tricks
25 | DELETE /cats/:cat_id/tricks/:id
26 | POST /cats/:cat_id/upvote
27 | DELETE /cats/:cat_id/upvote
28 | ```
29 |
30 | The interviewee can reference these routes [here][routes].
31 |
32 | [routes]: ../../code-excerpts/routes.md
33 |
34 | #### Solution
35 |
36 | This is the simplest way:
37 |
38 | ```ruby
39 | Rails.application.routes.draw do
40 | resources :cats do
41 | resources :tricks, only: [:index, :create, :destroy]
42 | resource :upvote, only: [:create, :destroy]
43 | end
44 | end
45 | ```
46 |
47 | If the interviewee uses the above code for their routes, they will be
48 | mapped to the following controller actions.
49 |
50 | ```
51 | GET /cats cats#index
52 | GET /cats/:id cats#show
53 | GET /cats/new cats#new
54 | POST /cats cats#create
55 | GET /cats/:id/edit cats#edit
56 | PATCH /cats/:id cats#update
57 | PUT /cats/:id cats#update
58 | DELETE /cats/:id cats#destroy
59 | GET /cats/:cat_id/tricks tricks#index
60 | POST /cats/:cat_id/tricks tricks#create
61 | DELETE /cats/:cat_id/tricks/:id tricks#destroy
62 | POST /cats/:cat_id/upvote upvotes#create
63 | DELETE /cats/:cat_id/upvote upvotes#destroy
64 | ```
65 |
66 | ### Bad Code
67 |
68 | #### Prompt
69 |
70 | What is wrong with the following controller action, and how would you
71 | improve it?
72 |
73 | ``` ruby
74 | class CommentsController < ApplicationController
75 | def users_comments
76 | posts = Post.all
77 | comments = posts.map(&:comments).flatten
78 | @user_comments = comments.select do |comment|
79 | comment.author.username == params[:username]
80 | end
81 | end
82 | end
83 | ```
84 |
85 | The interviewee can see the code [here][bad-code].
86 |
87 | [bad-code]: ../../code-excerpts/bad-code.md
88 |
89 | #### Solution
90 |
91 | There are a few problems here.
92 |
93 | First and foremost is the N + 1 query. First we are fetching all posts,
94 | then we are running the `comments` method on each post, which, in turn,
95 | runs an additional query. So, for each post, we are running a query.
96 |
97 | To fix that problem, we should `includes` the comments to keep them in
98 | memory.
99 |
100 | ``` ruby
101 | posts = Post.includes(:comments).all
102 | ```
103 |
104 | Additionally, for each comment, we are calling the `author` method,
105 | which performs an additional look up! We should all `includes` that:
106 |
107 | ``` ruby
108 | posts = Post.includes(comments: [:author]).all
109 | ```
110 |
111 | Fixing the N + 1 query is great, but there's another general problem
112 | with this. Why are we handling the logic of the query in Ruby? There are
113 | essentially three requests that occur: one for the posts, and two to
114 | include the comments and authors in memory. This looks like something
115 | that could be delegated to SQL pretty easily with ActiveRecord.
116 |
117 | Here's an answer that returns what we're looking for in one query:
118 |
119 | ``` ruby
120 | class CommentsController < ApplicationController
121 | def users_comments
122 | username = params[:username]
123 | @user_comments = Comment.joins(:author)
124 | .where({ author: { username: username }})
125 | end
126 | end
127 | ```
128 |
--------------------------------------------------------------------------------
/schedule/questions/w4/w4b.md:
--------------------------------------------------------------------------------
1 | # Week 4
2 |
3 | ## Student B
4 |
5 | Below are the two questions that you will be asking student A.
6 |
7 | ### Internal Project
8 |
9 | #### Prompt
10 |
11 | Our company needs an internal web application where employees can be
12 | associated with multiple projects and projects can be associated with
13 | multiple employees. How would you design the schema and models for this
14 | application?
15 |
16 | Include your database and model validations. What validations should you
17 | include?
18 |
19 | (Feel free to use `User` for the employee model and `users` for the
20 | employees table in the database.)
21 |
22 | #### Solution
23 |
24 | The key here is that users have a one-to-many relationship with projects
25 | and projects have a one-to-many relationship with users. This should
26 | signal to the interviewee that a join table will be needed. There are
27 | several names that could be used for this join table.
28 |
29 | For the validations, the interviewee ideally will think to prevent a
30 | case where a single user has multiple records for the same project. A
31 | user should only be able to be assigned to a project once. For this,
32 | they will need to validate for uniqueness on the combination of the
33 | `user_id` and `project_id`.
34 |
35 | Assuming that we choose to name the join table "assignments", the schema
36 | could look as follows. Note that they would not necessarily need to use
37 | the same `schema.rb` format.
38 |
39 | ``` ruby
40 | create_table "users", force: true do |t|
41 | t.string "name", null: false
42 | # ... Other Info ...
43 | t.datetime "created_at"
44 | t.datetime "updated_at"
45 | end
46 |
47 |
48 | create_table "assignments", force: true do |t|
49 | t.integer "user_id", null: false
50 | t.integer "project_id", null: false
51 | t.datetime "created_at"
52 | t.datetime "updated_at"
53 | end
54 |
55 | add_index "assignments", ["user_id"], name: "index_assignments_on_user_id"
56 | add_index "assignments", ["project_id"], name: "index_assignments_on_project_id"
57 | add_index "assignments", ["user_id", "project_id"], name: "index_assignments_on_user_id_and_project_id", unique: true
58 |
59 | create_table "projects", force: true do |t|
60 | t.string "name", null: false
61 | # ... Other Info ...
62 | t.datetime "created_at"
63 | t.datetime "updated_at"
64 | end
65 | ```
66 |
67 | The models could look as follows:
68 |
69 | ``` ruby
70 | class User < ActiveRecord::Base
71 | validates :name, presence: true
72 |
73 | has_many :assignments,
74 | primary_key: :id,
75 | foreign_key: :user_id,
76 | class_name: :Assignment
77 |
78 | has_many :assigned_projects,
79 | through: :assignments,
80 | source: :project
81 | end
82 |
83 | class Assignment < ActiveRecord::Base
84 | validates :user, uniqueness: { scope: :project }
85 |
86 | belongs_to :user,
87 | primary_key: :id,
88 | foreign_key: :user_id,
89 | class_name: :User
90 |
91 | belongs_to :project,
92 | primary_key: :id,
93 | foreign_key: :project_id,
94 | class_name: :Project
95 | end
96 |
97 | class Project < ActiveRecord::Base
98 | validates :name, presence: true
99 |
100 | has_many :assignments,
101 | primary_key: :id,
102 | foreign_key: :project_id,
103 | class_name: :Assignment
104 |
105 | has_many :assignees,
106 | through: :assignments,
107 | source: :user
108 | end
109 | ```
110 |
111 | ### CSS Pre-Processors
112 |
113 | #### Prompt
114 |
115 | Describe the advantages of using a CSS pre-processor and name some common examples.
116 |
117 | #### Solution
118 |
119 | A complete description should touch on at least three of the following:
120 |
121 | * Assign and reference variables
122 | * Iterative loops and conditional statements
123 | * Nested selectors
124 | * Custom function declaration (through `@mixin`)
125 | * Decomposition of code (through `@import` and partials)
126 | * Inheritance (through `@extend`)
127 |
128 | Examples:
129 | * Sass
130 | * SCSS
131 | * Less
132 | * Stylus
133 |
--------------------------------------------------------------------------------
/schedule/questions/w3/w3b.md:
--------------------------------------------------------------------------------
1 | # Week 3
2 |
3 | ## Student B
4 |
5 | Below are the two questions that you will be asking student A.
6 |
7 | ### Caesar Cipher
8 |
9 | #### Prompt
10 |
11 | Write a function that takes a message and an increment amount and
12 | outputs the same letters shifted by that amount in the alphabet. Assume
13 | lowercase and no punctuation. Preserve spaces.
14 |
15 | #### Solution
16 |
17 | The most time-efficient way to approach this problem is to create a
18 | dictionary of letters using a structure that makes it easy and fast to
19 | access a letter at any position in the alphabet. An array will do this
20 | for us -- arrays allow us to access a value at any index in constant
21 | time.
22 |
23 | ```ruby
24 | def caesar_cipher(str, shift)
25 | letters = ("a".."z").to_a
26 |
27 | encoded_str = ""
28 | str.each_char do |char|
29 | if char == " "
30 | encoded_str << " "
31 | next
32 | end
33 |
34 | old_idx = letters.find_index(char)
35 | new_idx = (old_idx + shift) % letters.count
36 |
37 | encoded_str << letters[new_idx]
38 | end
39 |
40 | encoded_str
41 | end
42 | ```
43 |
44 | ### OOP – Parking Lot
45 |
46 | #### Prompt
47 |
48 | Design a parking lot using object-oriented principles.
49 |
50 | (Don't spend too much time fleshing out actual methods. Aim to give a
51 | holistic view of which methods exist on each of the classes.)
52 |
53 | #### Solution
54 |
55 | This question is very open-ended. The interviewee should ask questions
56 | to specify what the design expectations are.
57 |
58 | Ensure that the interviewee aims to satisfy the following:
59 |
60 | * Each parking lot can have many floors.
61 | * Each parking lot allows for various kinds of vehicles to park. Assume
62 | these are motorcycle, car, and bus. Each of these has a different size.
63 | * There are multiple parking spot sizes. Assume those sizes are compact
64 | and regular.
65 | * The rules for parking a vehicle in a spot are something like this:
66 | * Motorcycles can take any parking spot, whether regular or compact.
67 | (They require, say, four feet of parking space.)
68 | * Cars can take any regular spot. (They require, say, an eight foot
69 | wide spot.)
70 | * Buses require, say, forty feet of parking space, so they will have
71 | to take multiple spaces.
72 |
73 | Obviously, there are many other possible questions about the structure,
74 | but the interviewee can assume that anything beyond these specifics are
75 | left to their discretion.
76 |
77 | What follows below would be a skeleton for a valid approach:
78 |
79 | ```ruby
80 | class Vehicle
81 | attr_reader :spots_needed, :size
82 |
83 | def initialize(license_plate)
84 | @parking_spots = []
85 | @license_plate = license_plate
86 | end
87 |
88 | def park_in_spot(spot)
89 | # ...
90 | end
91 |
92 | def clear_spots
93 | # ...
94 | end
95 |
96 | def can_fit_in_spot(spot)
97 | # ...
98 | end
99 | end
100 |
101 | class Bus < Vehicle
102 | def initialize
103 | super
104 | @spots_needed = 5
105 | @size = :large
106 | end
107 |
108 | def can_fit_in_spot(spot)
109 | # Checks if spot is :large
110 | end
111 | end
112 |
113 | class Car < Vehicle
114 | def initialize
115 | super
116 | @spots_needed = 1
117 | @size = :compact
118 | end
119 |
120 | def can_fit_in_spot(spot)
121 | # Check if spot is :compact or :large
122 | end
123 | end
124 |
125 | class Motorcycle < Vehicle
126 | def initialize
127 | super
128 | @spots_needed = 1
129 | @size = :compact
130 | end
131 | end
132 |
133 | class ParkingLot
134 | def initialize
135 | @levels = # generate_levels
136 | end
137 |
138 | def park_vehicle(vehicle)
139 | # Park the vehicle in a spot or multiple spots. Return false if failed.
140 | end
141 | end
142 |
143 | class Level
144 | def initialize(floor, num_spots)
145 | @spots = # generate spots
146 | @available_spots = num_spots
147 | @floor = floor
148 | end
149 |
150 | def park_vehicle(vehicle)
151 | # Find a place to park vehicle or return false.
152 | end
153 |
154 | def park_starting_at(spot_num, vehicle)
155 | # Park a vehicle starting at spot number and continue until vehicle.spots_needed.
156 | end
157 |
158 | def find_available_spots(vehicle)
159 | # Find a spot to park the vehicle. Return index of spot or -1.
160 | end
161 |
162 | def spot_freed
163 | @available_spots += 1
164 | end
165 | end
166 |
167 | class ParkingSpot
168 | attr_reader :row, :spot_num
169 |
170 | def initialize(size, level, row, spot_num)
171 | @vehicle = nil
172 | @spot_size = size
173 | @level = level
174 | @row = row
175 | @spot_num = spot_num
176 | end
177 |
178 | def is_free?
179 | !@vehicle
180 | end
181 |
182 | def can_fit_vehicle?(vehicle)
183 | # Check it will fit.
184 | end
185 |
186 | def park(vehicle)
187 | # Park in spot
188 | end
189 |
190 | def unpark
191 | # Remove vehicle from spot and notify level that a new spot is available.
192 | end
193 | end
194 | ```
195 |
--------------------------------------------------------------------------------
/schedule/questions/w7/w7a.md:
--------------------------------------------------------------------------------
1 | # Week 7
2 |
3 | ## Student A
4 |
5 | Below are the two questions that you will be asking student B.
6 |
7 | ### Bad Code
8 |
9 | #### Prompt
10 |
11 | A junior software engineer at our company wrote the following code.
12 | There are at least six problems with it. What are those problems, and
13 | how would you fix them? Also, what does the component do? And can you
14 | give an example of how it could be used?
15 |
16 | Feel free to let the interviewee view the code
17 | [here][geiger-code-excerpt].
18 |
19 | ```js
20 | import React from 'react';
21 |
22 | class GeigerCounter extends React.Component {
23 | constructor() {
24 | this.state = {
25 | counts: [false],
26 | probability: 50,
27 | maxCountsSize: this.props.maxCountsSize || 30,
28 | };
29 | }
30 |
31 | componentDidMount() {
32 | this.startCounter();
33 | }
34 |
35 | startCounter() {
36 | setInterval(() => {
37 | this.updateCounts();
38 | }, 1000);
39 | }
40 |
41 | updateCounts() {
42 | const booleanVal = this.generateBoolean();
43 |
44 | const newCounts;
45 |
46 | if (this.state.counts.length < this.state.maxCountsSize) {
47 | newCounts = this.state.counts.concat([booleanVal]);
48 | } else {
49 | newCounts = this.state.counts.slice(1).concat([booleanVal]);
50 | }
51 |
52 | this.setState({ counts: newCounts });
53 | console.log(this.state.counts.length);
54 | }
55 |
56 | generateBoolean() {
57 | const floatProbability = this.state.probability / 100.0;
58 | const randFloat = Math.random();
59 |
60 | return randFloat < floatProbability;
61 | }
62 |
63 | geigerValue() {
64 | const { length } = this.state.counts;
65 |
66 | const trueCounts = 0;
67 |
68 | for (let i = 0; i < length; i++) {
69 | if (this.state.counts[i]) trueCounts++;
70 | }
71 |
72 | return trueCounts / length;
73 | }
74 |
75 | updateProbability(value) {
76 | const newValue = this.state.probability + value;
77 | if (newValue >= 0 && newValue <= 100) {
78 | this.setState({ probability: newValue });
79 | }
80 | }
81 |
82 | render() {
83 | return (
84 |
85 |
86 | The radiation level is currently: {this.geigerValue()}
87 |
88 |
89 | The current radiation level is at {this.state.probability}%
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | );
98 | }
99 | }
100 | ```
101 |
102 | [geiger-code-excerpt]: ../../code-excerpts/geiger-counter.md
103 |
104 | #### Solution
105 |
106 | It can be tricky to find errors in code without running it. If the
107 | interviewee is having trouble finding the following problems, try to
108 | nudge them in the right direction.
109 |
110 | ##### The Errors
111 |
112 | ###### Missing `super`
113 |
114 | In the constructor, there should be a call of `super(props);` at the
115 | beginning. There should also be `props` passes in to the constructor.
116 |
117 | ###### Inappropriate `const`
118 |
119 | In the `updateCounts` function, we are using `const newCounts;`, but
120 | it's conditionally assigned a value in the lines that follow that
121 | declaration. Use `let` instead!
122 |
123 | ###### Infinite Interval
124 |
125 | This one can be hard to spot. The `startCounter` method called in the
126 | `componentDidMount` starts a `setInterval`, but when a component is
127 | unmounted, the interval will remain. To fix this, you would want to
128 | assign the interval so that it could be referenced and cleared later:
129 |
130 | ```js
131 | startCounter() {
132 | this.interval = setInterval(() => {...}, 1000);
133 | }
134 |
135 | componentWillUnmount() {
136 | clearInterval(this.interval);
137 | }
138 | ```
139 |
140 | ###### Async State Update
141 |
142 | Inside `updateCounts`, we have a console log that depends on the state
143 | after the `this.setState(...)`. Because `setState` is asynchronous, it
144 | may or may not return the correct value. Instead, we should pass it as a
145 | callback like so:
146 |
147 | ```js
148 | this.setState({...}, () => console.log(...));
149 | ```
150 |
151 | ###### Click Callback
152 |
153 | Each `onClick` should be a callback, not an invoked function. We should
154 | have something like this `onClick={() => this.updateProbability(1)}`.
155 |
156 | Alternatively, you could rework the `updateProbability` function to
157 | return a function. In that case, you would want to bind
158 | `updateProbability` so that `this` is the appropriate context.
159 |
160 | ###### Missing Bind
161 |
162 | Because we are directly invoking `this.geigerValue` in the render
163 | function, we should make sure it is properly bound. Add the following
164 | to your constructor:
165 |
166 | ```js
167 | this.geigerValue = this.geigerValue.bind(this);
168 | ```
169 |
170 | ##### Usage
171 |
172 | This component could be used like this:
173 |
174 | ```js
175 |
176 | ```
177 |
178 | ### React – Contrast and Compare
179 |
180 | #### Prompt
181 |
182 | Other front-end frameworks and libraries exist. What are some examples
183 | of these, and how does React compare/contrast with those?
184 |
185 | #### Solution
186 |
187 | ##### jQuery
188 |
189 | Like React, jQuery is a library, not a framework. It is the most popular
190 | JavaScript library in use. It wraps up many common vanilla JavaScript
191 | functions and initially gained popularity because it is guaranteed to
192 | behave identically on any browser.
193 |
194 | A key contrast: the components rendered by React are a pure function of
195 | the React state, i.e. props and component state. Thus a React developer
196 | only has to think about the state of his app. On the other hand, jQuery
197 | primarily allows you to directly manipulate the DOM, meaning that it is
198 | up to the programer to keep the DOM in sync with the internal state of
199 | an app.
200 |
201 | ##### Vue
202 |
203 | Vue is another front-end library. Like react it uses a virtual DOM and
204 | composable components. Vue's virtual DOM is lighter weight than React,
205 | and Vue is significantly faster, however Vue's developer community is
206 | much smaller than React's, so Vue has a smaller ecosystem of libraries
207 | and plugins.
208 |
209 | ##### Angular
210 |
211 | Angular was initially released in 2009 and is maintained by Google and a
212 | community of developers. It is part of the MEAN stack: the MongoDB
213 | database, Express.js server, Angular.js, and Node.js.
214 |
215 | Angular is a framework, not a library like React, and implements a MVVM
216 | framework (Model-View-ViewModel). As a result, it offers perhaps more
217 | functionality out of the box than React. However, it also takes much
218 | more time to master and is criticized in some corners for its lack of
219 | flexibility. Angular 1.0 also struggled to handle larger amounts of
220 | data. With the release of Angular 2.0, its ability to render large
221 | amounts of data in the browser has increased. However, it still loses
222 | out to React in terms of performance.
223 |
224 | ##### Ember
225 |
226 | Like Angular, Ember is a framework and not just a library. It has a
227 | number of customizations that can be added to the app from the Ember CLI
228 | (an idea the Ember team took from Rails!), as well as built in testing
229 | tools. However, it doesn't have a particularly large core team so
230 | development is slow. The community, while vibrant, doesn't produce as
231 | many add-ons. Also, because Ember is a framework, it's harder to
232 | customize.
233 |
234 | ##### React Native
235 |
236 | React Native allows developers to write React apps in javascript and run
237 | them on mobile devices. It was released by Facebook and is also used by
238 | companies like AirBnB and Instagram. It is currently supported by iOS
239 | and Android. Microsoft also has plans to start supporting React Native
240 | apps on Windows devices.
241 |
--------------------------------------------------------------------------------