Luca Ongaro

Web Engineer

Luca Ongaro Hi! I’m Luca Ongaro, a Web Engineer from Italy currently living in Berlin. This is my blog, where I like to share random experiments and the results of some of my tinkering with Web technologies.

Scala Pattern Matching and Validation of Structured Input

Pattern Matching is for sure one of the most powerful features in Scala (kindly borrowed from Haskell). Nonetheless, developers approaching the language for the first time might sometimes wonder where it is actually useful in real life. In this post, I describe one particular real life scenario in which Pattern Matching shines: validation of structured input.

For the purpose of the argument, suppose we have an application that deals with bank accounts, expressed as IBAN codes (International Bank Account Numbers). IBAN can have different formats depending on the country, but they all follow certain rules:

  • They begin with a country code followed by two digits used for the checksum calculation
  • They must only contain digits and the 26 latin alphabetic characters from A to Z
  • It is possible to validate them by calculating a checksum

Imagine that our system needs to accept an IBAN from user input, validate it, and decompose it into its part so that we can use it. One naive way would be to create a wrapper class with different methods that takes care of validation and access to the various components of the IBAN code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Suboptimal example.
// A better solution is explained after
class IBAN( code: String ) {
  def isValid: Boolean = {
    // Perform format validation
    // and checksum validation here...
  }

  def country = {
    code.take( 2 )
  }

  def account = {
    code.drop( 4 )
  }
}

This imperative style is quite brittle. Whenever we accept an IBAN we want to validate and decompose it before use, so this solution would lead to a big amount of repetition and the risk of forgetting to handle invalid codes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Assume userInput is a user provided string,
// like "GB82123876b87876b" or "invalidIBAN"
val iban = new IBAN( userInput )

if ( iban.isValid ) {
  val account = iban.account
  val country = iban.country

  if ( country == "DE" )
    // ...German IBAN, do something
  if ( country == "IT" )
    // ...Italian IBAN, do something else
  else
    // ...IBAN from other country
} else {
  // Handle invalid IBAN. What if we forget?
}

We can improve a lot on this by creating a custom extractor, enabling pattern matching on valid IBAN strings (explaining custom extractors is not in the scope of this post, but if needed you can read this awesome article):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
object IBAN {
  def unapply( code: String ): Option[(String, String)] = {
    // Match a Regex for format
    // validation and decomposing
    val IBANPattern = """([A-Z]{2})(\d{2})([A-Z0-9]{12,27})""".r

    code match {
      case IBANPattern( country, check, account ) =>
        if ( checksumIsValid( country, check, account ) )
          // The `check` part is only used for checksum
          // validation, no need to return it
          Some( (country, account) )
        else
          None
      case _ => None
    }
  }

  private def checksumIsValid(
    country: String,
    check:   String,
    account: String
  ): Boolean = {
    // Perform checksum validation here...
  }
}

This extractor makes it possible to match a string and, in case it is a valid IBAN, extract its components. Pattern matching in this situation makes handling of valid and invalid IBAN very explicit:

1
2
3
4
5
6
7
8
// Assume userInput is a user provided string,
// like "GB82123876b87876b" or "invalidIBAN"
userInput match {
  case IBAN( country, account ) =>
    // ...valid IBAN, do something with it
  case _ =>
    // ...invalid IBAN, provide proper feedback.
}

Note how the compiler would not have let us forget to handle the invalid case. Also, we can easily handle accounts from different countries separately:

1
2
3
4
5
6
7
8
9
10
userInput match {
  case IBAN( "DE", account ) =>
    // ...valid German IBAN
  case IBAN( "IT", account ) =>
    // ...valid Italian IBAN
  case IBAN( country, account ) =>
    // ...valid IBAN from another country
  case _ =>
    // ...invalid IBAN
}

The code that handles validation and decomposition stays in one single place, only responsible of these two operation that always go together. We also removed the need of a wrapping class, so we only work with plain strings. Freed from validation/decomposition concerns, the rest of the application code also becomes very legible, with a clear and symmetric way to handle the case of invalid input.

Non-primitive Properties, CoffeeScript Inheritance and Class Macros

JavaScript’s prototypal inheritance paradigm is easy to understand, but can lead to nasty surprises when it comes to non-primitive properties. While the issue I discuss here is purely a JavaScript one, the fact that the awesome CoffeeScript syntax make it so easy to implement classes and extend them leads developers to run more frequently into this kind of situations.

