Cheat Sheet: Twelve-Factor App

The Twelve Factor App

About

  • Methodology for building SaaS apps
  • By Heroku
  • Well-written (concise, plain language)

Goals

  1. Minimise time and cost for new developers to join a project
  2. Platform-agnostic code for maximum portability (i.e. cloud)
  3. Minimise divergence between dev and prod code, enabling continuous deployment for maximum agility
  4. Minimise scale up cost

Factors

  1. Codebase: Single repository per app (e.g. GitHub), deployed on various machines (e.g. staging, prod).
  2. Dependencies: All dependencies are explicitly declared in a packaging system (e.g. Bundler, Chef) and isolated from the wider system when the app is run.
  3. Config: Variables (i.e. values that vary between deploys, credentials) stored as environment variables (no code change, can’t be checked in to repo, OS agnostic, cleaner, scalable).
  4. Backing Services: All external dependencies (e.g. database, SMTP) are treated as attached resources, able to be swapped out without any code changes
  5. Build, Release, Run: Strictly separated, versioned, immutable, one-way process from code repository to build (most moving parts, complied and ready for execution), to release (build combined with a config), to run (fewest moving parts, launch in environment).
  6. Processes: Executed code is stateless and shares nothing — all data is stored in a stateful backing service (e.g. database, S3) although temporary storage can be used (e.g. memory, disk), but never depended upon.
  7. Port Binding: App is completely self-contained and provides its own webserver as a dependency — the only responsibility of the environment is binding to a port to serve requests.
  8. Concurrency: More smaller first-class citizen processes assigned to different process types working independently (collectively referred to as the process formation) to maximise scalability
  9. Disposability: Processes should start quick, shut down gracefully, be robust against sudden termination (e.g. hardware failure), and can be started or stopped at a moment’s notice.
  10. Dev/Prod Parity: Deploy hourly (time gap), coders also deploy (personnel gap), dev and prod environments are as similar as possible (tool gap) — including backing services (i.e. no developer shortcuts such as lightweight database via adapter)
  11. Logs: All running processed write to stdout captured and collated by the environment (e.g. Fluent, Papertrail) for tailing, indexing, graphical representation or analysis.
  12. Admin: Scripts should be checked into the codebase and executed remotely on the intended environment.

References

REA Tech Blog Scribbles

About

Just going through REA’s blog in no particular order as of September 15, 2016.

Getting Shit Done

Well-written: http://rea.tech/getting-shit-done/

What prevents us from “Getting Shit Done” is the last time we got shit done.

Pair programming lessons

  • There is only so much we can learn by watching someone else type
  • Driving helps us gain confidence as a member of the team and feel comfortable working with our pair
  • It gives us a sense of ownership
  • The fastest way to feel comfortable making mistakes, is to do it while someone is watching
  • Breaks comfort zones (less slacking, pushed to learn more)
  • Take breaks
  • Be prepared to say “I don’t know”

Why team managed infrastructure makes sense

  • Conway’s Law states that as an engineer you inevitably create a system that has the same structure as that of your organization.
  • Increases autonomy, responsibility, ownership, satisfaction and skills
  • Developers become dev-ops and support 24/7, incentivized not to make mistakes
  • Anyone in team should be able to deploy to production at any moment
  • Teams free to choose their own solutions, but should communicate/share with other teams
  • Some holistic solutions/standards will need to be adhered to by teams as deemed necessary

Category Theory

http://rea.tech/how-we-used-category-theory-to-solve-a-problem-in-java/

The Six QA Hats

tmp

Micro services, what even are they?

  • Different intent that SOA. SOA describes the organisation business logic, micro services describe the services themselves
  • Should do one thing well (narrow responsibility), have a small codebase (rewrite and redeploy within 2 weeks) and can be written in any language (cross-cutting logging and monitoring)
  • Mitigates bad design by restricting to a small service
  • More complexity in overall architecture, responsibilities and data integrity (scattered databases!)

Micro services are just tiny, focused SOA services. Too many micros and you push the complexity from the codebase to the architecture (contracts, responsibilities, data integrity). Like most things, use experience and common sense to do what’s right for a project.

A microservices implementation retrospective

What is the right size for a microservice? Varies between projects — balance between complexity (lots of repos, builds, clusters), maintainability (shared functionality, code) and the traditional benefits of SOA.

  • REA template projects
    • Logger (aggregation and rotation configs)
    • HAL (index and health check) and HAL Browser gems for exposing links between resources (i.e. RESTful HATEOAS)
    • Sample environment variable, database connection, async job, deployment config and monitoring
  • Non-blocking, idempotent (i.e. calling repeatedly is not harmful) APIs exposing meaningful events
  • Pact for contract testing
    • REA-developed open-source Ruby gem
    • Enables CDC (Consumer Driven Contract) testing (i.e. providers list set of endpoints, consumers inform provider of what services/data being used). Suited for when you control the provider and consumer.
    • Used for unit tests and mocks only, not ‘real’ integration testing
    • Checks consumer and provider contracts are in sync using a generated-then-shared pact file
  • Data integrity through idempotent job retries, job monitoring, change events triggering retrieval of current data, clear source of truth systems, unidirectional data flow (i.e. one-way sync).
  • Aggregated logging across many modules through Splunk (aggregation) and Nagios (monitoring). New Relic could also have been adopted.

Personally I’m not currently a huge fan of hyperlinked resources (i.e. HAL). They add extra weight to responses which 99% of the time will be ignored as users don’t tend to browse JSON and developers tend to read the documentation. Also, endpoints rarely change so additional calls for dynamic support are inefficient. My preference is RESTish or EBTH (everything but the hyperlinks).

Distributed Agile — Extreme Communication

  • Email is not the primary source of communication (face-to-face, video conf, IM)
  • Always-on video conferencing for offsite teams (China)
  • Remote pairing
  • Virtual card walls, physically replicated

Really interesting that REA needs so much development power that they need to outsource, which is never better except for cost-cutting. Pioneering the new global workplace I suppose!

Feeling Validated – A different way to validate your input

  • Validation requirements constantly change = refactoring
  • Use a Validation abstract class that only has two concrete subclasses: Success and Failure (with message)
  • Chain validation using flatMap. It will only continue to the next validation if passed the previous validation (otherwise map is empty) — and eventually returns a Success object.
