JavaScript

Rompendo e criando novos paradigmas.

(como o JS mudou minha maneira de programar)

@millermedeiros / Março 2013

Vídeo: youtube.com/watch?v=iuGcH_IiM34
Para ver minhas anotações aperte a tecla "s".

JavaScript é uma linguagem dinâmica que possui várias peculiaridades e por isso requer uma maneira diferente de pensar e solucionar problemas.

Metodologias adotadas em outros contextos podem não ser os mais indicadas e por isso é importante refletir antes de copiar paradigmas enraizados em outras linguagens.

Senta que lá vem história...

  • comecei a "programar" em 1999 usando o FrontPage.
  • em 2005 falei que nunca aprenderia JavaScript.
  • em 2006 lancei meu primeiro projeto open-source escrito em JavaScript (swffit).
  • hoje em dia sou Senior Developer na Firstborn e escrevo milhares de linhas de JS todo mês.

Como isso aconteceu?

JavaScript se tornou a linguagem mais importante da Web e hoje em dia é também a linguagem com o maior número de usuários.

Aprendi (a amar) JavaScript.

Indo com a correnteza

Composição > Herança

Quando herança é a única ferramenta que você conhece todos os problemas se parecem filhos de outros problemas.

Antigamente eu provavelmente faria algo do tipo:

function ZoomControl(){
    VerticalSlider.call(this);
    ...
}

ZoomControl.prototype = Object.create(VerticalSlider.prototype);

Hoje em dia é mais comum eu fazer:

function ZoomContol(){
    this._slider = new VerticalSlider();
    this._buttons = new IncrementButtons();
    ...
}

Duck typing

When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.

— Se parece um pato, é um pato.

Ao invés de escrever:

function process(foo)
    if (foo.constructor === Dolor) {
        foo.amet();
    } else if (foo instanceof Bar) {
        doSomething(foo.bar);
    }
    ...
}

Escrevo*:

function process(foo) {
    if (typeof foo.amet === 'function') {
        foo.amet();
    } else if ('bar' in foo) {
        doSomething(foo.bar);
    }
    ...
}

PS: use typeof somente para "string", "number" e "function" !!
typeof null == "object"

Na verdade mesmo escreveria:

function processFoo(foo) {
  foo.amet();
  sharedProcess(foo);
}
function processBar(foo) {
  doSomething(foo.bar);
  sharedProcess(foo);
}
function sharedProcess(foo) {
  // ...
}

WTFJS

Evite usar construtores para String, Number e Array.

typeof "foo" // string
typeof String("foo") // string
typeof (new String("foo")) // object (WTF?)

"foo" instanceof String // false (WTF?)
(new String("foo")) instanceof String // true

mais: Wat e WTFJS

Tipagem estática é desnecessária em 99% dos casos.

Use JSHint e escreva testes unitários!

Monkey patching e membros "privados"

var lorem = 'ipsum'; // `lorem` é global

// iife cria um "closure" (escopo local)
(function(){
    var foo = 'bar'; // `foo` é "local"
    console.log(lorem); // 'ipsum'
    console.log(foo);   // 'bar'
}());

console.log(lorem); // 'ipsum'
// ReferenceError: foo is not defined
console.log(foo);

Flexibilidade é uma das maiores virtudes do JavaScript.

Slider.prototype.refresh = function(){
    ...
};

Slider.prototype._updatePositionOnDrag = function(){
    ...
};

Marker Clusterer Plus

Moutain Dew Kickstart

// salva referência do método original
var originalOnAdd = ClusterIcon.prototype.onAdd;

// sobrescreve método
ClusterIcon.prototype.onAdd = function () {
   if (! this.shadow_) {
     this.shadow_ = document.createElement('div');
     this.getPanes()
       .overlayShadow
       .appendChild(this.shadow_);
   }
   // executa método original no "contexto" this
   originalOnAdd.apply(this, arguments);
};

Funções e nomes descritivos

slideshow.setDelayInSeconds(5);
slideshow.goTo(8);

slider.increment();
slider.decrement();
slider.setRatio(0.67);

Também uso as funções como uma maneira de forçar com que os erros sejam identificados rapidamente, já que um erro é disparado ao chamar um método inexistente.

calendar.show('apil'); //ops, erro silencioso
calendar.showApil(); // throw error!

Programação Funcional

Como JavaScript possui higher-order functions e execução de métodos raramente acarreta problemas de performance eu passei a adotar vários conceitos de programação funcional no meu código.

Ao invés de escrever:

var user;
var hipsters = [];
for (var i = 0; i < users.length; i++) {
    user = users[i];
    if (user.isHipster) {
        hipsters.push(user);
    }
}

doSomething(hipsters);

Escrevo:

var hipsters = filter(users, function(user){
    return user.isHipster;
});

doSomething(hipsters);

Ou até mesmo:

doSomething( filter(users, 'isHipster') );
http://moutjs.com

Micro-módulos

A maioria dos meus arquivos fonte hoje em dia possuem menos de 100 linhas de código sendo que destes alguns possuem apenas um único método.

As pessoas temem o desconhecido

O melhor "remédio" é aprender a linguagem a fundo.

Use a linguagem a seu favor.

Obrigado!

blog.millermedeiros.com / @millermedeiros

Vídeo: youtube.com/watch?v=iuGcH_IiM34