ES6

in production

Goals

  • JavaScript in 2016
  • All things ES6
  • What's next? (ES2016)

Bård

@bardguyver

About me

Front-End Dev @ CDD

About me

BaþufriþuR

baþu

friðr

Bárðr

Bård

About me

About me

About me

About me

About me

About me

Agenda

JavaScript in 2016

ES6/2015

browser support

Babel   

New features

Updating ES5 library

ES7/2016 and beyond

Final thoughts

Agenda - features

arrows

classes

enhanced object literals

template strings

destructuring

default + rest + spread

let + const

iterators + for..of

generators

unicode

modules

modules

module loaders

map + set

weakmap + weakset

proxies

symbols

subclassable built-ins

promises

library APIs

binary and octal literals

reflect api

Agenda - features

let, const

destructuring

arrow functions

blocks

template strings

modules

def. parameters

concise methods

for of

classes

object.assign

promises

strings

bonus level

final exams

parameters

2

1

3

5

4

6

8

7

9

11

10

12

13

14

?

99

Agenda - quiz slides

get ready...

Quiz time!

Who is this?

Quiz time!

Bennett from commando!

JavaScript in 2016

JavaScript in 2016

JavaScript in 2016

JavaScript in 2016

JavaScript in 2016

  • SPA's are hard to do (right)
  • State is hard to manage

JavaScript in 2016

JavaScript in 2016: 

Image source: https://blog.formidable.com/using-react-is-a-business-decision-not-a-technology-choice-63c4641c5f7#.2crsz2ky1

JavaScript in 2016

Redux

JavaScript in 2016: Tay

JavaScript in 2016: Bower

JavaScript in 2016

JavaScript in 2016

JavaScript in 2016

JavaScript in 2016: left-pad

Azer

vs

kik

(messaging app)

left-pad

module.exports = leftpad;
function leftpad (str, len, ch) {
    str = String(str);
    var i = -1;
    if (!ch && ch !== 0) ch = ' ';
    len = len - str.length;
    while (++i < len) {
        str = ch + str;
    }
    return str;
}

JavaScript in 2016

The aftermath

  • Better unpublishing rules from npm
  • A lot of angry blog posts
  • Questions about external dependencies

JavaScript in 2016

ES2015

  • Adopt features one at a time!
  • Landed in a turbulent time
  • Not an all-or-nothing deal

ES2015 - Names & acronyms

ECMA

ECMAScript

javaScript

VBScript

JScript

ActionScript

LiveScript

Harmony

TC39

ES.next

ES2015

ES2016

ES2017

ES2

ES3

ES4

ES5

ES6

ES7

ES8

ES2015 - Names & acronyms

JavaScript

1995

2009

ECMAScript

 (liveScript)

1996

ECMA

jScript

ES2, ES3

98/99

ActionScript

VBScript

JavaScript

ES5

2015

ES6

TC39

ES3.1

ES.next

Harmony

ES4

ES2016

ES2017

ES7

ES8

ES2015: Stages

Stage 0: strawman

Stage 1: proposal

Stage 2: draft

Stage 3: candidate

Stage 4: finished

ES2015: Stages

One of the things the committee really focuses on, and this is something that's been really healthy, is primitives.

We're looking not necessarily to innovate. We're looking to find what people are really doing out there on the web. We're looking to enable them to build features themselves.

ES2015: Stages

Quiz time!

20

150

x

3

Quiz time!

20

150

x

3

= 1000

ES2015 - Features

live slides:

let, const

1

let, const

`let` and `const` are new block-scoped variable declaration statements.

let, const: hoisting

// Hoisting 101

function hoistMe() {
    var x = 31;
    var x = 71;
    if (true) {
        console.log(x);
    }
    console.log(x);
}
// Hoisting 101

function hoistMe() {
    var x = 31;
    if (true) {
        var x = 71;
        console.log(x);
    }
    console.log(x);
}
// Hoisting 101

function hoistMe() {
    var x = 31;
    if (true) {
        var x = 71;
        console.log(x); // 71
    }
    console.log(x); // 71
}

let, const: Example

// var, let and const are available in all sub-blocks
    
var varName = 'Angus';
let letName = 'Angus';
const constName = 'Angus';

