Sunday 11 January 2015

JavaScript Design Patterns (Composite, Façade, Adapter)

JavaScript Design Patterns


 Composite Design Pattern 
  • Dfn: 
    • Dynamic User Interfaces achieved by replacing Groups of Objects with a Single Object organised in a Tree Hierarchical Structure in order to leverage functionality such that a Single Command (Function Call) on a Composite Object (Top-Level Parent) that will traverse an entire Nested tree of Collection(s) (composition) of many Sub-Objects and initiate Delegation with the same implementation method / Operation (Complex Behaviour) Recursively to its now independent Loosely Coupled bottom-level Leaf Objects (Leaves do not have Children) whose implementation may be hidden from clients, which provides choice and flexibility in selection of preferred Data Structures used to hold the Children, which may include Arrays, Objects, etc. All Objects within a Composite (including Leaves) must implement and respond to the same Composite Interfaces var ___ = new Interface(___); that must be defined for each Object Class (perhaps using a UML Diagram, accompanied by Duck Typing using Interface , or Type Checking), but Children are not Subclasses and do not Inherit from the Composite. 
  • Application Examples: 
    • Dynamic Input Form with Operations Saving, Restoring, Resetting, Validation, AJAX requests
    • Dynamic Media Gallery with Operations Drag-and-Drop, Hiding, Showing 
  • Usage Approach:
    • Super (Composite) View that has Children (has one or many) that are initially Unknown (Contents and Quantity) Partial (Leaf) Views that may be Grouped into Sets (Composite) of Partials and are potentially Different for each User and Dependent on User Interaction leverages Loosely Coupling:
      • Operations of Inputs is performed Dynamically on the Composite Design Pattern Framework with a Single Command that is called Recursively on all the Composites bottom-level Leaves / Children (not Tightly Coupled to specific input fields) by means of wrapping HTML elements inside JavaScript Objects
      • Additionally Operations and Levels in the Hierarchy may be added to the Modular Composite Interface of the Composite Design Pattern Framework to achieve higher Granularity on Operations that may be called (without affecting existing Object Classes)
  • Benefits: 
    • Loosely Coupled
    • Modular
    • Maintainable
    • Reuse (DRY)
    • Refactorable
  • Warnings: 
    • Cookies should not be used as a Data Structure to Store User Data and Children (Data Validity easily hacked, length restrictions may strip and cause missing data, contained in HTTP Headers of all requests causing performance lag)
    • DOM Nodes should not be used as a Data Structure to Store Children elements to avoid Memory Leaks in browsers caused by necessity for them to maintain reference to their JS wrapper class to implement operations. Use an Array instead.
    • Documentation must highlight the Restrictions that elements cause to the Composite's usefulness, and the Performance Cost each Operation supports, since in large hierarchies the call will still initiate complete traversal to all children in a tree.


 Façade Design Pattern 
  • Dfn: 
    • Organising Pattern that Decouples (Loose Coupling) and conveniently Wraps an Object, changing the Interface it presents to the world by simplifying it and making assumptions (rather than providing extra options like the Adapter Design Pattern) to simplify common and repetitive tasks involved in the process of accessing and modifying complex Classes (contained in an App) and Objects from the Client code (that calls it) in order to save time and maintain Efficiency to meet Demands
    • Utility Libraries
      • Convenience Methods created to increase Flexibility (combining methods) whilst maintaining Granularity (also separately retaining the individual methods that have been combined for convenience) along with ease of interacting (user-friendly presentation of an Object's features) with complex subsystems indirectly, with less likelihood of errors found directly (error checking performed behind the scenes), by combining several existing methods into one
  • Application Examples
    • Shortcut Icons (acts as Facade Interface) navigate deeply nested files and directories
    • Operations on OS GUI (acts as Facade Interface) that indirectly runs commands in background to computer data and functionality 
    • Adding an Event Function (Convenient Methods encapsulates detection code in single location acting as Facade Interface) allows Event Listeners to be added to DOM nodes, by performing cross-browser determination and branching code to detect capabilities and differences between browsers (using Object Detection and Browser Sniffing techniques using Lazy Loading at load time by Abstraction and execution once instead of on every call to speed up the app) with the heavy lifting performed under the hood for implementation of appropriate event listener syntax or event attachment technique to use (reuse hidden low-level code to check against browser differences to avoid repeated manually checking)
    • Abstract cross-browser differences into a Custom Event Utility with Facade Methods that provide a consistent Interface (act as a Facade Interface) to work comfortably (or alternatively with Third-Party Libraries such as Prototype, jQuery, YUI), easily interacting with JS functions built into each Browsers and deal with cross-browser event handling by Batching Utilities into Single Set, and using a Singleton Design Pattern containing Static Methods within a Namespace (Common Methods i.e. getMail, sendMail, archive, or alternatively using a Publish / Subscribe Design Pattern).
    • Wrapper Library or Shims (act as Facade Interface) to help Interface with a Collection of poorly designed APIs by Wrapping them in Single API (with good design)
    • Set Multiple Styles to Multiple HTML Elements' CSS Style Properties at same time by creating a Utility Function (acting as a Facade Interface using the Facade Pattern) to simplify matching HTML Elements and setting CSS Styles in Bulk, whereby we Batch all the HTML Elements and CSS Styles functionality together (under the hood without the client code being aware of the details or being broken by modifications) and trigger it all with just a Single Function Call
    • Error Logging
    • Tracking Page View Stats
  • Benefits: 
    • Loosely Coupled
    • Maintainable
    • Understandable
    • Reuse (DRY)
    • Abstract-Oriented
  • Warnings: 
    • Practicality of Operations must be considered to avoid unnecessary drag by Expensive routines (i.e. a simple task may only need a few simple Facade Functions rather than an entire JS Library)
    • Multiple Constituent Functions may be preferable to a Single Monolithic Facade Function to achieve desired Granularity

 Adapter Design Pattern 
  • Dfn: 
    • Decouples (Loose Coupling) of a Wrapper Object (of the Adapter Design Pattern) Abstraction from its Implementation (enabling independent variation), by using a thin layer of code between incompatible method calls is used to encapsulate an existing Interface that has otherwise Incompatible Classes (which prevents clients from accessing the API) with another different Interface by Migrating and adapting them by reconciling differences in syntax and allowing them to interact together through conversion to bridge differences and achieve Compatibility (it is different from the Facades Design Pattern, as it doesn't remove abilities or simplify the Interface for Convenience sake)
  • Application Examples
    • Interfaces of designed Classes may be Incompatible with Existing APIs. Adapter Design Pattern may be used to allow interaction with the API from these Classes without modifying them directly (and possible breaking them)
    • Existing API Interfaces may change, requiring all client code to be updated to be Compatible with the New Interface. Development of a Client Adapter that implements the New Interface is necessary to survive
    • Adapting between two Libraries by creating two Adaptor Methods to convert the difference between their Interfaces
    • Adapters to create Different Interfaces easier for clients to use
    • Adapter created to access a New API (different Interfaces) instead of an Expensive entire Codebase Rewrite, by Wrapping and handling the logic within a New Interface for an Existing Class without breaking existing implementations
  • Warnings: 
    • Considerations when choosing Set of Utilities for a Library include
      • Impact Determination (Development Suitability)
        • Match with Coding Style of Developers
        • Ease of Implementation
        • Incompatibility with Existing Codebase
      • Interchangeability with Alternative Libraries (Decoupled without requiring changes to Codebase) to improve Performance, Security, Design
      • Compatibility with Intermediary Sets of Adapters during migration from Existing API to New API
      • Expense of an Entire Code Rewrite VS New Adapter Library
    • Consideration when determining between Entire Code (API / Library) Rewrite VS New Adapter Library
      • Extent that Existing API / Library is Standardised
        • Avoid unnecessary development overhead (new set of Utilities that must be supported) of an Adapter when the Existing (Legacy) API or the New Interface proposed to be made compatible are incomplete

References:
  • Chapters 9 - 11, Pro JavaScript Design Patterns by Ross Harmes and Dustin Diaz
Note: Refer to similarities between these JavaScript Design Patterns and the iOS Design Patterns highlighted in one of my previous blog posts

Books
  • 60% Progress Pro JavaScript Design Patterns



Monday 5 January 2015

Thursday 1 January 2015

Functional Programming (PureScript)

PureScript Simple DOM (created by Ashley Towns .. and other Open Source contributors)


Important Note: The following was prepared before having read any PureScript books (and only after just having managed to get PureScript Compiler installed thanks to help from Hardy Jones). See below PureScript By Example Git Repo containing working solutions based my application of code samples and custom commentary from the textbook.
  • Link to GitHub Repo here (of the PureScript Simple DOM)
  • Setup
    • Install PureScript  with the commands cabal install cabal-install and cabal install purescript (recommend avoiding having to run 'cabal update', as it breaks GHCi for Haskell), which downloads, builds, configures, and installs:
      • monad-unify-0.2.2
      • pattern-arrows-0.0.2
      • ansi-wl-pprint-0.6.7.1
      • optparse-applicative-0.11.0.1
      • purescript-0.6.2
    • Refer to the following Issue for help I got and Lessons Learnt showing how to install PureScript https://github.com/aktowns/purescript-simple-dom/issues/18
    • Check your current PATH by typing the following in terminal $PATH
    • When you run which cabal it should return the location of the Cabal Executable (i.e. /Users/<your_user_name>/Library/Haskell/bin/cabal)
    • Check where your Cabal Executables are installed by going to the ~/.cabal  cd ~/.cabal directory and inspecting the contents of a where-is-my-stuff.txt File by opening it (i.e. subl where-is-my-stuff.txt).
    • Edit your ~/.bash_profile File (i.e. subl ~/.bash_profile) and add the following line to it to add the directory containing Cabal Executables to the PATH (which will include subdirectories of ~/Library/Haskell/bin as well): export PATH="$HOME/Library/Haskell/bin:$PATH" 
    • Download the latest PureScript Releases and extract it (i.e macos.tar.gz) into the PATH directories) such as ~/Library/Haskell/bin. This will create a subdirectory called /purescript (i.e. ~/Library/Haskell/bin/purescript), which contains the PureScript Compiler executables (allowing you to run commands like psc --help)
    • Finally, reload your current shell by source-ing the ~/.bash_profile with source ~/.bash_profile, which will ensure that when you run cabal --version it returns confirming that the cabal-install version that is installed matches the same version that it built, configured, and installed when you first ran cabal install cabal-install
    • Install and update NPM and Grunt project dependencies npm install -g grunt grunt-init grunt-cli bower and npm update -g grunt grunt-init grunt-cli bower
    • Note that this Grunt project has already been pre-configured with a package.json file and a Gruntfile.js
    • Install Bower dependencies bower install
    • Build with Grunt grunt (uses the Zombie Gem to perform headless Browser testing of the DOM using Node.js)
    • View Grunt commands grunt --help
    • View PureScript Compiler commands  psc --help
    • Try the PureScript Compiler REPL Interface  psci
  • About the Toolkit
    • PureScript Simple DOM is a cross-platform GUI Toolkit (lower level library) wrapper that aims to translate underlying JavaScript API methods into PureScript equivalents to enable imperative-style UI programming using the functional programming paradigm. 
    • PureScript Simple DOM provides an API that may be understood by referring to the Module Documentation (API.md).
    • Since PureScript is a purely functional language (does not support object-orientation or mutable variables without use of IO Actions), the translation is not as simple as translating from JavaScript to another imperative language (using wrappers for marshalling data types and mapping functions and objects), instead the PureScript Simple DOM toolkit wrappers must translate underlying JavaScript API methods into the special Eff Actions that must be caged in the Eff Monad (defined in the PureScript Prelude Module), similar to in Haskell where IO Actions (IO Functions that create IORef wrappers, which represent a pointer to a pure value, enabling event-driven UI callbacks to read and write to the global application state) may be caged in the IO Monad. The Eff Monad handles native effects whilst generating efficient JavaScript.
  • Understanding the GitHub Repo

/bower_components/*  { Bower dependencies installed after running bower install }

/node_modules/*  { Node.js NPM dependencies installed after running npm install }

/outputs/*  { this directory is created as a result of running grunt }

/js/*  { requires Node.js dependencies and called by a Grunt command to run the PureScript tests against the HTML file }

/src/*  { contains individual Safe PureScript Modules (and Unsafe ones too in a subdirectory) that match the API Module Documentation }

/tests/* { contains HTML template and PureScript file that uses QuickCheck to verify that PureScript Simple DOM interacts (read, write) with the Browser Window, HTML Document and Elements.

.bowerrc { generates the defined directory 'bower_components' and installs all bower dependencies in sub-directories after running  bower install }

API.md
  • The Module Documentation structure is as follows:
    • AJAX
      • Algebraic Data Types (ADTs) Type Annotation definitions using the data keyword and the :: symbol (compiler infers correct type) (i.e. data <type_constructor> :: <data_constructors> )
      • Function definitions (using currying) in the Type Signatures (i.e. <argument_1> -> <argument_2> -> <argument_3> )
      • Existential Types using the forall keyword to inform the compiler not to care about the type of data from a Type Class, eliminating the need for the type variable 
    • HTML Document
    • HTML Element
    • URI Encoding, Decoding, Parameterization, and JSON Conversion
    • UI Event Handling
    • Web Browser Navigator Info
    • DOM Arrows { Syntactic Sugar that defines Combinators that store DOM Arrow instances of Eff, Maybe, and Just HTML Element ordinary Functions that are applied to Functors (which contain only Values) and extended into Applicative Functors. Note: Arrows define computations that may be Chained. Monads are a computational strategy that define a container for chainable Eff Functions (Actions) and are a subset of Arrows }
    • Web Browser DOM Component Types
    • Unsafe AJAX
    • Unsafe HTML Document
    • Unsafe HTML Element
    • Unsafe UI Event Handling
    • Unsafe Web Browser Navigator Info
    • Unsafe DOM Arrows 
    • Unsafe Utilities
    • Unsafe Web Browser Window Attributes
}

bower.json { bower.json is a manifest of metadata for Bower that includes Package definitions and dependencies for development and production environments. The following command bower install is run from a terminal to install:

  • purescript-foldable-traversable#0.1.6 bower_components/purescript-foldable-traversable
    • ├── purescript-arrays#0.3.0
    • ├── purescript-control#0.2.1
    • ├── purescript-either#0.1.4
    • ├── purescript-maybe#0.2.1
    • ├── purescript-monoid#0.1.5
    • └── purescript-tuples#0.2.3
  • purescript-strings#0.4.2 bower_components/purescript-strings
    • └── purescript-maybe#0.2.1
  • purescript-math#0.1.0 bower_components/purescript-math
  • purescript-quickcheck#0.3.2 bower_components/purescript-quickcheck
    • ├── purescript-arrays#0.3.0
    • ├── purescript-either#0.1.4
    • ├── purescript-exceptions#0.2.2
    • ├── purescript-foldable-traversable#0.1.6
    • ├── purescript-math#0.1.0
    • ├── purescript-maybe#0.2.1
    • ├── purescript-random#0.1.1
    • ├── purescript-strings#0.4.2
    • └── purescript-tuples#0.2.3
  • purescript-sets#0.1.1 bower_components/purescript-sets
    • ├── purescript-arrays#0.3.0
    • ├── purescript-foldable-traversable#0.1.6
    • ├── purescript-maps#0.1.5
    • ├── purescript-maybe#0.2.1
    • └── purescript-tuples#0.2.3
  • purescript-tuples#0.2.3 bower_components/purescript-tuples
    • ├── purescript-arrays#0.3.0
    • ├── purescript-control#0.2.1
    • └── purescript-monoid#0.1.5
  • purescript-maybe#0.2.1 bower_components/purescript-maybe
    • └── purescript-control#0.2.1
  • purescript-arrays#0.3.0 bower_components/purescript-arrays
    • ├── purescript-control#0.2.1
    • └── purescript-maybe#0.2.1
  • purescript-random#0.1.1 bower_components/purescript-random
  • purescript-exceptions#0.2.2 bower_components/purescript-exceptions
  • purescript-control#0.2.1 bower_components/purescript-control
  • purescript-either#0.1.4 bower_components/purescript-either
    • └── purescript-control#0.2.1
  • purescript-monoid#0.1.5 bower_components/purescript-monoid
    • ├── purescript-arrays#0.3.0
    • └── purescript-maybe#0.2.1
  • purescript-maps#0.1.5 bower_components/purescript-maps
    • ├── purescript-arrays#0.3.0
    • ├── purescript-foldable-traversable#0.1.6
    • ├── purescript-math#0.1.0
    • ├── purescript-maybe#0.2.1
    • ├── purescript-strings#0.4.2
    • └── purescript-tuples#0.2.3
 }

Gruntfile.js PureScript Simple DOM is a Grunt project that uses Gruntfile.js to configure tasks. When run with the command grunt, it checks that Grunt is installed locally using the Node.js require() system, and if it is found then the Grunt CLI loads the local installation of the Grunt library, and applies and executes the tasks that have been configured in the Gruntfile.js. 
The Grunt "wrapper" function module.exports = function(grunt) { currently passes configuration data to the grunt.initConfig method

Custom project-specific tasks are defined in external .js files and loaded using the grunt.loadNpmTasks method, including: 

  • grunt-contrib-copy
  • grunt-contrib-clean
  • grunt-execute
  • grunt-purescript


The Gruntfile is currently configured so that when:
  • grunt or grunt default is run, it Registers the Tasks:
    • clean
    • make
    • test
  • grunt test is run, it Registers the Tasks:
    • pscMake:tests
    • copy
    • execute:tests  
  • grunt make is run, it Registers the Tasks:
    • pscMake:lib
    • docgen
    • dotPsci (creates a .psci file)
When I first ran grunt errors were encountered, prompting me to raise this Issue on GitHub (initially because I couldn't get PureScript in my PATH, but now this is resolved and psc commands are recognised). To get all the tests to pass, just comment out the final 'userAgent' test on Line 122 (i.e. replace Line 122 with   -- userAgent navigator >>= (\name -> quickCheck' 1 $ name == "Mozilla/5.0 Chrome/10.0.613.0 Safari/534.15 Zombie.js/2.0.0-alpha31")). Currently I'm trying to figure out why replacing the userAgent value with the userAgent value that is found when using Chrome Dev Tools, running ```self```, and expanding the Window object (i.e. Window > clientInformation > userAgent) 





.psci { configuration file for the interactive mode of the PureScript PSC Compiler, which is generated when grunt make command is run  }

package.json { package.json is a manifest of metadata for this Grunt project that installs the Modules and associated Dependencies from the /node_modules/ directory when the Node.js Package Manager command npm install is run from a terminal. The output installs:
  • ws@0.6.4  node_modules/zombie/node_modules/ws
  • contextify@0.1.11 node_modules/zombie/node_modules/jsdom/node_modules/contextify
  • grunt-contrib-copy@0.5.0 node_modules/grunt-contrib-copy (Copy files and folders)
  • grunt-purescript@0.5.3 node_modules/grunt-purescript
  • grunt-execute@0.1.5 node_modules/grunt-execute
  • grunt-contrib-clean@0.5.0 node_modules/grunt-contrib-clean (Cleans files and folders)
    • └── rimraf@2.2.8
  • grunt@0.4.5 node_modules/grunt
    • ├── which@1.0.8
    • ├── dateformat@1.0.2-1.2.3
    • ├── eventemitter2@0.4.14
    • ├── getobject@0.1.0
    • ├── colors@0.6.2
    • ├── rimraf@2.2.8
    • ├── async@0.1.22
    • ├── hooker@0.2.3
    • ├── grunt-legacy-util@0.2.0
    • ├── exit@0.1.2
    • ├── nopt@1.0.10 (abbrev@1.0.5)
    • ├── lodash@0.9.2
    • ├── coffee-script@1.3.3
    • ├── glob@3.1.21 (inherits@1.0.0, graceful-fs@1.2.3)
    • ├── minimatch@0.2.14 (sigmund@1.0.0, lru-cache@2.5.0)
    • ├── underscore.string@2.2.1
    • ├── iconv-lite@0.2.11
    • ├── findup-sync@0.1.3 (glob@3.2.11, lodash@2.4.1)
    • ├── grunt-legacy-log@0.1.1 (underscore.string@2.3.3, lodash@2.4.1)
    • └── js-yaml@2.0.5 (esprima@1.0.4, argparse@0.1.16)
  • zombie@2.5.1 node_modules/zombie
    • ├── ms@0.7.0
    • ├── lazybird@1.0.0
    • ├── mime@1.2.11
    • ├── debug@2.1.1 (ms@0.6.2)
    • ├── iconv-lite@0.4.5
    • ├── tough-cookie@0.12.1 (punycode@1.3.2)
    • ├── eventsource@0.1.4 (original@0.0.5)
    • ├── bluebird@2.5.3
    • ├── request@2.51.0 (caseless@0.8.0, aws-sign2@0.5.0, json-stringify-safe@5.0.0, forever-agent@0.5.2, tunnel-agent@0.4.0, stringstream@0.0.4, oauth-sign@0.5.0, qs@2.3.3, node-uuid@1.4.2, mime-types@1.0.2, combined-stream@0.0.7, form-data@0.2.0, http-signature@0.10.0, bl@0.9.3, hawk@1.1.1)
    • ├── ws@0.6.4 (options@0.0.6, ultron@1.0.1, nan@1.4.1)
    • └── jsdom@1.4.0 (browser-request@0.3.3, xmlhttprequest@1.6.0, cssom@0.3.0, nwmatcher@1.3.3, parse5@1.3.0, htmlparser2@3.8.2, cssstyle@0.2.22, contextify@0.1.11)
}



PureScript By Example (created by Luke Schoen)



Sublime Text 2 Plugin for PureScript (created by Hardy Jones)

Link to GitHub Repo here

Setup
  • Copy the Git Repo into a new sub-directory in the Sublime Text 2 Packages directory 
    • cd ~/Library/Application\ Support/Sublime\ Text\ 2/Packages
    • git clone https://github.com/joneshf/sublime-purescript
  • Restart Sublime Text 2
PureScript Syntax Highlighting & Code Snippets
  • After Setup, go to Sublime Text 2 menu 
    • View > Syntax > PureScript
  • Enter a Code Snippet keyword (until "instance      instance" appears in the Drop-Down) and then select "instance      instance" (using Up/Down Keys) and then Press Tab and PureScript "instance" code block template will auto-populate (i.e. for example, the 'instance' keyword may be used, as it is contained between the <tabTrigger></tagTrigger> tags of the /Snippets/instance.sublime-snippet file) )

    Reference Documentation (Sublime Text 2 Plugins) 


    Events
    •  ATTENDING Ruby Conference (RubyConf) (Melbourne, 4 - 7th Feb 2015)
      • 7pm, Wed 4 Feb, Opening Party, Trunk Bar & Restaurant, 275 Exhibition St, Melbourne
      • 4:30pm, Sat 7th Feb, Family Picnic, Flagstaff Gardens, Corner of Williams St & La Trobe St, Melbourne
      • 8pm, Sat 7th Feb, After Party, City of Melbourne Bowling Club, Within Flagstaff Gardens near Dudley St, Melbourne

    Books
    • 20% Progress Developing Web Applications with Haskell and Yesod
    • 20% Progress Graphical User Interfaces in Haskell (by Gideon Sireling)
    • Pending UML for Java Programmers
    • TODO PureScript by Example (LeanPub)

    Links

    IN PROGRESS (NOT WORKING) Deploying Haskell on Heroku