Enterprise Web Development

Lecture 1 slides

Web Development Frameworks

A Model-View-Controller framework is geared toward GUI development. It's a collection of design patterns to acheive code-reuse and a separation of concerns. It dates back to the 70s!

MVC architecture isn't always agreed upon; there is no strict definition. For example, does the view get its data pushed from the controller, or does the view pull its data directly from the model? Is the model in charge of validation, or is the controller? There are a lot of approaches, which is why there are so many MVC frameworks.

Why Use a Framework?

Choosing a Web Development Framework

Simple Model-View-Controller (MVC) PHP Example

Another PHP MVC Example

Apache Directives and Modules

Apache is free, open source web server software that hosts over 50% of websites worldwide (including this one). It's written in C and ported to most operating systems. It's a long-running process that typically responds to HTTP requests on port 80.

Apache is very extensible. It's usually configured with a local file called httpd.conf/apache.conf. This file uses settings called "directives" to configure functionality and add features.

Basic Apache Configuration

This is a very small selection of the most common and useful Apache directives:

There's a lot more! Don't be afraid to use them.

Creating self-signed certificates for SSL:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout local.example.com.key -out local.example.com.key.crt

My general philosophy on web servers: if the web server has a feature you need, use it instead of coding it in your web app. e.g. authentication, redirection, access control, error handling, etc. The web server is faster, more thoroughly tested, and more secure.

URL Routing and Dispatching

The first web pages were static HTML files. Introduce a scripting language like PHP and now the files serve dynamic content. Take is a step futher and dynamic content is served by files that doesn't even exist! Content is generated by MVC objects through a front controller. They use the URL components to determine how to generate the content.

Semantic URLs are less-cluttered URLs. Usually associated with RESTful APIs, they make it easier for frameworks to route and dispatch a resource.

Most web application frameworks use URL routing to map a request to a view/controller. The Front Controller Pattern is a common approach. Using mod_rewrite, all requests are redirected through a single file (like index.php) which parse the URL, and dynamically generates the page.

# Somewhere in your apache.conf file. This redirects all requests to index.php, 
# which will analyze, route, and dispatch the request.
RewriteEngine On
RewriteRule ^(.*)$ /index.php [L]

The first question you must ask when designing a router is: what will be URLs look like? Second, will I use dynamic or static routing? Dynamic means you will attempt to create the proper MVC objects based on URL components. Static means there's a mapping file with a list of allowed request URLs, each with a list of their MVC components.

mod_rewrite Front Controller example

Front Controller Dispatcher in PHP

Simple PHP URL Routing Example

Just a reminder when handling posts, use the POST/REDIRECT/GET pattern to avoid duplicate form submissions.

Composition vs Inheritance

Both help with code/class reuse. Most framework developers prefer composition over inheritance.

What's the difference? Inheritance is a class that extends functionality from a parent class at compile time. Composition is a class with member variables that are objects from other classes. It gains functionality runtime.

<?php
// inheritance
abstract class AbstractAnimal {

  protected 
$name;

  public function 
__construct($name) {
    
$this->name $name;
  }

  public function 
getName () {
    return 
$this->name;
  }

  abstract public function 
speak ();
}

class 
Duck extends AbstractAnimal {

  public function 
speak() {
    return 
"QUACK!";
  }
}

$alex = new Duck ("Alex");
echo 
$alex->getName() . ": " $alex->speak();
// Alex: QUACK!
?>

<?php 
// composition
interface AnimalInterface {
  public function 
speak();
}

class 
Animal {

  protected 
$name;

  
// object that implements the Animal interface
  
public $animal;

  public function 
__construct($name$animal) {
    
$this->name $name;
    
$this->animal $animal;
  }

  public function 
getName () {
    return 
$this->name;
  }
}

class 
Duck implements AnimalInterface {

  public function 
speak() {
    return 
"QUACK!";
  }
}

$alex = new Animal("Alex", new Duck());
// What makes this composition is $alex->animal->speak() will still work
// if a different animal that implements AnimalInterface is used. 
// Polymorphism without inheritance.
echo $alex->getName() . ": " $alex->animal->speak();
// Alex: QUACK!
?>

Composition follows a Strategy Pattern. That is, it enables an algorithms behavior to be selected at runtime.

Composition vs Inheritance, which to apply, and when.

Inversion of Control

Inversion of control (IoC) is a common framework pattern that gives object creation control to the caller. This makes software very flexible at runtime, because the caller can swap objects of a given interface. This is usually achieved with classes that use composition.