if (true){
    
    console.log(varName);   // Angus
    console.log(letName);   // Angus
    console.log(constName); // Angus
    
    varName = 'Donna';
    letName = 'Donna';
    constName = 'Donna'; // ERROR!
        
}

console.log(varName);   // Donna
console.log(letName);   // Donna
console.log(constName); // Angus

let, const: Example 2

// But only var is available outside of block scope

if (true){

    var varName = 'Angus';
    let letName = 'Angus';
    const constName = 'Angus';
        
}

console.log(varName);   // Angus
console.log(letName);   // letName is not defined
console.log(constName); // constName is not defined

let, const: let

for (let i = 0; i > 5; i++) {
    console.log(i); // 0, 1, 2, 3, 4
}

for (let i = 0; i > 5; i++) {
    console.log(i); // 0, 1, 2, 3, 4
}
        
console.log(i); // ReferenceError: i is not defined

if (true){
    let letName = 'fritz';
}

console.log(letName); // ReferenceError: i is not defined

let, const: const

// const with int value
const year = 2016;

year = 2017; // Error!


const person = {};

person.name = 'Ingrid';
person.age  = 32;

person = { 'name' : 'Ingrid' }; // Error!
person = 'test'; // Error!

let, const: Best practice

let, const: Use case

const

let

var

New default variable declaration statement

Use to indicate variable will change over time

Use to indicate legacy code

let, const: Best practice

const is the new var.

But: Don't blindly refactor all var instances as this can create side effects. (hoisting)

Template strings

2

Template strings

Template strings allow you to mix strings, variables and functions.

template strings: Example

// ES5
var person = {
    name: 'Jon Snow',
    status = 'dead'
}

console.log('I\'m pretty sure ' + person.name + ' is ' + person.status);


// ES6
const person = {
    name: 'Jon Snow',
    status = 'alive'
}

console.log(`I've read online that ${person.name} is ${person.status}`);

template strings: Example

// No more newline characters


// ES5
console.log('string text line 1\n\ string text line 2');


// ES6
console.log(
    `string text line 1
    string text line 2`
);  

template strings:  Use case

  • Use for string & variable mixing
  • Use for multi-line strings

Default parameters

3

Default parameters

Allows parameters to be given a default value.

Default parameters: Example

// Basic example

function add(x=0, y=0) {
    return x + y;
}

add(); // 0
add(1); // 1
add(2, 3); // 5

Default parameters: Example

// ES5
var datingProfile = function(name, interests) {
    
    if (name === undefined) { 
        name = 'John'; 
    }
    
    if (interests === undefined) { 
        interests = 'most forms of data processing';
    }
    
    return 'Hi, I\'m ' + name + ', and I like ' + interests;
};
// ES6
const datingProfile = function(name = 'Sal', interests = 'eels') {
    return `Hi, I'm ${name}, and I like ${interests}`;
};

Default parameters: Use case

Remove boilerplate

Quiz time!

Who is this?

Answer:

Murdoc!

MacGyver's nemesis...

Arrow Functions

4

Arrow functions

Arrow functions are function shorthands

Arrow functions doesn't create a new 'this' context.

Arrow functions: Concept

// ES5 function
const person = {
    greet: function(name) {
        return `hi, ${name}`;
    }
}
// Arrow function
const person = {
    greet: (name) => {
        return `hi, ${name}`;
    }
}
// Implicit return
const person = {
    greet: (name) => `hi, ${name}`
}

Arrow functions: Example

// ES5 - Movie plot generator

const plots = [
    'avenge dead wife',
    'use skillset to eliminate threat to nation',
    'save daughter'
];

const createMoviePitch = function(plot) {
    console.log(`Liam Neeson has to ${plot}`);
};

// Make it rain!
plots.map( function(plot) {
    return createMoviePitch(plot)
});

Arrow functions: Example

// ES6 - Movie plot generator

const plots = [
    'avenge dead wife',
    'use skillset to eliminate threat to nation',
    'save daughter'
];

const createMoviePitch = function(plot) {
    console.log(`Liam Neeson has to ${plot}`);
};

// Make it rain!
plots.map( (plot) => {
    return createMoviePitch(plot)
});

Arrow functions: Example

// ES6 - Movie plot generator

const plots = [
    'avenge dead wife',
    'use skillset to eliminate threat to nation',
    'save daughter'
];