validateInput(Map("postCode" -> "3121"), "postCode")
.flatMap(postCode => postCode.parseInt.leftMap(nfe => "post code must be a number"))
.flatMap(postCode => postCodeLookup(postCode).toSuccess("not in a valid area"))

For comprehensive validation, add metadata (i.e. annotations, directives) to elements and auto-validate.

The abject failure of weak typing

  • Ruby play-dough typing
  • Types are a proposition (i.e. assertion) applied by the compiler and known up-front. Implementation is it’s proof.
  • Tags are runtime type information (e.g. string, array, map) used by dynamic languages
  • Dynamic languages are actually unityped, not untyped
  • “Don’t write software that isn’t broken; write software that can’t be broken.”
  • “It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.”
  • Algebraic Data Type (ADT) are an abstract set of ‘objects’ and their operators. Very flexible objects that can return many types and apply functions depending on type. Objects with finite possibilities — a set. Still don’t really understand…!
  • Nulls
    • Ticking time bombs of NullPointerExceptions
    • Employ default values (e.g. “”, 0) or a safe Null object (that can respond in a sensible way)
    • What does “initialised piecemeal” mean?
    • Write immutable objects initialised in the constructor (to avoid null objects)
    • Java 8 Optional class, which checks for null and can handle missing methods
  • Exceptions
    • Don’t throw exceptions unless unavoidable
    • Checked exceptions are widely despised and frequently ignored (unsubstantiated)
    • When a result could be success or failure, use an Either or Validation (Success/Failure) object instead
    • Define your own ADT
  • Primitives
    • Possible astronomical number of values (e.g. integers). How to test all possible values?
    • Strings are vertitile and often used wrongly. Should only be for unstructured free text, not anything that has a constraint or structure (e.g. name, URL, email).
    • If there are a finite number of possibilities, used an ADT
    • Use wrappers to encapsulate the structure and make it impossible to create invalid variables. Can also be used to normalise as well.

References

Consumer-Driven Contracts: A Service Evolution Pattern

ConsumerDrivenContracts

About

Reading up on Pact for contract testing between API providers and consumers led me to a whitepaper by Ian Robinson from ThoughtWorks.

Cliffnotes

CDC (Consumer-Driven Contracts, or Derived Contracts) pattern for evolving API contracts as an alternative to schema extension (versioning) or “just enough” validation.

  • SOA
    • High-value business logic in discrete, reusable, encapsulated, testable, modifiable, connected services
    • Fully realise if services can evolve independently
    • Paradoxically, APIs couple providers and consumers rather than decouple (i.e. providers scared to make changes)
  • Existing strategies:
    • Update API: best for providers (simple change), worst for consumers (potentially all consumers must re-implement)
    • Extend API maintaining backwards compatibility: worst for providers (more complexity, less elegant, harder maintain), best for consumers (no change). Really big changes still require providers and consumers to jump at the same time.
  • W3C Technical Architecture Group (TAG) has proposed versioning strategies from none (no versioning) to big bang (abort if any changes), backwards/forwards-compatible 
  • Provider contracts
    • Term introduced meaning a complete set of business functions (i.e. APIs)
    • Stable and immutable for a set period of time!!
  • Consumer contracts
    • Consumers send providers expectations of what specific data is being used based of Schematron assertions (i.e. incomplete schemas validating only what the consumer actually uses)
  •  CDC:
    • CDC container consists of schemas, interfaces (endpoint definitions and possibly links), conversations (provider state!!), policy (usage of data) and quality of service (availability, latency and throughput) for a provider contract
    • Allows providers to track and analyse how services are being used in order to better meet customer demands
    • Adds complexity and protocol-dependence
    • Doesn’t protect from breaking changes or reduce coupling, but rather adds visibility
  • Misc:
    1. When developing a consumer, do “just enough” validation to get the data you need in accordance with the Robustness Principle (i.e. liberal attitude towards incoming data)
    2. Would be nice for consumer responses to possibly include data fields they want in the future (i.e. feature requests)

Conclusion

CDC violates REST (stateful), relies on immutable periods of time (fragility), adds too much complexity and overhead. A better standard for receiving feedback from consumers would be an optional (yet standardised) header in the request, which the provider could track.

Resources

Default Rails Application Demystified

rails-flow-mapping

Intro

When you run ‘rails new helloworld’ it creates 41 folder, 41 files and 10 gem dependencies! Below is a default Rails 4.1.6 project contents presented (comments edited for brevity) and demystified.

Simplified Flow

bin/rails > boot.rb > application.rb > environment.rb > server started

Ruby Files

Ignoring backtrace_silencers.rb, inflections.rb and mime_types.rb (empty).

/config/application.rb

Runs boot and loads all gem files. Called by the rails executable.

require File.expand_path(‘../boot’, __FILE__)
require ‘rails/all’
Bundler.require(*Rails.groups)
module HelloWorld class Application < Rails::Application end
end

/config/boot.rb

Sets environment variable to the location of the Gemfile then calls Bundler setup, which uses ENV to find the dependencies.

ENV[‘BUNDLE_GEMFILE’] ||= File.expand_path(‘../../Gemfile’, __FILE__)
require ‘bundler/setup’ if File.exist?(ENV[‘BUNDLE_GEMFILE’])

/config/environment.rb

Generic config file defining the application. Runs all initialiser classes.

require File.expand_path(‘../application’, __FILE__)
Rails.application.initialize!

/config/routes.rb

Map requests to controllers.

Rails.application.routes.draw do
end

/config/environments/development.rb

Overriding /config/application.rb settings when run in development mode.

Rails.application.configure do
# Changes don’t require a server restart
config.cache_classes = false
# Do not eager load code on boot.
config.eager_load = false
# Show full error reports and disable caching. 
config.consider_all_requests_local = true 
config.action_controller.perform_caching = false
# Don’t care if the mailer can’t send. 
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger. 
config.active_support.deprecation = :log
# Raise an error on page load if there are pending migrations. 
config.active_record.migration_error = :page_load
# Debug mode disables concatenation and preprocessing of assets. 
config.assets.debug = true
# Adds additional error checking when serving assets at runtime. 
config.assets.raise_runtime_errors = true
# Raises error for missing translations # 
config.action_view.raise_on_missing_translations = true
end

/config/environments/production.rb

Overriding /config/application.rb settings when run in production mode.

