Skip to content

Instantly share code, notes, and snippets.

@dhruvio
Last active August 17, 2016 06:25
Show Gist options
  • Save dhruvio/9b9c98014fdb1ec7f9c5be481d2cbafb to your computer and use it in GitHub Desktop.
Save dhruvio/9b9c98014fdb1ec7f9c5be481d2cbafb to your computer and use it in GitHub Desktop.
bloc_technical_assessment

JavaScript

The bug you've encountered is a tricky one, and it has to do with something called Variable Scoping and Closures. This means that when you define a variable using var, it's important to understand where you can refer to its value, and when its value changes.

What's happening in your code is that the entire for loop is running to completion before any of the buttons are clicked. That means that by the time any of the buttons are clicked, the btnNum variable has a value of 3. Why 3? Because the loop increments btnNum to the first value that btnNum < prizes.length equates to false. So, even though you define the onclick handler each time the loop iterates with a different value for btnNum, the alert(...) statement only runs at the end of the loop once btnNum is 3, whenever a button is actually clicked.

var prizes = ['A Unicorn!', 'A Hug!', 'Fresh Laundry!'];
for (var btnNum = 0; btnNum < prizes.length; btnNum++) {
  document.getElementById('btn-' + btnNum).onclick = function() {
    // btnNum is always 3 here since this function is called
    // when the button is clicked, after the loop has finished running completely
    alert(prizes[btnNum]);
  };
}

So, to solve this bug, we need a way to keep track of btnNum at a later point in time, so a button click alerts the correct prize to the user. We can do this by creating something called an Immediately-Invoked Function Expression, or an IIFE. An IIFE is a function you define that you run straight away. This gives you the advantage of tracking variables inside its scope. In our case, we are going to create an IIFE that returns another function that will handle each button's click event, keeping track of the correct value for the btnNum variable over time.

Note: Variables declared with var aren't tracked in the same way for for loops (this is called "variable hoisting," which means these variable definitions are stuck to the nearest function scope only).

Here's what a working solution looks like:

var prizes = ['A Unicorn!', 'A Hug!', 'Fresh Laundry!'];
for (var btnNum = 0; btnNum < prizes.length; btnNum++) {
  // the button's onclick handler is the function returned by IIFE()
  document.getElementById('btn-' + btnNum).onclick = (function IIFE() {
    // we are now inside the IIFE's scope
    // whatever variables defined in here will stick around
    // we define btnNumCorrect to keep track of btnNum at this point in time
    var btnNumCorrect = btnNum;
    // we the return function that handles the onclick event
    // this handler refers to the prize at index btnNumCorrect
    return function onClickHandler () {
      alert(prizes[btnNumCorrect]);
    };
  })() // <-- see how we are immediately running the function?;
}

IIFEs are fairly common in JavaScript programming, primarily because they are concise ways of creating a function scope (like we do above).

SQL

A SQL injection attack occurs when you don't protect the ways you query your database in your back-end code.

When you build a back-end API, you normally write functions that will return data from a database. For example, an HTTP GET request to http://yourapp.com/api/posts would return a list of blog posts. To get those blog posts, your back-end code might query a posts table in a database using SQL:

database.runSQL("SELECT * FROM posts;"); // SELECT * FROM posts;

Similarly, you may be offer functionality to search blog posts by an author's name using a query string at the same URL. For example, an HTTP GET request to http://yourapp.com/api/posts?author=felix would only return blog posts written by Felix. It would do this by querying the posts table again with a condition that the author column has the value felix:

// assume your code binds a variable, "name", to the value of "author" in the querystring
database.runSQL("SELECT * FROM posts WHERE author=\"" + name + "\";"); // SELECT * FROM posts WHERE author = "felix";

Imagine a hacker decides to run a HTTP GET request with some malicious SQL in the querystring to the following URL: http://yourapp.com/api/posts?author=felix"; DROP TABLE posts; ". This is very dangerous, because, if executed, this would cause your own back-end code to destroy the entire posts table!

// assume your code binds a variable, "name", to the value of "felix\"; DROP TABLE posts; " in the querystring
database.runSQL("SELECT * FROM posts WHERE author=\"" + name + "\";"); // SELECT * FROM posts WHERE author = "felix"; DROP TABLE posts; ";
// this results in 3 SQL statements:
// 1. SELECT * FROM posts WHERE author = "felix"; -> returns the posts whose author is "felix"
// 2. DROP TABLE posts; -> destroys the posts table
// 3. "; -> results in an error

The best way to prevent this from ocurring in your applications is to validate and escape all strings that are inserted into SQL statements that are run on your application's database. This means that you check each string for any SQL, and escape, or remove, it before inserting it into a query (or, even better, respond with an error). There are libraries available for the most popular programming languages that will help you escape any strings that may contain malicious SQL commands.

Angular/jQuery

The main difference between a framework and jQuery is that a framework, like Angular, helps you build all aspects of a web application according to a certain convention. Whereas jQuery is a collection of functions that act as utilities ― they don't define how you should build your web app, rather make certain, narrow aspects of front-end development easier.