const createMoviePitch = (plot) => {
    console.log(`Liam Neeson has to ${plot}`);
};

// Make it rain!
plots.map( plot => createMoviePitch(plot));

Arrow functions: Anatomy

// Passing arguments 
() => { ... }   // no argument
x => { ... } // one argument
(x, y) => { ... } // several arguments


// Function bodies
x => { return x * x }  // block
x => x * x  // expression, equivalent to previous line

Arrow functions: `this`

// ES5
function sneeze() {
    
    var self = this;

    console.log('ahh.. ahh.. ahh..');
            
    this.choo = function(){
        console.log('CHOO!');
    };

    window.setTimeout( function() {
        self.choo();
    }, 1000);
}
// ES6
function sneeze() {

    console.log('ahh.. ahh.. ahh..');
            
    this.choo = () => console.log('CHOO!');

    window.setTimeout( () => {
        this.choo();
    }, 1000);
} 

Arrow functions: Use case

  • anonymous functions 
  • when you need 'this' to stay in parent context
  • When using map, filter, reduce

Destructuring

5

Destructuring

Easily extract values from data stored in objects and Arrays

Destructuring: Example

// ES5 object creation

const person = {
    name: 'Tim Samson',
    features: {
        face: 'round',
        arms: 'sort',
        hair: false
    }
}

// Imagine if you had to do this instead:
const person = {};

person.name = 'Tim Samson';
person.features = {};
person.features.face = 'round';
person.features.arms = 'sort';
person.features.hair = false;

Destructuring: Example

// ES5 data extraction

const person = {
    name: 'Tim Samson',
    features: {
        face: 'round',
        arms: 'sort',
        hair: false
    }
}

// To get values out with ES5 you had to dig!
const name = person.name;
const face = person.features.face;
const arms = person.features.arms;
const hair = person.features.hair;
// ES6 data extraction

const person = {
    name: 'Tim Samson',
    features: {
        face: 'round',
        arms: 'sort',
        hair: false
    }
}

// To get values out with ES5 you had to dig!
const name = person.name;
const face = person.features.face;
const arms = person.features.arms;
const hair = person.features.hair;

// Not anymore!
const { name, features: { face, arms, hair } } = person;

Destructuring: argument

// Useful when you only care about certain parameters

const menu = {
    appetiser: 'flea soup'
    mains: 'locust eggs'
    dessert: 'goblin sorbet'
}

function orderDessert({dessert}){
    console.log(`Can I please have a bucket of ${dessert}, please?`);
}

orderDessert(menu); // Can I please have a bucket of goblin sorbet, please?

Destructuring: defaults

// Provide a default value if property doesn't exist

const person = {
    name: 'Draco',
    age: 673
}

const { name = 'Ricardo', height = '180cm' } = person;

console.log(name);      // Draco
console.log(age);       // 673
console.log(height);    // 180cm

Destructuring: defaults

// Variable unpacking - common react pattern

// ES5
var author = this.props.author;
var posts = this.props.posts;
var bio = this.props.bio;
    
// ES6
const { author, posts, bio } = this.props;  

Destructuring: Use case

  • get data from JSON/objects
  • provide default variable values
  • destructure function arguments

Modules

6

Modules

Modules bring module loading to native javaScript

modules: Basic example

/**
 * CommonJS (Node)
 */
var _ = require('lodash');
_.join(['a', 'b', 'c'], '~'); // → 'a~b~c'


/**
 * AMD (RequireJS)
 */
define(['lodash'] , function (_) {
    return function () {
        _.join(['a', 'b', 'c'], '~'); // → 'a~b~c'
    };
});


/**
 * ES6 modules
 */
import _ from 'lodash';
_.join(['a', 'b', 'c'], '~'); // → 'a~b~c'

modules: Named Exports

// --- animalFarm.js --- //

export const napoleon = {
    species = 'pig',
    speak() => { console.log('Four legs good, two legs bad'); }
};
export const boxer = {
    species = 'horse',
    speak() => { console.log('I will work harder'); }
};

// --- main.js --- //

// Named imports
import { napoleon, snowball } from 'animalFarm';

napoleon.speak();

// Import all the things
import * as animalFarm from 'animalFarm';

animalFarm.boxer.speak();

modules: Default exports

// --- helpers.js --- //

// Default exports

var helpers = {
    generateRandom: function() {
        return Math.random();    
    },
    sum: function(a, b) {
        return a + b;
    }
};

export default helpers;


// --- main.js --- //

import helpers from 'helpers';

Modules: Use case

  • The new standard module syntax
  • To use modules today you need some sort of bundler like browserify or webpack.

Blocks

7

Blocks

the End of the IIFE

Blocks

Blocks: Example

// ES5

(function () {
    var secret = 'Soylent green is people!';
}());

console.log(secret); // Reference Error


// ES6

{
    let secret = 'Bush faked the moon landing';
}

console.log(secret); // Reference Error

Blocks: Use cases

  • Wherever you used IFFE's before
  • To create a new block scope context

Quiz time!

Add up n'th character

then reverse

(of first names)

2

4

3

1

Quiz time!

Add up n'th character

then reverse

(of first names)

2

4

3

1

hal

Quiz time!

ABBA

hal

donald

2

4

3

jeb

bonnie

1

Enhanced Object Literals

8

Enhanced Object Literals

Object literals have been given more functionality with ES6.

  • Shorthands for defining methods
     
  • Dynamic property names

Enhanced Objects: Example

// ES5
var person = {
    name: 'Doyle',
    poke: function() { console.log('Stop that!'); },
    greet: function() { console.log('Ahoi-hoi!'); }
};

// ES6
var person = {
    name: 'Doyle',
    poke() { console.log('Stop that!'); },
    greet() { console.log('Ahoi-hoi!'); }
};

Enhanced Objects: Example

// Computed property names (ES6)
const prefix = 'half';
const people = {
    [prefix + 'man']: 'Tyrion',
    [prefix + 'hand']: 'Qhorin',
    [prefix + 'mast']: true
};

console.log(people.halfman);    // → Tyrion
console.log(people.halfhand);   // → Qhorin
console.log(people.halfmast);   // → true

Enhanced Object: Use case

  • Creating object methods
  • Computed property names

Parameters

9

Parameters

There's a few new ways of managing parameters in ES6:

  • Default parameters (already covered)
  • Rest parameters
  • Spread operators

Rest Parameters: Example

const arguments = ['test', 'test2', 'okay', 2, {}, null];

// ES5
function printAllArguments1() {
    for (var i=0; i < arguments.length; i++) {
        console.log(arguments[i]);
    }
}

printAllArguments1(); // → test, test2, okay, 2, {}, null
// ES6
function printAllArguments2(...things) {
    things.forEach( thing => {
        console.log(thing);
    });
}

printAllArguments1(); // → test, test2, okay, 2, {}, null

Spread operator: Example

var args = [0, 1, 2];
function myFunction(x, y, z) { }

// ES5
myFunction.apply(null, args);
// ES6
myFunction(...args);

// Or even
myFunction(...[1,2,3]);

A better apply

Promises

10

P

Promises

Promises are perhaps the most important new feature.

  • Lots of 3rd party libraries implement promises
  • Node developers have been using them for a long time
  • Finally a native implementation
  • Used under the hood for a lot of upcoming async features

Promises

A promise is a representation of the eventual result of an async computation

  • A more familiar example

Promises

  • Synchronous code = easy

Why are they needed?

  • Error handling in callbacks are hard
  • Async is hard
  • Pyramid of doom (Callback hell)

Promises

Promises: Example

// ES5
func1(function (value1) {
    func2(value1, function (value2) {
        func3(value2, function (value3) {
            func4(value3, function (value4) {
                // Do something with value 4
            });
        });
    });
});

// ES6
func1(value1)
    .then(func2)
    .then(func3)
    .then(func4, value4 => {
        // Do something with value 4
    });

Promises: Syntax

// Promise creation 
promise = new Promise(function(resolve, reject) {});
  • The promise constructor takes one argument, a callback with two parameters, resolve and reject.
  • Running new Promise will immediately call the function passed in as an argument.  

Promises

A promise is a special kind of javascript object which contains another object.

Promises: Creating a new promise

const promise = new Promise(
    function (resolve, reject) {
        
        // Do something async here!
        setTimeout(() => resolve({name: 'Bård'}), 2000)
        
        // Or, with ES5 syntax:
        setTimeout( function(){
            return resolve({name: 'Bård'})
        }, 2000)
    }
);