Rails.application.configure do
# Code is not reloaded between
requests. config.cache_classes = true
# Load most of Rails and app object in memory for performance 
config.eager_load = true
# Full error reports are disabled and caching is turned on. 
config.consider_all_requests_local = false 
config.action_controller.perform_caching = true
# Disable Rails’s static asset server (Apache or nginx will already do this). 
config.serve_static_assets = false
# Compress JavaScripts and CSS. 
config.assets.js_compressor = :uglifier
# Do not fallback to assets pipeline if a precompiled asset is missed. 
config.assets.compile = false
# Generate digests for assets URLs. 
config.assets.digest = true
# Log level not debug to keep file size down. 
config.log_level = :info
# Send deprecation notices to registered listeners. 
config.active_support.deprecation = :notify
# Use default logging formatter so that PID and timestamp are not suppressed. 
config.log_formatter = ::Logger::Formatter.new
# Do not dump schema after migrations. 
config.active_record.dump_schema_after_migration = false
end

/config/environments/test.rb

Overriding /config/application.rb settings when running test suites.

Rails.application.configure do 
# Code is not reloaded between requests. 
config.cache_classes = true
# Do not eager load code on boot. 
config.eager_load = false
# Configure static asset server for tests with Cache-Control for performance. 
config.serve_static_assets = true 
config.static_cache_control = ‘public, max-age=3600'
# Show full error reports and disable caching.
config.consider_all_requests_local = true 
config.action_controller.perform_caching = false
# Raise exceptions instead of rendering exception templates. 
config.action_dispatch.show_exceptions = false
# Disable request forgery protection in test environment. 
config.action_controller.allow_forgery_protection = false
# Tell Action Mailer not to deliver emails to the real world. 
config.action_mailer.delivery_method = :test
# Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
end

/config/initializers/assets.rb

# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = ‘1.0'

/config/initializers/cookies_serializer.rb

# Serialise cookies in JSON.
Rails.application.config.action_dispatch.cookies_serializer = :json

/config/initializers/filter_parameter_logging.rb

# Configure sensitive parameters which will be filtered from the log file.
Rails.application.config.filter_parameters += [:password]

/config/initializers/session_store.rb

# Cookie and session name based of app name.
Rails.application.config.session_store :cookie_store, key: ‘_hello-world_session’

/config/initializers/wrap_parameters.rb

Wraps the parameters hash into a nested hash allowing POST requests without having to specify any root elements.

# Enable parameter wrapping for JSON.
ActiveSupport.on_load(:action_controller) do wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
end

YAML Files

/config/database.yml

Define which database, locations and basic settings.

# Default settings
default: &default adapter: sqlite3 pool: 5 timeout: 5000
development: <<: *default database: db/development.sqlite3
test: <<: *default database: db/test.sqlite3
production: <<: *default database: db/production.sqlite3

/config/secrets.yml

Security-related configs such as signed cookie validation. Never push this file to a public Git repository!

development: secret_key_base: randomlygeneratedkeyatleast30characterslong
test: secret_key_base: randomlygeneratedkeyatleast30characterslong
# Read production key from environment (can’t start app if doesn’t exist)
production: secret_key_base: <%= ENV[“SECRET_KEY_BASE”] %>

/config/locales/en.yml

Internationalisation (i18n) properties file.

en: hello: “Hello world”

Other Files

Ignoring .gitignore, Gemfile.lock and README.rdoc.

/config.ru

Rackup file for running the Rack-compliant (adheres to a spec) web server.

require ::File.expand_path(‘../config/environment’, __FILE__)
run Rails.application

/Gemfile

Dependencies for the project. Managed by Bundler.

source ‘https://rubygems.org'
# Rails
gem ‘rails’
# Use sqlite3 as the database for Active Record
gem ‘sqlite3'
# Use SCSS for stylesheets
gem ‘sass-rails’, ‘~> 4.0.3'
# Use Uglifier as compressor for JavaScript assets
gem ‘uglifier’, ‘>= 1.3.0'
# Use CoffeeScript for .js.coffee assets and views
gem ‘coffee-rails’, ‘~> 4.0.0'
# Use jquery as the JavaScript library
gem ‘jquery-rails’
# Turbolinks makes following links in your web application faster.
gem ‘turbolinks’
# Build JSON APIs with ease.
gem ‘jbuilder’, ‘~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem ‘sdoc’, ‘~> 0.4.0', group: :doc
# Speed up development by keeping your application running in the background.
gem ‘spring’, group: :development

/Rakefile

Load web application when rake is called.

require File.expand_path(‘../config/application’, __FILE__)
Rails.application.load_tasks

/bin/bundle

Bundler gem management executable.

ENV[‘BUNDLE_GEMFILE’] ||= File.expand_path(‘../../Gemfile’, __FILE__)
load Gem.bin_path(‘bundler’, ‘bundle’)

/bin/rails

Main Rails executable.

begin load File.expand_path(“../spring”, __FILE__)
rescue LoadError
end
APP_PATH = File.expand_path(‘../../config/application’, __FILE__)
require_relative ‘../config/boot’
require ‘rails/commands’

/bin/rake

Build tool executable (Ruby equivalent to Make).

begin load File.expand_path(“../spring”, __FILE__)
rescue LoadError
end
require_relative ‘../config/boot’
require ‘rake’
Rake.application.run

/bin/spring

For development, keeps a copy of the running app in the background. Injects code into rails and rake executables.

unless defined?(Spring) require “rubygems” require “bundler”
if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ spring \((.*?)\)$.*?^$/m) ENV[“GEM_PATH”] = ([Bundler.bundle_path.to_s] + Gem.path).join(File::PATH_SEPARATOR) ENV[“GEM_HOME”] = “” Gem.paths = ENV
gem “spring”, match[1] require “spring/binstub” end
end

References

Ruby observations from a Java guy

rails
About

After a decade of Java experience currently learning Ruby/Rails because it’s the Hot Shit™.

Overall

  • Fun. A cowboy language (see: monkey patching).
  • Rapid development great for new projects, startups, messing about. Productive.
  • Low enterprise adoption in Australia yet lots of smaller companies looking for developers.
  • Lots of freedom for developers (patching, overriding) relies on discipline of programmers, and since all humans make mistakes, eventual loss of control — especially for large projects. Mitigate risk with comprehensive regression testing and small modular components.
  • ERB (Embedded RuBy) reminds me of JSP on pages in Java — a practice frowned upon because it mixes languages (used HTML-valid taglibs).
  • Lots of files generated with a new project (41 folders, 41 files)!
  • Lots of objects per request (Rails3 ‘hello world’ ~8.5k objects, GC every ~6 requests)!
  • MRI (Matz’s Ruby Interpreter, CRuby) was replaced by YARV (Yet Another Ruby Vm, KRI) in Ruby 1.9 as the default executable. Other implementations include JRuby (runs on Java’s JVM), Rubinius, RubyMotion etc.
  • Ruby doesn’t support true concurrency (Global Interpreter Lock). Use JRuby threads or fibres and non-blocking IO. Headaches of dealing with code and gems that aren’t thread-safe.

Conventions

  • Convention over configuration (“The Rails Way”), lean principles.
  • No service folder/layer by default? Rails way to put business logic in models — can get messy.
  • GDD (Gem-Driven-Development): Before coding, check what gems exist, don’t reinvent the wheel. For serious projects, can lead to security and performance (i.e. object creation) issues.
  • Brackets for method parameter/arguments? No consensus.
  • Symbols don’t get GC’d so don’t use for dynamic data or else memory leak.
  • “Fat model, skinny controller.” Only logic for sessions, cookies, request parameters, model selection, rendering/redirecting.
  • Don’t put too much logic in the view — leverage partials, decorators, helper classes.
  • Don’t put too much logic in the model. Only logic for ActiveRecord relations/validation, database interaction, property helpers (e.g. fullname), sophisticated queries. Use POROs (Plain Old Ruby Objects) instead (i.e. services, SOA).

Production

  • Define secret_key_base in secrets.yml.
  • Set config.assets.compile to true in production.rb (otherwise CSS not included).

Heroku

  • No support for SQLite, must add ‘pg’ (PostgreSQL) gem to Gemfile for production. Pain in the ass adding the pg gem (requires install of Postgres locally even though not used…WTF).
  • Very easy to deploy.

Testing

  • Huge necessity for BDD/TDD and regression testing to ensure confidence. Poor static code analysis due to loosely-typed, difficult to enforce design patterns with interfaces/abstract/access modifiers/encapsulation.
  • Minitest or RSpec? Both good.
  • Domain Specific Language (spec) notation (e.g. “describe calling foo it should return bar”), matches user stories, easier for non-programmers to understand, personal preference.
  • Minitest supplied with Ruby, replacement for older Test::Unit gem, unit testing (Ruby or spec), mocking, benchmarks, lightweight, BDD requires configuration (capybara = start browser), require ‘test_helper’ for web application context (loads initialisers/configs, slower).
  • RSpec many ways to do the same thing, advanced features (before all, around each, shared groups/contexts, powerful mocks, verifying doubles = mock checks methods exist…awesome), BDD out of the box.
  • Additional gems: Mocha (mocking), Shoulda (matchers).

RubyMine

  • Generated test classes do not work out of the box.
  • Can’t get Heroku deployment to work (terminal only).
  • Poor code completion and IDE errors due to loosely-typed. Not knowing off-by-heart end up Googling (read: Stack Overflow) a lot. BDD/TDD guesswork because not sure if even syntax is correct until at the implementation stage — run and see if it breaks!

Conclusions

  • Very enjoyable and ideally suited for non-critical projects/modules with manageable numbers of developers (80/20 rule).
  • BDD/TDD is essential.
  • Standard Rails may have performance issues due to high object creation and inefficient GC.

References

Java Interview Questions Cheat Sheet

java

About

For refreshing one’s memory before an interview.

Core Java

  • About: Strict typed, class-based, OO, platform-agnostic
  • Lifecycle: compile .java to .class bytecode, run just-in-time by the JVM, no reference, finalize(), GC
  • Keywords: import, finally, super, class, package, int, synchronized (one thread at a time, avoids data race [multiple threads access same data], method or block), volatile (modified by other threads)…many more!
  • Objects:
    • state = fields, behaviour = methods
    • == (compares references i.e. same object in memory, shallow comparison), equals method can be overridden for deep comparison of properties
    • hashCode (unique hash) — used by maps, same object should produce same hash must override both
    • Dog puppy [declaration] = new [instantiation] Dog(“fido”) [initialisation]
  • Class: object creation blueprint, load manually by ClassLoader (dynamic plugins), top-level can’t be private/protected, auto loads java.lang.package, inner classes, nested class (static within class)
  • Interface: collection of abstract methods, Externalizable (serialisation), Enumerator (loops), Iterator (looping with support for removing, thread safe), Comparable (natural order), Comparator (custom order), Marker (empty, use annotation instead)
  • Scope: local (within method), instance (property), class (static)
  • Constructor: invoked only once on creation, if private no instantiation no subclassing (e.g. singletons)
  • Primitives: boolean, char (16-bit unicode), byte (8-bit), short (16), int (32), long (64), float (32), double (64)
  • Wrappers: Autoboxing, unboxing (e.g. Integer)
  • Collections:
    • Set (no duplicates), TreeSet (sorted), Vector (heterogeneous [different types], dynamic, sync), ArrayList (dynamic, random access), LinkedList (sequential add/remove), Map, HashTable (sync, no null)
    • ordered longer insert, faster lookup
  • Loops: do executes at least once
  • Streams: Reader/Writer (char), Input/OutputStream (byte, serialisation), System.out (PrintStream)
  • Modifiers:
    • final (variable = immutable, methods = no override, class = no extend)
    • protected (access by same package and subclasses)
    • default (same package)
  • Switch: byte, short, int, char (why?)
  • Strings: immutable, final (can’t subclass and make a mutable string), stored on stack, thread-safe, StringBuffer (sync), StringBuilder
  • OO: simple, modular, modifiable, extensible, maintainable, reusable
  • Abstraction: partial implementation, enforcing blueprint, class only extended
  • Encapsulation: data hiding through getters/setters, maintainability, modifiable
  • Inheritance: no multiple inheritance (no circular dependency, ambiguous calls e.g. super = diamond problem), extend one class, implement many interfaces
  • Polymorphism: Dynamic Method Dispatch, “many forms”, method overloading at runtime, method overriding at runtime
  • Acronyms: JAR (Java ARchive), WAR (Web ARchive), JDBC (Java DataBase Connectivity), Java EE (Enterprise Edition), Java SE (Standard Edition), JDK (Java Development Kit), JRE (Java Runtime Environment)
  • JDBC: PreparedStatement precompiled faster
  • Threads:
    • single execution in a process
    • sleep, wait (up to until notify), yield, suspend, notify, notifyAll, isAlive,
    • newborn > runnable > running > blocked > dead
    • daemon = background low priority
    • implement Runnable or extend Thread (manage manually)
  • Errors:
    • Error: irrecoverable (e.g. OutOfMemory)
    • Exception: recoverable (e.g. FileNotFoundException), Checked: throws BadInputException
    • Assertion: never-happen scenarios and tests (e.g. assert dependency exists)
  • Binding: dynamic (late, generics, polymorphism), static (static, final, private)
  • Sockets: lightweight TCP/IP (Transmission Control Protocol)
  • Env: CLASSPATH (.class files), PATH (executables)
  • Casting: downcast to a more specific type down the hierarchy (e.g. Animal > Dog), implicit (inferred, lossy), explicit, promotion (e.g. short to int)
  • Big O Notation: O(1) constant, O(n) linear loop, O(n2) quadratic nested loop, O(n3) cubic double-nested loop, O(log n) logarithmic half list each time binary search
  • Cookies: client-side sent every request, Session: server-side (or encrypted cookies)
  • Date: sql date (no time) extends util
  • Parameters:
    • definitions, Arguments: actual values
    • pass by value, object properties can still be modified!
  • Bean: encapsulation (getters/setters), public constructor, serialisable
  • Terms:
    • Referential Transparency: no outside influence, don’t need to understand full context/globals.
    • Boundary Condition: extreme inputs.
    • Composition: class holding reference to another class.
    • SOLID Principle: open to extension, closed to modification.
    • Demarcate: to define boundaries (e.g. transaction).
    • Non-blocking API: don’t wait for 3rd party API calls (e.g. threads).
    • Single responsibility principle: each variable/method/class should define a single responsibility (only one reason to change).
    • Idempotent: calling same method multiple times doesn’t hurt (e.g. remove item from list).
    • Separation of concerns: modular.
    • (String) Interpolation: String with placeholders (e.g. $foo).
    • Method vs function: methods are functions tied to an object (e.g. it’s behaviour).
  • Memory Leaks: Thread running ClassLoader (ThreadLocal keeps reference), String.intern, unclosed streams/connections, static, setAttribute (context, session)
  • Improve Java: less verbose (e.g. getters/setters), as-needed modular (Jigsaw), kill servlets, not Oracle
  • Performance: monitoring, java startup arguments (e.g. heap), pooling, caching, refactoring, latest versions, scale up, scale out
  • Sort:
    • Bubble (quad, compare and swap adjoining elements, pass through until no swaps, low memory > performance, simple)
    • Insertion(quad, one element at a time, insert in the right spot, linked list pointers, simple, efficient small data)
    • Quick (log to quad, choose pivot/middle value, from left>right if value less than pivot, replace with first lesser value working from the right, recursive)
    • Merge (log, divide and conquer, split until single elements, combine in order until sorted, simple, requires space)
  • Search: linear (n, for loop), binary (sorted, half each pass, recursion)
  • Annotations:
    • meta-data through introspection, less code, dev time (documentation, checking), runtime (wiring, descriptions)
    • @NotNull, @Controller, @Transaction, @Entity, @Override
  • IDE: auto-completion, code generation, static code checks, plugins, highlighting (CheckStyle, FindBugs)
  • Java Versions:
    • 5 (generics, annotations, enums, for-each), 6 (meh), 7 (string switch, try with resources, <> operator), 8 (lamdbas)
    • Java SE = JVM, JDK = JRE + compilers
  • Testing: mock objects, stub methods, unit = smallest component (e.g. a method), integration = multiple components together (e.g. log in), user acceptance = customer expectations, non-regression = re-running all tests for confidence (e.g. Continuous Integration), spec = declarative specification style (non-programmers, readable, Domain Specific Language)
  • Design Patterns: singleton (instantiated once, shared resources e.g. log, pooling), prototype (copy), facade (abstract away complexity), factory (create objects), abstract factory (create factories), observer (notifies, AOP), MVC, MVVM (ViewModel = exposed data bindings to the view rather than rendering, separate UI), adapter (connect two interfaces), strategy (common functionality e.g. sort), state (?), proxy (control access), DI, builder (create complex objects), chain of responsibility (pass request e.g. filter, log), template (outline, subclasses do steps), decorator (add functionality to existing e.g. override). Gang of Four (GoF) authors.

Spring

  • About: framework, open-source, IoC container
  • Modules: core, bean, context, JDBC, ORM, JMS, web (context, binding), AOP, transactions…
  • Inversion of Control (IoC): loose coupling of code from metadata and dependencies, easier to test in isolation, Dependency Injection (DI via constructor or setters)
  • Service-Oriented Architecture (SOA): Loosely coupled services (Law of Demeter), interact as black boxes, distributed, modular, interoperability
  • BeanFactory: creates container
  • Container: lifecycle of a bean (invokes, config, dependencies, security, transactions, management, destroy), override setup/destroy methods
  • Pattern: default Singleton, otherwise prototype (inner bean)
  • Annotations: declarative management, @Autowired (auto resolve dependencies), @Required (must be initialised at runtime), @Service/Component/Repository (labels), @Transactional, @Test(expected=IOException.class), @Before, @After
  • AOP: Aspect (encapsulation), Joinpoint, Pointcut (1+ Joinpoints), Advice (actual code)
  • DAO: JPA and Hibernate, lazy/eager loading
  • JMS: Message-Driven Beans (MDB), queues, process messages async
  • Dispatcher: DispatcherServlet reads incoming requests, calls the right class/method, combines result with the right view and returns response
  • Context: WebAppContext extends AppContext and adds ServletContext (resources, defined contexts in web.xml)
  • Deployment Descriptor: web.xml, describes classes, resources, config, request mapping
  • Classloader: Executes hierarchy top to bottom (superclasses first), different strategies per app server
  • TDD: JUnit (assertEquals), Mockito (mock foo, when foo.bar thenReturn, verify foo.doh), Hamcrest (assertThat, is, not, any, anything, equalTo, isA)

JavaScript

  • About: ECMAScript, scripting language, loosely typed, prototypical (prototype-based), object-based
  • Modules: wrap in function block, namespacing, alias (e.g. $.foo)
  • Scope: var foo (local), foo (global). Only functions create new scope, not blocks.
  • Data Types: undefined (default), number, string, boolean, object (e.g. foo = {}, foo = new Array), function, null
  • Operators: == (type conversion), === (no type conversion)
  • Inheritance: prototype (i.e. chained parent refs, inherit properties, parent not modified) or Object.create(Object.create) = recommended
  • Strict Mode: no accidental globals, duplicate property names etc.
  • Number: no integer, floating point precision (nearest binary point) = weird stuff! Don’t use for precision!
  • DOM: Document Object Model, object of rendered page, interact with
  • Event Bubbling: parent nodes triggered
  • jQuery: lightweight, cross-browser, plugins, CSS3, supported, selectors, manipulation, loops, events, animations, AJAX, utilities…
  • Hoisting: Variable declarations and function declarations (not function expressions) are invisibly moved to the top of their scope.
  • Isomorphic: Code that can be run client or server-side.
  • Function Types: Function expression (i.e. unnamed/anonymous, parse-time available when assignment line hit) vs function declaration (i.e. named, run-time scope before any step-by-step code is executed, can’t put inside conditional blocks such as if/try/while, proper name when debugging). It’s possible to combine both styles, but has IE8 issues. Never use the Function() constructor. ECMAScript6 will attempt to infer expression names from context.
    // Function expression
    var foo = function() {}
    // Function declaration
    function foo() {}
    // Combined/Named Function Expression
    var foo = function bar(){};
    // Combined with proper aliasing across browsers
    function bar(){};
    var foo = bar;
  • Cross Browser: JavaScript can’t POST cross-domain (use a library like easyXDM or back-end)
  • Weird: null is an object (default undefined), foo(2)(3) returns annon function, semicolons optional, negative infinity (negative / 0)

Functional

  • Predicate: function that runs against every item in a collection — returning true or false. Used for filtering without nested for/if statements.
  • Lambdas: function that can be passed around like an object.
  • Closures: private variables made possible through self-invoking functions (i.e. outer function contains private variables and returns function expression — outer only ever called once). Example:
// self-invoking run only once
var add = (function () {
  // counter protected by anonymous scope (private)
  var counter = 0;
  // add function associated with returned function expression
  return function () {return counter += 1;}
})();

add(); // counter = 1
add(); // counter = 2

Tips

  • BDD/TDD!
  • Whiteboarding use pseudo code placeholders to guide the thought process — then replace pseudo with implementation. Don’t get stuck on implementation before solution is mapped out.
  • Don’t commit boilerplate code, IDE files and comments to the repository
  • Be involved in the community (follow people, read blogs, stream, attend events, network, work on projects)
  • Commit often to your local Git repository and every day or so to the remote origin
  • Never say “can’t” — don’t lie, but back yourself to learn it. Most things are not that hard.

Room For Improvement

  • Encoding, bit shifting, octal/hex, Applets (Swing, AWT), JVM heap, GC (WeakReference), PermGen (class metadata), RMI, Servlets/JSP, Angular, monoids.

About

My takeaway from the article “42 Rules to Lead by from the Man Who Defined Google’s Product Strategy” around running a (technology) business.

Leadership

  • Primary job is judgement and communication
  • Verify data decisions are based on
  • Thoughtful and precise communication
  • Don’t prevent failures (i.e. risk), prevent bad failures
    • Don’t let failures hurt you (be robust)
    • Low downside, big upside
    • Failure is information (appreciation, change)
  • Say ‘yes’ to new ideas
  • Surround yourself with great people (better at what they do than you) and empower
    • Delegate
  • Mean what you say

Communication

  • Transparency
  • Straight talk
    • Tell people when they aren’t doing a good job

Culture

  • Everyone’s opinion is equal (ignore title)
  • Crush bureaucracy (organisation’s ability to get out of the way)
  • Crowded is creative (office energy)
  • Empowered small teams
    • “In software development, the worst thing you can do is put more people on a project.”
  • No working from home (requires great culture)
  • Hope is not a plan
  • Spend 80% of your time on 80% of your revenue
  • If must reorganise, do it in 1 day

Team

  • A-grade people want (i.e. need) to work with other A-grade people
  • Interview well to give the best chance
    • Look for passion
    • Don’t hire specialists (no adaptability)
    • Take time searching (don’t compromise quality)
    • Great employees are going to be random
    • Fail fast (get rid of bad eggs quickly)
  • Hire and promote by committee (peer reviews)
  • Diversity is good

Self

  • Never stop learning
  • Constant critical and honest self-inspection
    • “It’s the only way to learn he says. Communicate, confess, and comply. No one is perfect – not even you.”

Decisions

  • Start with the right goals
  • If everyone is thinking alike, then somebody isn’t thinking (Devil’s advocates)
  • Innovation = mistakes. Inspect, take accountability and learn.

Innovation

  • Creativity can’t be dictated or managed — only tracked and encouraged
  • Try all ideas, the best will win (that won’t result in bad failures)
    • “To have a great idea, have a lot of them”
  • New ideas to protect from intertia
    • Large companies stop innovating and treat innovators as a virus

References

The Future of JavaScript: Java

js-java

About

Comparing server-side JavaScript with Java in the context of web applications.

JavaScript is adopting many of the traditional (i.e. mature) Java principles and patterns — while Java is adopting some of the dynamic and flexible qualities of JavaScript.

Differences

Differences that cannot be bridged through current libraries or future releases:

  • Minor syntax differences
  • JavaScript prototypes can be redefined at runtime

Similarities

Feature
Java
JavaScript
Server-side Everything worth using… Sling, Node.js, SilkJS
MVC (Model View Controller) Struts, Spring MVC, JSF, Play! Ember, Backbone, Angular
DI (Dependency Injection) Spring, Guice Angular
Mocking Mockito, JMockit jsMockito, Jasmine
Serialisation JAXB, XStream JSON
Precompiling JVM bytecode Concatenation, minification, Handlebars, Closure Compiler
BDD (Behavioral-Driven Development) JBehave Jasmine, JSpec
OO (Object Orientated) Principles Encapsulation (classes, modules) and inheritance Encapsulation (classes, modules) and inheritance (ES6)
Data Persistence Hibernate, Play! JavaScript database (SQLite), Ember, Backbone, Angular
Types Strongly typed StronglyTyped, js-tipos, typed arrays (ES6)
Collections Array, map, set, list, vector Array, map, set (ES6)
Iterators Java 5 for-each For loop (ES6)
Static Code Analysis FindBugs, Checkstyle, PMD JSLint, JSHint
AOP (Aspect-Oriented Programming) Spring AOP, AspectJ jQuery AOP, Dojo, AspectJS
Transactions Spring, SimpleJTA, Atomikos, JOTM AtomizeJS, Txn
Security (Authentication, Authorisation) Spring Security, JAAS, Shiro Ember, Backbone, Angular
Messaging RabbitMQ, ActiveMQ Postal, Rabbit
Annotations Java 5 Closure Compiler, JSDoc, Yaap
Functional Programming (Lambdas, Closures) Java 7 Closures, Java 8 Lambdas, Functional Java, lambdaj By default…
IDE (Integrated Development Environment) Eclipse/MyEclipse, IDEA, STS, Netbeans Eclipse, Netbeans, Webstorm, Aptana

Conclusion

As frameworks continue to mature and grow, JavaScript will provide a genuine alternative (if not already) to server-side Java development.

Taking into consideration accessibility/exposure/familiarity, the future of new web application development belongs to JavaScript.

References

Man Crush: David Heinemeier Hansson

About

Notes and thoughts from David’s homepage. Inspirational, he has a great outlook and perspective on business and lifestyle.

Note: Considering consolidating the notes from the three videos in the future (as they overlap quite a bit).

At a glance

  • Created Ruby on Rails
  • Partner at 37signals (known for Basecamp)
  • Author or co-author of REWORK and Getting Real
  • Public speaker
  • Race-car driver (WTF?!)

The Secret To Making Money Online

“Great achievement comes from solving simple problems.”

  • Charge for your product
    • Subscription, pay per use or pay to own are all tried-and-true business models
    • If the product is good enough, people will pay for it
    • Scaling problems are GREAT as it linearly correlates to revenue (unlike YouTube…)
  • Don’t focus on trying to “catch the next wave” (e.g. Facebook, YouTube)
    • Odds of success are microscopic (exception rather than the rule)
    • The jump from nothing to $1m is a lot harder than the jump from $1m to $1b
    • People are too eager to release and take VC money
    • Sensationalised in the media along with plane crashes
  • Try and build an “Italian restaurant” (doesn’t have to be the best Italian food in the world, just convenient and slightly better than local competitors)
    • Most businesses will still fail
    • $1m is a hard but achievable target (e.g. 2,000 customers @ $40/month, with 5% conversion rate need 40,000 customers or 110 a day)
    • Be happy with $1m…it’s a lot of money
    • Only 2,000 customers? Attack a niche!
  • Choose sustainable over viral growth
    • Start small and be patient
  • Target Fortune 5,000,000 companies!
    • No business too small
    • Just want their problem solved at a reasonable price
  • Many small customers over a few large customers
    • No corporate bureaucracy
    • Not reliant on a few customers (bend over backwards, feature coercion)
    • Evenly distributed customers = less fragile
  • Passion over money
    • If you can earn a million a year and do what you enjoy, why give that up for a pay day? What would you do next?
    • After a point (comfortable living, freedom), money provides diminishing returns and even negatives (email, meetings, reputation, more to lose)
  • Work smarter, not harder
    • Only 2/3 really productive hours a day
    • Working less hours a week forces you to focus and not waste time
    • The work ethic (hours, patterns, practices) at the start will never ease off — make sustainable choices

TWiST #46 Interview

Facebook to startups is equivalent to lottery tickets for a wage — it only works for a precious few. Is a lottery a good way to run a business?

  • Rule #1: Just build a profitable business
    • Don’t try and get hits then figure it out later
    • Charging for your product is better than begging for advertising crumbs
    • Social, traffic, hype (e.g. TechCrunch), VCs and acquisitions are a fake game, a bubble
    • Lots of spinning the wheels while going nowhere
  • Startups don’t need VC
    • Nothing easier than spending someone else’s money
    • Too much runway, easy to goof around, no fire up your ass!
    • Besides the top tier, overall VCs have lost money
  • Acquisition (i.e. exit strategy) will likely make your company worse
    • Successful acquisitions are the exception, not the rule
    • Keeps happening because of delusions of grandeur and risk taking (i.e. “this time it will be work”)
  • Profit is king
    • Best feedback mechanism for measuring the success of a idea/company
    • Revenue is irrelevant
    • Strong profit margins is the best position to be in
    • Who cares about market share if profits are strong (see: Apple)? Only matters if it leads to profits.
  • Selling out
    • Work on your best idea right now. Why would you sell to work on your second best idea?
    • It’s possible you won’t have a better idea in the future (e.g. Microsoft’s best ideas of Windows/Office are decades old)
  • Big != Better
    • Overvaluations, going public, massive acquisitions…
    • Loss of control and dealing with bullshit associated with being “big”
    • Reduced quality of life
  • Misc
    • If established and profitable, it’s OK to sell non-controlling shares for a personal payout (i.e. take money ‘off the table’)
    • Urgency is overrated
    • Meetings suck! Make decisions quickly, fail fast and iterate
    • Working harder (i.e. more hours) does not equal success
    • Revenue per employee is a good measure of efficiency (beware the bloat)
    • Web allows for many small businesses — not just Wallmarts

Unlearn Your MBA

“Take the time, at a reasonable sustainable pace, and own your company in the end — or strap the [VC] time bomb on your back and see if that’s going to make you run faster; and see if you’ll be happier in the end.”

  • Planning is harmful guessing
    • Most decisions are temporary (i.e. not building factories)
    • Decisions don’t matter that much, pick and get started
    • Constraints force new ideas in new markets
  • Sustainable and scalable
    • You can’t pay your bills with eyeballs (i.e. page hits)
    • Should be no linear correlation between revenue and the org chart (more revenue doesn’t mean more people)
    • Sustainable businesses built on word of mouth
    • Generally don’t make big splashes in the media (not sexy)
  • Working
    • Being a workaholic is not a requirment or guarantee for success
    • Only 5-10% of effort matters
    • Less execution through a well rested mind (i.e. work smarter)
    • Startups need people who contribute direct value, not ideas or management
    • Entrepeneurs should force themselves to work for a shit company for 6 months to learn from mistakes and get the motivation to be better
  • VC is a time bomb
    • Seems like a good idea, probably the most harmful thing you can do
    • Push for big returns in short timeframes — have no interest in slow, sustained growth
    • No constraints and no urgency…until the the time and money runs out (then you’re fired)
    • Spending your own money is a strong driving force
    • Either have the pain now (struggle with no money) or later (wasted time, pushed out, nothing to show)
    • Wasted time and effort getting the next round of funding (addicted, next hurdle)
    • Accelerated growth is a farce — it takes a long time to get something good
    • Killing industry by crushing ideas/companies and wasting people’s time
  • Big leagues via the small leagues
    • Even small companies can make millions per year
    • Creating a small company is like playing poker: it takes skill and luck, but at least you have a fighting chance. Creating the next YouTube is like the lottery.
    • Very few companies go straight to big, but that’s what VCs are searching for (optionality, low investment for a potential huge payoff)
    • Most ‘overnight successes’ took 10-years
  • Existing business lessons
    • Easiest way to destroy a successful company is to deviate away from what make it successful
    • Idle managers are the worst as they need to make things up (e.g. processes) to justify their job
    • Opportunities exist when times are tough and business shift to more cost-effective alternatives
    • Salesforce has terrible margins (~6% profit)…and they sell software!
    • Bad decisions a product of the environment more than the people (e.g. no accountability, perspective, training, familiarity with business, culture)