For example, imagine you're building a blog. Without a framework, and just using jQuery, you will certainly be able to accomplish your task, but your codebase will likely grow unweildly without any concrete code conventions, especially at an early stage in your career as a developer. However, building it with a framework will enable you to think logically about your program.

A common design pattern employed by front-end frameworks is Model, View, Controller, or MVC. A framework like Angular or Backbone will give you the basic functions and classes to build an app with MVC. Continuing the example of a blog, you may represent a blog post as a Model. This allows you to reason about all blog posts in a particular way. For example, a BlogPostModel may expect all blog posts to have a name, publishDate and author. Similarly, you may define a View to render a particular blog post by reading the data inside an instance of this model. MVC is one example of how a framework uses an architectural convention to make it easier for us to reason about an application. Beyond this, frameworks also offer useful functionality like routing to manage web app URLs, and building Collections to manage lists of Models.

Do note that You may use jQuery alongside a framework for utility functions, like fetching data from a server, or manipulating DOM elements. Also, some front-end frameworks even depend on jQuery for its may useful utility functions!

More recently, front-end development has been embracing Functional Reactive Programming, or FRP. This approach is different from traditional MVC applications, and tends to present itself only as view libraries, like React.js. A view library, like React, is not a framework. It is solely a way of reasoning about how data should be displayed in the browser. It does not take into account how to store and access data, or how to separate your business logic. For most web applications using FRP, it is recommended to spend more time thinking about how you would like to organise these aspects of your application than if you used a holistic framework.

Algorithms

Big O notation is a way to reason about the performance, or time complexity, of an algorithm. It allows us to describe the time required for an algorithm to finish compared to the size of its arguments. Imagine you have an algorithm that counts the number of times a particular item exists in an array:

function howMany (array, value) {
  var count = 0;
  for (var i = 0; i < array.length; i++) {
    if (array[i] === value) {
      count++;
    }
  }
  return count;
}

To calculate the Big O notation for this algorithm, we need to figure out how many "steps" it needs to complete for each item in the array it is passed. For each item, howMany takes the following steps:

function howMany (array, value) {
  var count = 0; 
  for (var i = 0; i < array.length; i++) { // step 1: manage the the index of the loop
    if (array[i] === value) { // step 2: test the equality of the array item to the value argument
      count++; // step 3: (optionally) increment count
    }
  }
  return count;
}

It takes a maximum of 3 steps for each element in the array argument for the algorithm to complete. So, if the array had 20 elements, it would take 3 * 20 = 60 steps to complete the algorithm. If the array only had one element, the algorithm would take 3 * 1 = 3 steps to complete. Do you see the pattern?

In this example, the formula that describes how many steps required for an array of length n is steps = 3n. In Big O notation, we generalise this even further by removing any constants and scalars. So, this algorithm has a time complexity of steps = n, or O(n). We perform this generalisation because the job of Big O notation is to describe the performance of an algorithm, not to give us a precise way of measuring it.

Generally, most algorithms have a time complexity of O(n). However, some others have a time complexity of O(n^2), or O(log n).

CSS

You are facing a common quirk with CSS: parent elements of only floated elements collapse unless the floats are "cleared". For the CSS to style the page correctly according to the design, there need to be three changes to existing style blocks, and one addition of a style block:

Updated style block: .pricing-tiers

Adding the rule display: inline-block forces the element to clear the floats of its children, respecting their heights.

Updated style block: .pricing

Adding the rule text-align: center centers the .pricing-tiers element, now that it is displayed as inline-block.

Updated style block: .tier h1

Remove the margin-top to match the PSD.

New style block: .tier ul

Added some list and alignment rules to match the PSD. Note that the list-style-type rule manges the bullets of an <ul> element. We have set the value of that rule to none to remove the bullets. Similarly, we have removed the margin and padding for the list. We have also set the text alignment to left to override the text-align: center rule that is inherited from .pricing.

The working CSS can be found below:

header {
  width: 100%;
  height: 60px;
  background-color: #333;
}

.pricing {
  width: 100%;
  padding: 20px;
  background-color: tomato;
  text-align: center; // new rule
}

.pricing-tiers {
  width: 960px;
  margin: 0px auto;
  background-color: #ddd;
  display: inline-block; // new rule
}

.pricing-tiers .tier {
  width: 260px;
  margin: 20px;
  padding: 10px;
  background-color: white;
  float: left;
}

.tier h1 {
  font-family: "Helvetica", sans-serif;
  font-weight: bold;
  font-size: 2em;
  margin-bottom: 20px;
  margin-top: 0px; // new rule
}

.tier ul { // new style block
  list-style-type: none;
  text-align: left;
  margin: 0px;
  padding: 0px;
}

.pricing-tiers > .tier:last-child {
  margin-right: 0px;
}

Rails

I have limited experience with Ruby and Rails, so let me reach out to another mentor with your question and get back to you with a useful answer. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment