Joel Ross
Winter 2017

Model
View
Controller

https://slides.com/joelross/arch-w17-mvc/live

https://github.com/info498e-w17/lec11-mvc

Structure of the Day

  • Admin & Homework

  • MVC: Theory

  • Implementing MVC

  • MVC and the Web

https://slides.com/joelross/arch-w17-mvc/live

https://github.com/info498e-w17/lec11-mvc

https://www.flickr.com/photos/77818424@N06/

Reading Review

Questions/thoughts on "Code Smells" reading?

  • Any smells particularly stinky (or not)?

For Thursday's class: Usability Architectural Patterns (read for the basic argument)

  • Also some textbook stuff on Modeling (squeezing in)

Principle of
Separation of Concerns

"Organize software into separate components (pieces) that are as independent as possible."

Keep the data separate
from the presentation

  • Present same data in different ways
     

  • Change presentation without needing to change the data
     

  • Update data once, affect presentation everywhere (all presentations)!

Model-View-Controller

Software architecture that helps separate the  data from the presentation of that data.

Model - the data structure that represents the "information"

View - a visual presentation of the model; what the user "sees"

Controller - helps/facilitates the link between the view and the model (and the user!)

MVC Example: Music Player

Model

View

Controller

(View)

MVC Example: A Web Page

Model

View

Controller

JavaScript MVC(ish) Frameworks

Let's talk about the controller...

History: Smalltalk (1980)

Classical (Smalltalk) MVC

User interacts with the controller to manipulate the model.

Classical (Smalltalk) MVC

Model

View

Controller

Alternative MVC

User interacts with the view to modify the model; controller mediates this and connects to storage

Alternate MVC

"Proper" MVC Interaction

  1. User interacts with the view

  2. View tells controller what to do

    1. Controller tells model to change state

      • Model changes state, notifies view

    2. Controller tells view to change state

      • View changes state, asks model for information

"Proper" MVC Interaction

MVC Key Ideas Quiz!

  1. The model is the information in the system
  2. The view is the data structure (e.g., array) for the model
  3. The controller connects the model and view
  4. Each model has a single unique view
  5. Models have no knowledge of their views and are totally independent from them
  6. Models and views can only talk to the controller, not to each other
  • True: False:
  • True: False:

  • True: False:
  • True: False:
  • True: False:

  • True: False:

Some MVC Variants

Three-Tier Architecture

MVC and Patterns

MVC and Observer Pattern

MVC and Observer Pattern

/* pseudocode! */

//subject
class Model {
  register(observer){ }
  remove(observer){ }
  notifyAll() { }

  getState() { }
  
  setState(newState){
    this.state = newState;
    notifyAll(); //updated!
  } 
}

//observer
class View {
  constructor(model) {
    this.model = model;
  }

  notify() {
    display(this.model.getState())
  }
}
//registrar/middle-man
class Controller {
  constructor(model, view) {
    this.model = model;    
    this.view = view;

    //register the observer
    this.model.register(view);
  }
  
  //when user does stuff
  userDoAction(){
    //process action...
    this.model.setState(newState);
  }
}

//execute the program
function main() {
  let model = new Model();
  let view = new View(model);
  let ctrl = new Controller(model, view);
  ctrl.userDoAction();
}

MVC and Strategy Pattern

MVC and Strategy Pattern

class View {
  constructor(model){
    this.model = model;
    
    //view elements
    this.button = new Button();
  }

  setController(controller) {
    this.controller = controller;
  }

  //when button is pressed
  performButtonPress(){
    //delegate to controller
    this.controller.userDoAction();
  }

  notify() {
    display(this.model.getState())
  }

  //...  
}

//registrar/middle-man
class Controller {
  constructor(model, view) {
    this.model = model;    
    this.view = view;
    view.setController(this); //assign

    //observer pattern
    this.model.register(view);
  }
  
  //when user does stuff
  userDoAction(){
    //process action...
    this.model.setState(newState);
  }
}

//execute the program
function main() {
  let model = new Model();
  let view = new View(model);
  let ctrl = new Controller(model, view);
  view.performButtonPress();
}

MVC and Composite Pattern

MVC Practice:
Tic-Tac-Toe

Proof of a Good MVC

Is your app skinnable?

Another view!

TypeScript and the Web

TypeScript compiles to plain JavaScript, so it runs great in a webpage!

...except loading modules gets tricky

<!-- Which one to load first?! -->
<script src="dist/model.js"></script>
<script src="dist/view.js"></script>
<script src="dist/controller.js"></script>
<script src="dist/index.js"></script>

Bundling

Solution: bundle (combine) all of the modules into a single file that can be optimized and downloaded at once.

<!-- one file for all your js needs -->
<script src="dist/bundle.js"></script>

Since TypeScript is compiled anyway,
why not compile into a single file?

Bundling with Webpack

# install dependencies (listed in package.json)
npm install

Install Webpack and dependencies

Create webpack.config.js file (included)

Use webpack to compile the code

# global, watch mode
webpack --watch

# installed locally
./node_modules/.bin/webpack --watch

# dev server (auto reload)
webpack-dev-server --inline --open

A jQuery View

display() {
  let gamebox = $('#game-box');
  gamebox.empty(); //clear old display

  // make grid of buttons
  for(let i=0; i<this.game.size; i++){ //row
    let row = $('<div>'); //a row for the button
    for(let j=0; j<this.game.size; j++) {
      let player = this.game.getPiece(i,j);
      if(player === undefined) player = -1;

      let button = $('<button class="btn btn-default">' +
                        this.playerSymbols[player+1] +
                     '</button>')
      button.click((e) => this.handleClick(i,j)); //closure!!
      row.append(button);
    }
    gamebox.append(row);
  }

  //show winner, if any
  let winner = game.getWinner();
  if(winner !== undefined){
    this.showWinner(winner)
    $('button').attr('disabled','disabled'); //disable all the buttons
  }
  else {
    this.showPrompt(); //show prompt for next move
  }
}

ACTION ITEMS!

For next week...

  • Finish the Antz (for realz)

  • Readings (Usability Architectural Patterns; Modeling)

 

Thursday: See readings!