Jason Calacanis

TWiST host. The Bill O’Reilly of technology (maybe not that bad…maybe).

Greedy, forceful, egotistical, selfish, devious and arrogant. Don’t care who you think you know, what you did and how much you made.

Derives pleasure through belittling and condescending behaviour. Relentless comparisons to tech giants (e.g. Google, Facebook) in an effort to poke holes in business comfortable where it is. Not every basketball player in the NBA can be (or needs to be) LeBron James.

Afraid (“are you a communist?”) of a person who is perfectly content in the ‘middle’ rather than at the ‘top’. Confused and offended at the very notion that you wouldn’t trade happiness and purpose for a pile of money!

A manifestation of everything that is wrong with capitalism.

References

API-Driven Development (ADD)

About

ADD is a fast, flexible, robust, reusable, testable, scalable architecture design for (new and existing) applications.

Unlike traditional MVC (Model View Controller) frameworks, there is no model (i.e. data/representation) tightly coupling the view (e.g. webpage, app) to the controller (i.e. services, business logic). Instead, with the proliferation of technologies/platforms (e.g. browser, mobile, TVs), you will have many interfaces dealing with a single back-end.

Shifting business logic and data to web services follows the Semantic Web movement, which many believe to be the natural evolution of the internet.

Note: API refers to best practice RESTful web services, not SOAP!

Advantages of APIs

  • Decoupled (separation of business logic and presentation)
  • Stateless (less complex, scalable)
  • Simple (view/test in browser)
  • Reusable (one back-end API consumable by web, phone, ps3, etc.)
  • Exposed (open, mashups/marketing, scrutiny/improvement)
  • Facade (complexity hidden)
  • Universal/Agnostic (communication between systems using potentially different technologies)
  • Secure (HTTPS, OAuth)
  • Versionined
  • Cachable (browser or server)
  • Defined and documented (API Blueprint, RAML or Swagger)

Disadvantages

  • Overhead (HTTP requests)
  • Vulnerable (exposed services, mitigated by proper design and security)

ADD Architecture & Advantages

  • Easy to mock
    • API consumers (e.g. HTML page) can interact with a mock API response, such as a URL to a static JSON file on Dropbox or Mockjax plugin for jQuery
  • Easy to test
    • Isolate and test just the business logic by calling an endpoint and validating the JSON returned
  • Technology agnostic
    • Underlying API and front-end technologies do not matter — use the best tool for the job
  • Modular
    • Break services into self-contained modules for greater robustness (smaller systems are less fragile) and selective scalability
  • Firewalled
    • All requests can be routed through a ‘Gatekeeper’ module that handles authorisation and authentication
    • Calls can be monitored and rate-limited to mitigate abuse
    • Can be added to the stack later with very little integration effort
  • Daisy chain
    • Provided endpoints are persistent and versioned, it’s possible to chain API calls together (i.e. functional programming)
  • Work to your strengths
    • Back-end people work exclusively with data, persistence, scalability and business logic. Front-end work exclusively with user experience, visuals, accessibility and JSON.

Approaches

The front-end (e.g. HTML, iPhone app) can be developed completely independently of the back-end (APIs) business logic. Approaches:

  1. Meet in the Middle: Both sides agree on the initial API specification and build them independently — with the front-end initially mocking the requests/responses. Requires flexibility from both sides via constant adjustments.
  2. Ground Up: Front-end developed running on mocked data, which is revised as needed. The final mock data is then filled-in by real APIs. Does not take into consideration requirements from other back-end systems.
  3. Top Down: API specification is created that (hopefully) exposes everything the front-end will need. Late discovery requirements at the front-end may be discovered.

All options are good, but #1 is recommended because it promotes RAD (Rapid Application Development) through low starting barriers, constant iteration and working in parallel.

The initial API specification document requires planning of the fundamental model and behaviours — and will be constantly revised during development. Don’t try and anticipate and build future endpoints now.

Scatter Loading

mockup

Recommended approach for new web applications, referred to as AJAX Scatter Loading:

  1. Back-end services as RESTful APIs returning JSON
    1. Modular and stateless for maximum scalability
  2. Authentication via a ‘Gatekeeper’ server using OAuth
    1. Proxy for all requests
    2. Returns a session token for future OAuth requests
    3. Stateless for scalability
  3. Front-end landing page
    1. Lightweight, generic, unsecured, uncached (to allow CSS/Javascript updates) skeleton HTML
    2. Server calls API to get OAuth session token, used to sign protected API calls
      1. Store the token on page (i.e. Javascript variable) or browser (e.g. cookie) to ensure front-end servers are stateless
      2. Tokens expire and may be associated to an IP
    3. Page populated by a series of AJAX calls to APIs

Alternatives?

Each blue area is a pagelet streamed to the page

  • Facebook BigPipe
    • Endpoints return JSON containing HTML/Javascript/CSS, called pagelets
    • Use of Chunked Encoding and Flush-tranfer to make a single HTTP request (skeleton) with pagelets streamed and rendered in sequence thereafter
    • Reduced Facebook latency by half
    • Extra complexity
    • Does not support templating or caching
    • Harder to debug
    • Violates decoupling by putting HTML in JSON
    • Minor performance gains for normal web applications (possibly worse performance if lots of caching possible)
  • WebSockets may replace REST in the future due to overhead/performance gains
    • Current lack of browser support and replacement standard

BigPipe is Scatter Loading geared for enormous scale meets maximum performance and is overkill for normal businesses, but it was the inspiration for my interest in ADD…

References