Promises

.then() is used to get the data stored in a promise

Promises: Executing

getName.then(function(user) {
    // process result
    console.log(user.name)
    
}, function(err) {
    // handle error
    console.log('error! error!')
});

Promises: States

Promises start out in pending state and are settled when they’re either fulfilled or rejected

pending

rejected

fulfilled

settled

Promises: .then()

.then() is the most important method

  • registers callbacks to receive either the eventual value or the reason why the promise cannot be fulfilled
  • accepts two arguments (Both are optional, can add a callback for the success or failure case only)
  • then always returns a new promise

Promises: .then()

// Basic usage
.then(successFn, errorFn)

// Chaining
getSomeData()
    .then(filterTheData)
    .then(processTheData)
    .then(displayTheData);

Promises: Promise.all

  • Returns a promise which resolves when all of it’s argument promises have resolved
  • Or: is rejected when any of it’s argument promises are rejected

Promises: Promise.all()

// Syntax
Promise.all(promiseArray).then(function(resultsArray) {
    //...
});

// Example:
Promise.all([
    queryUserToken(),
    queryUserDetails()
]).then(function() {
    renderProfiles();
});

Promises: Error handling

keep your Promise chains flat with a trailing .catch() to properly handles errors

  • Easier than in callback pyramids
  • Promises are implemented to allow a single channel for errors
  • .catch() is better than using .then(errorFn)

Promises: Error catching

// Error catching
getSomeData()
    .then(doSomething)
    .then(doSomethingElse)
    .catch(function(err) {
        // handle all errors
    });

Promises Use cases

  • Working with async data
  • Concurrent async requests
  • REST etc

Object.assign

11

P

Enhanced Object Literals

works like jquery.extend

Object.assign: Example

// Syntax
Object.assign(targetObj, source, source2, source3);

const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };

const newObj = Object.assign(o1, o2, o3);
console.log(newObj); // { a: 1, b: 2, c: 3 }

Object.assign: Example 2

function UIModal(userOptions) {

    const DOM;
    const defaults = {
        modal: '.js-modal',
        openBtn: '.js-modal-btn',
        closeBtn: '.js-modal-close-btn',
        overlay: '.js-modal-overlay',
        showOverlay: true
    };

    // Combine defaults with passed in options
    const settings = Object.assign(defaults, userOptions);
    
    // ...
}

Object.assign: Use case

  • Config objects
  • Combining multiple objects

Quiz time!

What is this?

Quiz time!

for-of

12

for-of

Like for-in, but returns object, not index.

for-of: Example

// ES5
var sum1 = 0;
var arr1 = [1, 2, 3];

for (var index in arr1) {
    sum += arr1[index]; 
}

// ES6
let sum2 = 0;
let arr2 = [1, 2, 3];

for (let value of arr2) {
    sum += value;
}

for-of: Example

// Strings
let iterable = "Jammie Dodgers";

for (let value of iterable) {
    console.log(value);
}

// J
// a
// m
// m
// i
// e
//  
// D
// o
// d
// g
// e
// r
// s

for-of: Use case

  • Iterating over objects and arrays
  • Watch out for future uses (observables)

strings

13

Strings

The string native has been extended with some very useful new features

Strings: string.includes()

// ES5
console.log('devSouthCoast'.indexOf('Coast') > -1); 
// true


// ES6
console.log('ryanGoslin'.includes('Goblin')); 
// false

Strings: string.repeat()

// ES5
function repeat(string, count) {
    var strings = [];
    while(strings.length < count) {
            strings.push(string);
    }
    return strings.join('');
}

repeat('chill', 3); // 'chillchillchill'


// ES6
'go'.repeat(3); // 'gogogo'  

Strings: Use case

  • When you need string includes & repeat functions...

classes

14

Modules

Simple sugar over the prototype-based OO pattern

Classes: Example

// Basic syntax     
class className  {
    
    // Constructor
    constructor() {}
    
    // Method
    methodName(){}
    
    // Super call
    super.superMethod();
}

Classes: ES5

// ES5
function Person(name, age, species) {
    this.name = name;
    this.age = age;
    this.species = species;
}

Person.prototype.greet = function () {
    return 'Greetings, I am ' + this.name + '!';
};

var cindy = new Person('Cindy', 98, 'klingon');
console.log(cindy.greet()); // Greetings, I am Cindy!

Classes: ES6

// ES5
class Person {
    constructor(name, age, species) {
        this.name = name;
        this.age = age;
        this.species = species;
    }

    greet() {
        return 'Greetings, I am ' + this.name + '!';
    }
}

const cindy = new Person('Cindy', 98, 'klingon');
console.log(cindy.greet()); // Greetings, I am Cindy!

Classes: Use case

  • Same as before
  • Just sugar..
  • Babel demo?

Babel

Babel

  • Transpiles ES6 to ES5
  • Polyfills complex features

P

  • .babelrc

Babel

ES5 library update

ES7/ES2016 and beyond

What's next!?

bonus

ES7/ES2016:

  • Array.prototype.includes
  • Exponentiation Operator

That's it!

Array.prototype.includes

// Example
['a', 'b', 'c'].includes('a'); // true

['a', 'b', 'c'].includes('d'); // false


// Almost the same Async
['a', 'b', 'c'].indexOf('a') >= 0

// But not quite
[NaN].includes(NaN) // true
[NaN].indexOf(NaN)  // -1

Exponentiation Operator 

// ES5
Math.pow(x, y);

// ES6
x ** y;

// Example
const twoTimesTwo = 2 ** 2; // 4
const fourTimesFourTimesFour = 4 ** 3; // 64

ES7/ES2016 and beyond

What else?

Web Assembly (wasm)

  • Low level binary compile target
  • Heavy duty applicaitons and games
  • Level the playing field for other languages

Web Assembly (wasm)

WebAssembly fills in the gaps that would be awkward to fill with JavaScript

  • Not a JavaScript replacement
  • Compilation target for other languages

ES7/ES2016 and beyond

Other upcoming ES features?

  • Async Await

Async Await

Write syncronous code, make it act asynchronous

  • Relies on promises (ES6 core function)
  • functions in exactly the same way as calling `.then()` on a promise
  • simply pauses execution of a method until the value from the promise is available.

Async Await: The problem

// Async function
function getStarship() {
    return fetch('URL').then( response => {
        return response.json().name;
    })
}

// Sync function
function printStarship() {
    const starship = getStarship();
    console.log(starship);
}

printStarship(); // undefined

Async Await: The solution

// Async function
function getStarship() {
    return fetch('URL').then( response => {
        return response.json().name;
    })
}

// Async await function
async function printStarship() {
    const starship = await getStarship();
    console.log(starship);
}

printStarship(); // Death Star

Async await vs promises

Async Await functions in exactly the same way as calling `.then()` on a promise

(but without requiring any callback function)

Promises vs Async Await

// Promise
function getDailyJoke() {
    fetch('http://joke.org', {}).then(function(response) {
        return response.body.joke;
    });
}

// Async await
async function getDailyJoke() {
    let response = await fetch('http://joke.org', {});
    return response.body.joke;
}

Async Await: Use case

  • Write code as if it is sync (readable)
  • Code  = easier to understand and simpler to write.

Final thoughts

Is ES6 worth the effort?

  • Compilers aren’t going away
  • less code is better. Less room for error.
  • Not an all-or-nothing deal
  • Adoption will happen. Typescript etc

Quick wins

  • End of callback hell (promises)
  • No more `self = this` (arrows)
  • Less data validation in functions (default parameters)
  • Super-easy object value extraction (destructuring)

Words of caution

  • Workflow integration could be painful
  • Concern about amount of features?
  • Debugging does become slightly harder (but only slightly)

When uncertain, chances are you probably should default to ES5 and older syntax instead of adopting ES6 just because you can. 

Words of caution

By this I don’t mean that using ES6 syntax is a bad idea – quite the opposite, see I’m writing an article about ES6!

 

My concern lies with the fact that when we adopt ES6 features we must do it because they’ll absolutely improve our code quality, and not just because of the "cool factor" – whatever that may be.

My advice

Don't get fatigued! Keep it simple!

Final Quote

There are only two kinds of languages: the ones people complain about and the ones nobody uses

- Bjarne Stroustrup

Final Exams

99

Thanks for listening!

all material & slides:

ES6 in production - Final edition

By Bård Hovde

ES6 in production - Final edition

ES6 in production

  • 1,269
Loading comments...

More from Bård Hovde