<?php 
// NOT inversion of control -- note the $connection object is being created in the code.
public function getUsers ($username$password) {
  
$connection = new PDO("mysql:host=localhost;dbname=test"$username$password);
  
$statement $connection->prepare("SELECT * from users");
  
$statement->execute();
?>

<?php 
// inversion of control -- note the $connection object is now being passed in.
public function getUsers ($connection) {
  
$statement $connection->prepare("SELECT * from users");
  
$statement->execute();
?>

Dependency Injection

Most web development frameworks use dependency injection. It's a very powerful pattern that is an eventuality of long-term projects.

Dependency injection (DI) is an implementation of inversion of control for resolving dependencies. Frameworks will commonly configure objects using a configuration file with XML/JSON/YAML etc. These are called DI containers (or IoC containers). The "injection" happens when the framework uses the configuration file to get values for class constructors and setters. Objects are created on the fly as needed, and instantiated with values based on the type of request. This puts an enourmous amount of control over your application in one place.

Dependency Injection Example in PHP

Dependency Injection in PHP Laravel

Composition, Inversion of Control, and Dependency Injection explained together.

Advantages of dependency injection:

Disadvantages of dependency injection:

Object Relational Mapping

Object Relational Mapping is basically an abstraction layer for saving/retrieving an object's state in a database.
The "mapping" is usually a class -> table, attributes -> columns.

Another slideshare ORM introduction specific to PHP.

Lots of framworks do this, because CRUD operations are so common. You typically don't even have to write SQL queries, because they are auto-generated by the framework. It's sort of like object serialization with the benefits of relational data queries. For example: you create a User object, and tell the framework "I want to persist this data", and it generates the queries, DAO methods, and table as static code for you!

<?php

// Example of a class and table equivalent

class User {
  
  private $name;
  private $email;
  private $password;

  /** methods, etc **/
}
?>

/**
TABLE USER
---------------------------
| name | email | password |
---------------------------
**/
          

Examples of ORMS:

Advantages of ORMs:

Disadvantages of ORMs:

PHP Laravel

PHP Laravel lecture slides

PHP Laravel lecture github repo

The Ruby Language

Ruby on Rails notes

Notes

The Python 3 Language (since it differs vastly from previous versions)

  • Dive into Python3
  • Python Flask notes

    TaskList App Example

    Advanced JavaScript Concepts

    Most of this section is based on JavaScript: The Good Parts

    Why learn JavaScript? As a web developer, you don't have a choice. But that's okay, because JavaScript is actually a really good language.

    Most JavaScript concepts that are considered advanced are centered around scope. Functions are the de facto scope delimeters. Nested braces don't create scope. For example, declaring a variable in a loop doesn't create new scope.

    for (var i = 0; i < 10; i++) {
    } 
    console.log(i); // i is <--- 10
    

    The most common use of JavaScript is adding client-side behavior to HTML. But, JavaScript is so much more than interacting with the DOM. It's a very elegant and expressive language.

    JavaScript is syntactically like C, but semantically like Scheme.

    Unlike most langauges, JavaScript is case sensitive. Variable names, methods, etc.

    function hello () {
    }
    
    // is different than...
    
    function Hello () {
    }
    
    

    JavaScript objects are associative arrays, augmented with prototypes. This is why JSON is both clean, and representative of JavaScript objects.

    Hoisting is how JavaScript deals with variable initialization. At runtime, it moves all variable declarations to the beginning of its scope (function). It's good practice declare all variables at the beginning of your functions.

    foo = "hello world!";
    console.log(foo);
    var foo; // <--- this gets moved to the top at runtime

    JavaScript has a single number type, it's a 64-bit float, same as Java's double. There is no separate integer type.

    NaN is "Not a Number" (the value returned when the result of an arithmetic operation cannot produce a normal result).

    + 'oops' // NaN 
    NaN === NaN // false (what?)
    typeof NaN === 'number' // true (WHAT?)
    

    NaN comes from the IEEE 754 standard for floating point arithmetic. It's a confusing value.

    All JavaScript characters are 16 bits wide. It was invented at a time when Unicode was a 16-bit character set.

    JavaScript does not have a character type. Make a string with one character.

    Strings are immutable. e.g. you cannot change a character within a string:
    myString = "abbdef"; myString[2] = 'c';

    var defines a function's private variables

    Things that are false:

    JavaScript has a bonus parameter available to functions when they are invoked: argument.

    var sum = function () {
      var i, sum = 0;
      for (i = 0; i < arguments.length; i+=1) {
        sum += arguments[i]; 
      }
      return sum;
    }
    
    console.log(sum(4, 8, 15, 16, 23, 42)); // 108
    

    JavaScript methods by default return undefined. If you are in an function and have nothing to return, return this as a best practice so the method can be chained with other method calls.
    var bob = new Kitten(); bob.setName('Bob').setColor('black');

    // define the class
    var Kitten = function() {
      this.name = 'Garfield';
      this.color = 'brown';
      this.gender = 'male';
    };
    
    Kitten.prototype.setName = function(name) {
      this.name = name;
      return this;
    };
    
    Kitten.prototype.setColor = function(color) {
      this.color = color;
      return this;
    };
    
    Kitten.prototype.setGender = function(gender) {
      this.gender = gender;
      return this;
    };
    
    Kitten.prototype.save = function() {
      console.log(
        'saving ' + this.name + ', the ' +
        this.color + ' ' + this.gender + ' kitten...'
      );
    

    JavaScript does not include any I/O, such as networking, storage or graphics facilities, relying for these upon the host environment in which it is embedded.

    JavaScript Objects

    Classes don't exist in JavaScript. But objects do!

    As mentioned, JavaScript objects are basically associative arrays.

    var person = {
      name: 'zaphod', 
      age: 42
    };
    
    console.log(person.name);
    // is the same as
    console.log(person['name']);
    

    Object Literals are objects created on-the-fly. They are a pair of curly braces surrounding zero or more name/value pairs.

    var empty_object = {};
    

    Objects are passed around by reference. They are never copied.

    Functions are objects. In fact, they inherit from Function.

    You can create objects with functions that look like constructors.

    // a "class" in JavaScript
    
    function Animal () {
    
        // Private property
        var alive=true;
    
        // Private method
        function fight(){ //... }   
    
        // Public method which can access private variables
        this.isAlive = function() { return alive; } 
    
        // Public property
        this.name = "Joe";
    }
    
    // There are lots of ways to create objects. Using "new" treats this function like a constructor; 
    // without new it just executes the function but doesn't return anything. The "new" value gives us a 
    // copy of the function.
    var obj = new Animal();
    

    The problem with the above example is it causes confusion. JavaScript doesn't do "class inheritance" like regular Java. It uses "object inheritance", which is called Prototype-based Inheritance.

    JavaScript Prototype-based Inheritance

    Most developers think of writing quick, small proof-of-concept code when they hear the word "prototyping". But in JavaScript, it means something else.

    In Javascript, prototypes are an OO inheritance concept. It can simulate many familiar class-based features, but is different at the core.

    Most OO langauges use "classical" inheritance. Classes inherit behavior, without any state, from the parent class, the moment it is instantiated. Prototypal inheritance inherits both state and behavior from its parent (aka prototype). If the parent changes at runtime, so does the child.

    Programmers argue Prototypal Inherhitance is simpler than classical inheritance, once understood. There are no interfaces, abstract classes, final classes, virtual classes, constructors, destructors, etc. There is only one type of abstraction: objects.

    There are two ways to create an object using prototypal inerhitance.

    Every JavaScript function has a prototype property (this property is empty by default), and you attach properties and methods on this prototype property when you want to implement inheritance. The prototype property is used primarily for inheritance; you add methods and properties on a function’s prototype property to make those methods and properties available to instances of that function.

    In prototypal inheritance, instead of defining the structure through a class, you simply create an object. This object then gets reused by new objects, thanks to the way that prototype chain lookups work. It is called the prototype object because it provides a prototype for what the other objects should look like.

    // Example editing a prototype property
    
    
    // creating a new object (remember, there are no classes in JavaScript. Functions behave like constructors.)
    function PrintStuff (myDocuments) {
      this.documents = myDocuments;
    }
    
    // We add the print () method to PrintStuff prototype property so that other instances (objects) can inherit it:
    PrintStuff.prototype.print = function () {
      console.log(this.documents);
    }
    
    // Create a new object with the PrintStuff () constructor, thus allowing this new object to inherit PrintStuff's properties and methods.
    var newObj = new PrintStuff ("I am a new Object and I can print.");
    
    // newObj inherited all the properties and methods, including the print method, from the PrintStuff function.
    // Now newObj can call print directly, even though we never created a print () method on it.
    newObj.print (); //I am a new Object and I can print.
    
    
    // If you create an object, and later change its parent prototype, it still inherits the changes.
    // That's because, like most things in JavaScript, inheritance is resolved at RUNTIME.
    
    
    // More interesting example of object creation and prototyping
    
    var circle = {
        radius: 5,
        create: function (radius) {
            var circle = Object.create(this); // This is cloning the circle object, and returning it.
            circle.radius = radius;
            return circle;
        },
        area: function () {
            var radius = this.radius;
            return Math.PI * radius * radius;
        },
        circumference: function () {
            return 2 * Math.PI * this.radius;
        }
    };
    var circle2 = circle.create(10);
    
    
    
    
    // Another way to do the same thing
    
    function Circle (radius) {
        this.radius = radius;
    }
    
    Circle.prototype.area = function () {
        var radius = this.radius;
        return Math.PI * radius * radius;
    };
    
    Circle.prototype.circumference: function () {
        return 2 * Math.PI * this.radius;
    };
    
    var circle = new Circle(5);
    var circle2 = new Circle(10);
    
    
    
    
    // You can change core objects if JavaScript is missing a feature you really need.
    // Adding a reverse method to the built-in String object:
    
    String.prototype.reverse = function() {
      var s = "";
      var i = this.length;
      while (i > 0) {
        s += this.substring(i-1,i);
        i--;
      }
      return s;
    }
    
    // Now ALL strings have the reverse method.
    
    

    JavaScript acheives private variables through closures (discussed later).

    Plain English Guide to JavaScript Prototyping

    JavaScript "this" Binding

    Most OO langauges have implicit binding. In JavaScript, binding is explicit.

    this in JavaScript is totally different than Java.

    In languages like Java, this refers to the current instance of the class. In JavaScript, the value of this is determined by the invocation context. this is all about scope at runtime.

    Every function in JavaScript inherits two methods that can manipulate scope: apply() and call().

    var a = { name: "Conrad" };
    var b = { name: "Sarah" };
    
    printName = function () {
      console.log(this.name);
    } 
    
    printName.call(a); // Conrad
    printName.call(b); // Sarah
    
    // apply() is identical to call(), but also lets you pass parameters
    

    JavaScript Anonymous Functions

    In JavaScript, functions are objects, so they can be passed around, and reassigned.

    a = function () {
      console.log("hello world!");
    };
    b = a;
    b(); // hello world!
    

    Functions can be dynamically declared at runtime. An anonymous function is a function without a name. It can be stored in a variable.

    Anonymous functions are a matter of style. Using them is never required; anywhere you could use them, you could define a separate normal function that accomplishes the same thing. Sometimes they are much more elegant. They are basically used to contain scope and be reusable.

    Anonymous functions are analogous to blocks in Ruby, and are used heavily as callbacks in JavaScript frameworks such as jQuery.

    // Lots of ways to use an anonymous function.
    
    
    // regular function named "hello"
    function hello() {
      console.log('world');
    }
    hello();
    
    
    // anonymous function stored in a variable called "anon"
    var anon = function() {
      console.log('I am anonymous');
    };
    anon();
    
    
    // self-executing anonymous function (those final parenthesis execute it)
    (function() {
      console.log('Im anonymous AND call myself');
    })();
    
    
    // self-executing anonymous function with a parameter
    (function(message) {
      console.log(message);
    }('foo'));
    
    
    // object created on the fly
    var Person = {
    };
    
    
    // anonymous function assigned to a method name in an object
    var Person = {
      sayHello: function () {
        console.log("hi");
      }
    };
    Person.sayHello();
    

    JavaScript Callbacks

    A callback function is a function that is passed as a parameter or returned from another function.

    A function that accepts a callback as a parameter or returns a function is called a "higher-order" function. So fancy.

    // simplest callback example of all time
    function a (b) {
      b();
    }
    
    var b = function () {
      console.log("hello world!");
    }
    
    a(b); // hello world!
    
    

    They are very important and common in JavaScript. This is because callbacks can be run asynchronously, which is useful in a browser.

    Callbacks allow you to compose big functions out of small functions. This makes code cleaner, and more reusable.

    var pets = [ 
      { name : "Fluffykins", species : "cat" },
      { name : "Jellybean", species : "dog" },
      { name : "Betsy", species : "dog" },
      { name : "Jaws", species : "fish" }
    ];
    
    // I want to get the dogs.
    // Typical for loop:
    var dogs = [];
    for (var i = 0; i < pets.length; i++) {
      if (pets[i].species === "dog") {
        dogs.push(pets[i]);
      }
    }
    console.log(dogs); // [ { name: 'Jellybean', species: 'dog' }, { name: 'Betsy', species: 'dog' } ]
    
    
    
    // Now I'm going to use JavaScript's built-in filter function: Array.prototype.filter.
    // It takes a callback as a parameter.
    var dogs = pets.filter(function(pet) { // filter performs an implicit foreach over pets
      return (pet.species === "dog"); // returns a boolean
    });
    console.log(dogs); // [ { name: 'Jellybean', species: 'dog' }, { name: 'Betsy', species: 'dog' } ]
    
    
    // Same thing, only the callback is broken out.
    var isDog = function (pet)  {
      return pet.species === "dog";
    }
    var dogs = pets.filter(isDog);
    console.log(dogs); // [ { name: 'Jellybean', species: 'dog' }, { name: 'Betsy', species: 'dog' } ]
    
    
    // **** AWESOME ***
    
    
    // Now lets talk about another higher order function called Array.prototype.map.
    // I want to get all the names of the animals from the objects in the pets array.
    
    
    // Using a for loop:
    var names = [];
    for (var i = 0; i < pets.length; i++) {
      names.push(pets[i].name);
    }
    console.log(names); // [ 'Fluffykins', 'Jellybean', 'Betsy', 'Jaws' ]
    
    
    // Using map
    var names = pets.map(function(pet) {
      return pet.name;
    });
    console.log(names); // [ 'Fluffykins', 'Jellybean', 'Betsy', 'Jaws' ]
    
    
    

    JavaScript Closures

    All JavaScript functions are closures, in the strictest sense. Usually a closure refers to a specific subset of functions that are interesting from a theoretical point of view.

    A closure is a nested function that is declared, used later, and "remembers" all the variables that were in its scope.

    A closure is a function that must have a free variable. If there's no free variable, it's not a closure.

    A free variable is a variable that isn't global, defined locally, or passed in to the function using it. A free variable is included from scope of the function's container (usually another function or object).

    If a function has a free variable, and that function is referenced outside it's parent scope, then that function just became a closure for that free variable. That free variable is now called an upvalue for the closure.

    // simplest closure example of all time
    var message = "hello world!";
    function a () {
      console.log(message); // notice message wasn't passed in 
    }
    a(); // hello world!
    
    
    // Note message changes after the function. A closure isn't reading a snapshot of "message",
    // but directly reading it at runtime. It has access to its outer scope.
    var message = "hello world!";
    function a () {
      console.log(message); // notice message wasn't passed in 
    }
    message = "hello galaxy!";
    a(); // hello galaxy!
    
    
    
    // Closure example using a nested function.
    // Free variables are not copied to the nested function, but are only referenced.
    function init() {
      var message = "hello world"; // <-- variable created by init() function
    
      function displayName() { // <--- inner function displayName(), a closure 
        console.log(message); // using variable declared in the parent function, a free variable
      }
      displayName();    
    };
    init(); // "hello world"
    
    
    
    
    // generic unit conversion function using closures.
    function makeConverter(toUnit, factor, offset) {
      offset = offset || 0;
      return function(input) {
        return [((offset + input) * factor).toFixed(2), toUnit].join(" ");  
      }
    }   
     
    var milesToKm = makeConverter('km',1.60936);
    var poundsToKg = makeConverter('kg',0.45460);
    var farenheitToCelsius = makeConverter('degrees C',0.5556, -32);
     
    milesToKm(10); //"16.09 km"
    poundsToKg(2.5); //"1.14 kg"
    farenheitToCelsius(98); //"36.67 degrees C"
    
    
    
    
    // Asynchronous closure
    
    function closureExample() {
      var i = 0;
      for (i = 0; i< 3 ;i++) {    
        setTimeout(function() {
          console.log('counter value is ' + i);
        }, 1000 * i);
      }
    }
    // counter value is 3
    // counter value is 3
    // counter value is 3
    
    // Why not 0, 1, 2? Because the loop finishes before the first setTimeout executes its contents.
    // Remember, i is a refernce, not a copy.
    
    
    // Now it works as expected.
    
    function asyncOperation(counter) {  
      setTimeout(function() {
        console.log('counter value is ' + counter); // counter is being closed over 
      }, 1000 * counter);
    }
    
    function otherClosureExample() {  
      var i = 0;
      for (i = 0; i < 3 ;i++) {    
        asyncOperation(i);
      }
    }
    
    otherClosureExample();
    
    // counter value is 0
    // counter value is 1
    // counter value is 2
    
    
    
    
    // Emulating private variables using closures.
    
    var counter = (function() {
      var privateCounter = 0;
      function changeBy(val) {
        privateCounter += val;
      }
      return {
        increment: function() {
          changeBy(1);
        },
        decrement: function() {
          changeBy(-1);
        },
        value: function() {
          return privateCounter;
        }
      };   
    })();
    console.log(counter.value()); // 0
    counter.increment();
    counter.increment();
    console.log(counter.value()); // 2
    counter.decrement();
    console.log(counter.value()); // 1
    

    Closures are useful for implenting the Module Pattern

    Angular.js

    Angular slides

    React.js

    Joey's in-class React examples

    JavaScript Graphing SVG & Raster

    At some point in your web development career, you will be plotting data graph on a web page.

    "I need a dashboard." -CTO. "I need reporting." -Customer. "I need monitoring." -Operations

    You probably have some websites that you regularly visit that has graphs. Use the inspector to figure out which graphing library they use.

    Data is the new Oil. This whole "Big Data" push is more useful with graphs.

    There is no shortage of graphing tools for the web. Both old and new.

    Many are server side. For example, JpGraph is a popular PHP graphing library. It plots data and generates a temporary image, like a JPG or PNG. Server side graphic libraries work, but aren't very interactive - because they are served as static images.

    Client side JavaScript graphing libraries are becoming more popular. They can be very interactive; mouse-over legends, "drill down" links, tool tips, animations, etc.

    Choosing a JavaScript graphing library depends on your needs.

    D3 stands for data driven documents. It's very flexible, and the most widely used. Has a learning curve.

    SVG stands for Scalable Vector Graphics. Unlike raster graphics (conceptually a bitmap), which represent a grid of pixels, SVG uses start and end points of curves and angles, and can be scaled without losing image quality. D3.js uses SVG. Most server-size graphic libraries use raster images.

    1. Download the graphing libary and include the js in your project.
    2. Read the docs on how to format the data for the specific graph. (Usually the toughest part.)
    3. Create a page with the raw data (JSON, CSV, etc) to supply the graph widget.
    4. Create the graphing widget that consumes the data.

    2000+ d3 examples!

    D3.js tutorial.

    Processing is a Java dialect for creating interactive data visualizations called "sketches". They create Java Applets, which are becoming rare thanks to mobile devices. Processing.js is a project that converts Processing sketches into JavaScript.

    The Canvas element initially introduced by Apple in 2004 for the WebKit rendering engine.

    HTML5

    HTML5 is the 5th revision of the HTML standard. It was finalized October 2014. HTML4 was standardized in 1997. That's 17 years! That's like 293 internet years. (That probably won't be on the final.)

    Browsers typically aren't a binary "I support/don't support HTML5". They support a collection of HTML5 features to varying degrees.

    It is MUCH MORE semantic.

    This means HTML5 is better suited for SEO, and accessibility (think screen readers). There is a whole spec on HTML5 accessibility called ARIA.

    Not meant to replace HTML4, but to enhance.

    HTML4
    
    <div id="header"></div>
    <div id="nav"></div>
    <div id="article"></div>
    <div id="figure"></div>
    <div id="footer"></div>
    
    HTML5
    
    <header></header>
    <nav></nav>
    <article></article>
    <figure></figure>
    <footer></footer>
            

    HTML5 deprecates very few tags (center, and a few others that are now handled in CSS). Also blink is gone too! :'( So you can still use div, span, etc.

    Browser adoption as been slow (because the spec has taken forever (mostly because XHTML was going to be the succesor for a while)). IE8 and earlier, FF2 and earlier are unsupported. There is current full support in Chrome and Opera, and most modern browsers.

    New HTML5 elements

    Most websites still use HTML4 only tags, (this one you're looking at). A List Apart is a good example of an HTML5 site. (Look at the source.)

    HTML5 has way cool new input types. color, date, range, etc.

    A native progress bar element.

    Ever notice how your smartphone sometimes changes the keyboard to include an @ on the default layout? That's because of the "email" input type.

    HTML5 offers limited client side validation. max, required, pattern, etc.

    HTML5 handles media better; audio, video, track, source, etc.

    The "type" attribute is no longer needed for HTML5 link elements. For example:

    <link href="file.css" rel="stylesheet" type="text/css"/>
    is now
    <link href="file.css" rel="stylesheet"/>

    The HTML <canvas> element is used to draw and contain 2d raster graphics, on the fly, via scripting (usually JavaScript).

    By default, canvas has no border and no no content, and is size 150px x 300px.

    Canvas is raster based, and is supported by pretty much all browsers except IE8 and older.

    Dive into HTML5 canvas.

    There isn't a good reason to use canvas for static content. Browsers are optimized to render <img>.

    Canvas can be used to replace flash and Silverlight for animations, and video.

    Mozillla HTML 5 Canvas Animations Tutorial

    HTML5 has a new way to store data on the client: Application Cache. It uses a manifest file and has a max of 5MB per domain. Look at the source of this page in the html tags to see the reference. It's used to make access to static content possible when the network is down.

    HTML5 has a few APIs, like geo location (with the users permission).

    CSS3

    CSS3 is the latest standard for CSS. It's completely backward compatible.

    CSS3 makes a lot of things possible that used to require JavaScript.

    HTML5 and CSS3 are often talked about together, because they both represent progress and more interactive browser capabilites.

    Unlike CSS 2, which is a large single specification defining various features, CSS 3 is divided into several separate documents called "modules". Each module adds new capabilities or extends features defined in CSS 2, preserving backward compatibility.

    Native rounded corners!

    Border images?

    2D rotate

    3D rotate

    Transitions

    I spin

    Enterprise Web Development

    There is no agreed upon definiton of "enterprise" software.

    To some it means software used by an organization rather than an individual, or that it uses "enterprise" frameworks, or that it's mission critical. Or even an arbitrary level of professionalism.

    For this class, it means:

    Many of these concerns are both development and operational (DevOps). Operations deals with keeping the network and server infrastructure up and running. Scalability is about architectural design with hardware limitations in mind.

    Service oriented architecture is a common strategy for being horizontally scalable.

    Service oriented architecture is the basis for cloud computing.

    Scalability: What is the effort required to increase capacity to handle greater amounts of load? How much additional traffic can it handle? How easy is it to add more storage? Was your software architected to be scaled horizontally, or is adding CPU and RAM the only way to add capacity?

    Caching: The speed of a website affects usage and user satisfaction, as well as search engine rankings, a factor that directly correlates to revenue and retention. As a result, creating a system that is optimized for fast responses and low latency is key. Caching at various levels is key.

    Monitoring: A scalable system must be manageable. This correlates to the ease of diagnosing and understanding problems when they occur.

    Fault tolerance: For some of the larger online retail sites, being unavailable for even minutes can result in thousands or millions of dollars in lost revenue, so designing their systems to be constantly available and resilient to failure is both a fundamental business and a technology requirement. Guaranteed uptime is measured in the number of 9s (i.e. 99.9999% uptime)

    Internationalization and localization: Systems whose user base spans multiple countries must deal with various economies and cultures. This includes languages, currencies, timezones, and even spellings within the same language. Taking a site global means making assumptions about how the rest of the world works. Things as simple as time (and more time), names, color, geography, or addresses shows how quickly things get complicated.

    Compliance to regulations: Government systems are typically required to adhere to accessibility regulations. e-commerce sites are usually PCI compliant to store card holder data. Auditing all activities for legal reasons becomes a requirement.

    Security: The more public and successful your site, the more attractive it is to exploit. The reputation of a company is tarnished forever after a security breach. This translates to loss of revenue.

    Testing: programmers are notoriously bad at testing their own code. However, they are responsible making their code testable. This means writing their code in such a way that it can be tested as discrete units -- which is another reason modular code using the "Single Responsibility Principle" is a good thing. Modular code lends itself well to unit tests. There are various approaches to testing, depending on the goal: unit testing, smoke testing, usability testing, integration testing, regression testing, etc. Even Test Driven Development, where developers write the tests before they write the code to be tested.

    Scaling software means company growth. Hiring additional staff necessitates increased communication, coordination, and competing ideas and priorities. Growth is a good thing, but brings baggage. Scaling the organization is something that cannot be ignored, and according to Conway's Law, the way teams are organized has a dramatic effect on software architecture.

    Profiling and Caching

    Where at the bottlenecks in your code? How do you find them? (Hint: it's not always where you think it is.)

    When you start dealing with large amounds of data, performance becomes an important issue.

    PHP has an extension called xdebug. You can set it to output cachegrind files and visualize where your code performance using Cachegrind.

    Debuggers and profilers are great ways to find relative execution speeds and frequency. However, these tools maintain state of every variable and execution path, and severely impact the performance of your code. They can't be left on for a legitimate a load test, or production. Performance metrics must be gathered using lightweight techniques.

    A common approach to gathering metrics in a production environment is to have a global metrics object that accumulates execution times per method and counters during the lifecyle of a request, then dumps the results to a file or database. These metrics can be slurped up visualization software like Splunk.

    Many performance issues can be mitigated by in-memory caching.

    Memcached is an open-source general-purpose distributed caching memory system.

    Serves as a quick read/write of data, but not a database replacement (caching is not storage).

    Memcache is used by Reddit, Facebook, Twitter, Wikipedia, YouTube, and thousands of other websites.

    It's an in-memory key-value associative array that runs as a daemon process.

    It's a multi-threaded server that reads/writes via a TCP/UDP socket.

    Rule of thumb: cache everything that is slow to fetch, query, or calculate.

    // common pattern for caching
    
    public function getData () {
      $cacheKey = "data";
    
      // check the cache
      $data = $this->cache->get($cacheKey);
      if (empty($data)) {
    
        // expensive get data operation 
        $data = $dao->getData();
    
        // set the cache
        $this->cache->set($cacheKey, $data);
      }
      return $data;
    }
    
    public function setData ($data) {
      $dao->setData($data);
      $cacheKey = "data";
    
      // delete the cache because the data has changed
      $this->cache->delete($cacheKey);
    }
    
    

    $this->cache->set($cacheKey, $data, 60) takes an optional third parameter: expiration in seconds. Default is that it never expires.

    Cache expiration: how long should something stay in cache? Timer? When the data changes? If you aren't sure, follow the Five-minute rule.

    Cache expiration strategy: how much data needs to be cached? How often is it going to be used? How often does it change?

    Data that doesn't change frequently should be cached. User preferences. Daily reports. Lookup tables like currency exchange rates.

    Large loads of data are good to cache for performance, but comsume RAM. There is always a trade-off.

    Data in the cache is "stale" if it is out of date (i.e. the source has changed).

    Memcache has a limit of 1M per key.

    Memcache can replicate for high availability, and distribute cache across n nodes.

    Memcache can store any type of data. Strings can be read by other heterogenous systems.

    Systems can become so dependant on memcache that restarting it can cause severe performance degredation until the cache fills up. An empty or stale cache is called a "cold cache". To negate these effects, caches can be "warmed" by filling them with data before the system uses the cache.

    Monitoring

    Chris Galli lecture slides

    Browser performance & Reducing Assets

    How fast your page loads is important. You should make it load and render as fast as possible. Most tricks are easy to implement.

    Generally, each of these performance tips shave off a few percentage points of the overall page load. You must implement many of them to make a significant difference.

    In the previous section we discussed memory caching. The browser itself still must render the page, and if your DOM is full of resources to cobble together, it can make the page feel slow and clunky.

    An "asset" is an individual resource the browser must request and add to the rendering process. Images, CSS, JavaScript, HTML, video, audio, custom fonts, flash, etc.

    Use the network tab in the inspector see how long a page actually takes to load. Note the website below took 6.48 seconds and pulled 292 assets. That is a lot.

    The browser inspector is your best tool for profiling asset performance.

    Other online analyzers include Googles Page Speed and Yahoos extension YSlow.Page Speed and YSlow give a "grade" and suggestions to increase performance.

    Chrome has a built-in mobile device emulator and network throttler. This is useful because most web developers use localhost, and do not see performance degredation until after they deploy.

    Reduce the overall number of requests. Socket overhead is expensive. Some resources can be combined into one file at deploy time. Images, JavaScript, CSS, etc.

    Image size: Make your images as small as possible while still looking good. Generally, you should not be resizing images with CSS, but with something like Photoshop. Even when using preview thumbnails -- create two sizes of the same image. This is furthur complicated by user-supplied images. Sites like Facebook process uploaded images and shrink them to optimize page loads and storage.

    Sprites: Combine small images with the same dimensions into one larger image, and using the CSS background-position property to show the correct segment. This works esspecially well with thumbnails, icons, buttons, etc.

    This is one image.

    Compression: to improve transfer speeds and bandwidth utilization, lossless compression of HTTP data can be done on the server at request time. mod_deflate or mod_gzip can reduce the size of a plaintext file by 70% or more. Compression is more CPU intensive, but gives more throughput since network is in the bottleneck for web sites. The client can send request headers like Accept-encoding: gzip to tell the server it can decompress requests.

    <IfModule mod_deflate.c>
      # Turn on output compression for everything but images. Why? Images are already compressed.
      SetOutputFilter DEFLATE
      BrowserMatch ^Mozilla/4 gzip-only-text/html
      BrowserMatch ^Mozilla/4\.0[678] no-gzip
      BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
      SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png|swf)$" no-gzip dont-vary
      Header unset Vary
    </IfModule>
    

    JavaScript and CSS Minification: JavaScript source files are transfered to the client where they are interpreted. This includes comments, whitespace, large variable names, etc -- things the interpreter does not care about. JSCompress, and JSMin solve these problems. The do not compress, but strip out superfluous characters.

    // JavaScript
    
    function sum(num1, num2) {
      return num1 + num2;
    }
    
    // minifies to...
    
    function sum(A,B){return A+B;}
    
    
    
    
    /* CSS */
    /* Layout helpers
    ----------------------------------*/
    .ui-helper-hidden {
      display: none;
    }
    
    /* minifies to... */
    
    .ui-helper-hidden{display:none}
    
    

    JavaScript to the Bottom: JavaScript files are typically linked in the <head> section of the DOM. This is actually bad practice, as JavaScript blocks page rendering while the JavaScript is being loaded and executed. Linking JavaScript should be put at bottom of the DOM, right above the closing </body> tag. JavaScript code is usually wrapped in an onLoad event, and must wait for the page to finish loading anyway.

    <head>
      <!-- Non-javascripty stuff -->
    </head>
    <body>
      <p>Lorem ipsum dolor sit amet.</p>
    
      <!-- JS -->
      <script src="script.js"></script>
    </body>
    

    Browser caching: Response headers such as Last-Modified, expires, or an Etag give hints the browser on how long to cache data. Use Apache to encourage the browser to cache even longer.

    <IfModule mod_expires.c>
      ExpiresActive On
    
      <FilesMatch "\.(jpg|jpeg|png|gif|svg)$">
      ExpiresDefault "access plus 1 month"
      </FilesMatch>
    
    </IfModule>
    

    Keep CSS and JavaScript out of HTML: JavaScript and CSS are cached by the browser. This reduces transfer size of content.

    CSS Preprocessors: Pre-processors like SASS, Less, Stylus are similar to JS minifiers, and they also combine CSS files into a single file.

    Pagination: Large tables of data or images take a long time to load and render. Pagination is technique of dividing the data into discrete pages. Search engine results like Google, e-commerce products pages like Amazon, and 'infinite' scrolling like Facebook (which is techincally a separate approach to solve the same problem) are common and can be tricky to implement. 'Previous' and 'Next' buttons, performing separate database queries for each page (or pulling it all into memory depending on the number of rows), how many rows total, and how many pages total all should be implemented.

    Best Practices for Increasing Website Performance

    Web Assets - Tips for Better Organization and Performance

    Browser Diet

    i18n & L10n

    You want your website to have an international audience? It's hard.

    Public websites are available globally the instant they're deployed. If you want an international audience, you must cater to their preferences.

    Internationalization is the process of developing your application in such a way that it can be localized for languages and cultures easily. Separation of content from formatting. For example: swappable language files. Gathering device data about locale.

    Localization is targeting a specific locale. You typically have a collection of resource files for a locale.

    Web frameworks have various ways for dealing with internationalization.They revolve around organization and templating.

    i18n & L10n stands for Localizaion and Internationalization. See for yourself.

    Use HTTP request headers to detect locale based on the IETF language tag.

    What to localize?

    Best practices for internationalization:

    Character Encoding

    "The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)" by Joel Spolsky

    Character encodings: binary glyphs to represent characters in an alphabet. The browser is actually interpreting binary data to render these very letters, which are converted to vector graphics.

    The first character encoding was ASCII - 1 byte per character. The original problem with ASCII comes down to how many characters can you represent with a single byte. (Enough for Latin alphabets - not so much for others.) Remember, this has to include upper and lower case letters, punctuation, numbers, and other control characters like newline, tab, etc.

    Latin based alphabets contain relatively few letters (English/French/German = 26 letters, Spanish/Danish/Norwegian = 29, Portuguese = 23 letters). The Cyrillic alphabet (Russian, Slavic) = 33 letters. The Arabic alphabet contains 28 letters. Hebrew has 22 letters and no casing.

    Asia had to go and make things hard. There are roughly 2,000 Kanji characters used in Japan. There are many more that even native speakers do not know. To be fair, some Asian countries have reasonable alphabets. Tibetan has 30 letters. The Devanagari alphabet used in India and Nepal (languages like Hindi and Sanskrit) have 46 letters.

    The total number of Chinese characters from past to present remains unknowable because new ones are developed all the time. One modern dictionary lists 106,230.

    There have been many attempts to unify character encoding standards to encompass all alphabets. The most successful is Unicode.

    Unicode contains over 120,000 charcters covering 129 modern and historic scripts. Many modern programming langauges use it by default: Java, .NET, Python, etc. Some bolt it on after the fact: PHP, etc.

    Popular encodings include UTF-8 (the most widely used) and UTF-16.

    Problems occur when moving data from one system to another. Particularly the database to the server-side langauge to the browser.

    As a web developer, it is your job to be aware of the character encodings used by various systems in your application.

    Be explicit in your response header.

    Content-Type:text/html; charset=UTF-8

    Almost every modern browser supports UTF-8.

    Unit Testing

    As a developer, you need to champion good software practices, including unit testing. Enterprise companies should always be unit testing.

    Unit testing is for individual components rather than the system as a whole.

    Responsibility of the person writing the code.

    A class is a good definition of a "unit". Test each of the methods.

    Most web development frameworks have tools for unit testing.

    Ultra-simple unit test example using phpunit

    <?php
    class Calc {

      public static function 
    add ($a$b) {
        return 
    $a $b;
      }
    }

    <?php 
    require_once "Calc.php";

    class 
    CalcTest extends PHPUnit_Framework_TestCase {

      public function 
    testAdd () {
        
    $c Calc::add(55);
        
    $this->assertEquals(10$c);
      }
    }

    >phpunit CalcTest.php
    PHPUnit 4.8.18 by Sebastian Bergmann and contributors.
    
    .
    
    Time: 76 ms, Memory: 11.75Mb
    
    OK (1 test, 1 assertion)
    

    Usually there's a script that can run all unit tests, and tools that track code coverage, and alert you about broken tests. These are called Continious Integration servers, like Jenkins.

    Unit test code coverage report:

    If the class has dependencies like a database, create "mock" dependencies that give canned responses.

    Advantages of Unit Testing:

    Unit tests should be:

    My code alread works, why should I write tests? Answer: refactor insurance. You WILL change your code.

    You test your code anyway. Instead of testing via the command line, use unit tests.

    What about GUIs in browsers? Answer: that's not really unit testing, but it can still be automated with tools like Selenium. It automates mouse clicks, detects HTTP response codes, etc.

    Test-driven development means writing the unit tests first. Some people swear by it. Others, not so much.

    Other types of testing:

    Authentication

    Almost every website has authentication -- to prove you are who you say you are. Authorization is a related but separate concept: are you allowed to do something. Identity vs rights. Usually authorization follows authentication.

    Web developers must deal with various means of authentication, whether implementing it on their own projects, or using authentication schemes of 3rd party APIs.

    Examples of authentication schemes:

    Browsers sometimes pop-up a native login prompt. This means the website is using HTTP Basic Authenticaion.

    Using HTTP Basic Auth

    HTTP Basic Auth example

    Interesting discussion about HTTP basic auth security.

    Each authentication scheme has its own set of pros and cons. Usually a balance of convenience and security. For example: Basic HTTP Auth is easy to implment, but doesn't manage logging out.

    Two-factor authentication is more secure, but takes longer.

    Client certificates use asymmetric keys, which make it extremely secure. But a PKI is a pain to manage, and confuses many developers.

    How do I pick an authentication scheme?

    Other considerations:

    Guide to Authorization - OWASP

    Additional reading on web authentication schemes