Scheming – What do we use it for?



Scheming – What do we use it for?

0 0


scheming-presentation

Presentation about the Scheming library and its usefulness

On Github NicholasBoll / scheming-presentation

Scheming

by Nicholas Boll

Who Am I?

  • @NicholasBoll
  • nicholas.boll@gmail.com
  • I'm a Software Engineer at LogRhythm
  • I've been writing software for a long time

What is Scheming?

  • Created by Erin Noe-Payne
  • Isomorphic, reactive, typed JavaScript Objects!

What does it provide?

  • Typed object schemas
  • Nested schemas
  • Validators
  • Observe (deep) model changes
  • Batched change resolution
  • Small size (18k min, 6k gzip)

What doesn't it provide?

  • Database communication

Example:

Scheming = require('Scheming')

User = Scheming.create 'User',
  name :
    type : String
    required : true
  email :
    type : String,
    required : true
    validate : (val) ->
      if val.match('@')
        return true
      else
        return 'An email address must have an @ symbol!'
  birthday : Date
  password :
    type : String
    setter : (val) ->
      return md5(val)

Group = Scheming.create 'Group',
  name : String
  dateCreated : {type : Date, default : -> Date.now()}
  users : [User]

jane = new User
  email : 'jane.gmail.com'
  birthday : '9/14/86'
  password : 'p@$$w0rd!'

console.log Person.validate jane
# {name : 'Field is required.', email: 'An email address must have an @ symbol!'}

jane.name = 'jane'
jane.email = 'jane@gmail.com'

console.log Person.validate jane
# null
        

Nesting

Car = Schema.create
  make : String
  model : String

Person = Schema.create
  name : String
  car : Car

mark = new Person {name : 'mark'}

# Explicit construction and assignment
# At the time of assignment, civic is already an instance of Car
# so the Car constructor will not be invoked a second time
civic = new Car {make : 'honda', model : 'civic'}
mark.car = civic

# Implicit construction
# At the time of assignment, the value is a plain object. Therefore
# the object is passed to the Car  constructor (or in strict mode,
# an error is thrown)
mark.car = {make : 'toyota', model : 'corolla'}
mark.car instanceof Car # true
        

Validation

Person = Scheming.create
  name :
    type : String
    validate : [
      -> return "Error number one"
      -> throw new Error "Error number two"
      -> return true
      -> return false
    ]

bill = new Person()

errors = Person.validate bill
# returns null, because bill object does not have a name defined, and name is not required

bill.name = 'bill'
errors = Person.validate bill
# {name : ["Error number one", "Error number two", "Validation error occurred."]}
        

Watches

Person = Scheming.create 'Person',
  name : String
  age : Number
  mother :
    type: 'Schema:Person'
    default: {} # create implicit model - otherwise will default to undefined
  friends : ['Schema:Person']

lisa = new Person()

# Sync changes are rolled up
lisa.name = 'a'
lisa.name = 'b'
lisa.name = 'lisa'

# Async change resolution
lisa.watch 'name', (newVal, oldVal) ->
  # this listener is called once
  newVal == 'lisa'
  oldVal == undefined

lisa.mother.name = 'jane'

# Deep watch
lisa.watch 'mother', (newVal, oldVal) ->
  newVal.name == 'jane'
  oldVal.name == undefined
        

What do we use it for?

  • AngularJS components

Component Models

  • Data contract
  • Put the "M" in *VC
  • Ditch $scope.$watch
  • Ditch 2-way data bindings
  • Move WAY past 2,000 bindings

Performance

  • Change resolution on rAF
  • Assignment is more expensive
  • (Deep) watches are cheap
  • Can disconnect component's $scope
  • Don't need $scope.$apply() for changes

Questions?

Scheming by Nicholas Boll