The Issue with Non-Primitive Properties

The issue can occur whenever we have a CoffeeScript class (or JavaScript constructor) with a property which is not of a primitive type (basically anything which is not number, string, boolean, null nor undefined). For example, let’s have a class with an Array property:

1
2
class Person
  needs: ["eat", "drink", "breath"]

Now let’s create two instances, and let’s modify this non-primitive property on one of them:

1
2
3
4
5
6
7
8
9
10
11
12
guy   = new Person
maker = new Person

maker.needs.push "create"

console.log maker.needs
# => ["eat", "drink", "breath", "create"]
# Ok, looks good

console.log guy.needs
# => ["eat", "drink", "breath", "create"]
# Wait... what? `guy` got the "create" need added too?!?

Changing one instance led to unwanted changes to other instances too! This issue occurs because the needs property is stored in the shared [[Prototype]].

Note that if we overwritten the property on one instance everything would have been fine, since the overwritten value would live on that particular instance only. But if we only modify the property, it stays in the [[Prototype]] and the changes are shared among instances. This is why this issue can only occur with non-primitive properties: primitives are immutable.

Polyfilling the Details Tag

A common feature in many UIs is a widget that can be hidden or shown by clicking on some handle. Some examples are “accordions” or collapsible/expandable sections and navigation menus. Usually the interactivity is achieved with some JavaScript code that toggles the display property of some elements when a handle is clicked.

HTML5 adds two new tags that can theoretically be used to achieve the same effect without any JavaScript code: the details and the summary tags. Here is an excerpt from the HTML5 spec:

The details element represents a disclosure widget from which the user can obtain additional information or controls. […]

The first summary element child of the element, if any, represents the summary or legend of the details. If there is no child summary element, the user agent should provide its own legend (e.g. “Details”).

The rest of the element’s contents represents the additional information or controls.

The open content attribute is a boolean attribute. If present, it indicates that both the summary and the additional information is to be shown to the user. If the attribute is absent, only the summary is to be shown.

In other words, details is a block-level tag with a boolean open attribute that controls its visibility, and it usually have a nested summary tag that is always visible and represent the “handle” that toggles the open attribute, and thus the visibility, on and off.

Cool, isn’t it? Well, unfortunately support is currently quite poor, as at the moment only WebKit seems to properly implement it. The big question is: can we easily polyfill it and start using it in the real world?

Easy Two-Way Data Binding in JavaScript

Two-way data binding refers to the ability to bind changes to an object’s properties to changes in the UI, and viceversa. In other words, if we have a user object with a name property, whenever we assign a new value to user.name the UI should show the new name. In the same way, if the UI includes an input field for the user’s name, entering a value should cause the name property of the user object to be changed accordingly.

Many popular client-side JavaScript frameworks like Ember.js, Angular.js or KnockoutJS advertise two-way data binding among their top features. This doesn’t mean that it is too hard to implement it from scratch, nor that adopting one of those frameworks is the only option when this kind of functionality is needed. The underlying idea is in fact quite basic, and can be condensed into a 3-point action plan:

  1. We need a way to specify which UI elements are bound to which properties
  2. We need to monitor changes on the properties and on the UI elements
  3. We need to propagate any change to all bound objects and elements

DOM Selection Without jQuery

jQuery is so easy to use that sometimes we end up relying on it even for tasks that could be easily achieved using the native browser APIs. While there is nothing wrong with using jQuery, going native makes our code more portable, future proof and often more performant.

DOM selection is an example of something often performed with jQuery, but straightforward enough to achieve without any external library.

The Selectors API

The HTML5 Selectors API has been around for quite some time now, and it is supported in all modern browsers and in IE down to version 8. Its implementation is based on the querySelector family of methods, that includes four members:

  • document.querySelector( selector ) takes a CSS selector string and returns the first DOM element that matches the selector, or null if no match is found.

  • element.querySelector( selector ) does the same, but searching only among the descendants of element.

  • document.querySelectorAll( selector ) takes a CSS selector string and returns a non-live NodeList of all the DOM elements matching the selector. If no element matches the selector, an empty list is returned.

  • element.querySelectorAll( selector ) does the same as its counterpart defined on document, but again searching only among the descendants of element.