Arquivo

Textos com Etiquetas ‘Boas Práticas’

Anotações sobre o livro “JavaScript: The Good Parts”

15 de agosto de 2010

Em geral quando eu leio um livro, costumo fazer anotações de trechos interessantes que encontro.

No livro JavaScript: The Good Parts, de Douglas Crockford, encontrei um punhado deles. Eu listo esses trechos aqui, até sendo um forma de eu organizar meu estudo.

Só lembrando que minha intenção não é publicar partes do livro. Na verdade, espero que você, que usa/gosta de JavaScript, se sinta incentivado a ler o livro, o qual gostei muito e recomendo.

Ah, para quem quiser, também há a versão traduzida para português, O Melhor do JavaScript, publicada pela editora Alta Books.

Analisando o JavaScript

O JavaScript se baseia em algumas idéias muito boas, que incluem funções, tipificação fraca e objetos dinâmicos, e umas poucas idéias ruins, como um modelo de programação baseado em variáveis globais.

Se você deseja aprender sobre as partes ruins e como mal utilizá-las, consulte qualquer outro livro sobre JavaScript.

Números

Há um único tipo de número, onde não há um tipo inteiro distinto, diferente de outras linguagens de programação. Então 1 e 1.0 têm o mesmo valor.

Strings

Strings são imutáveis, nunca podem ser alteradas. Concatenando com o operador “+”, uma nova string é criada.

Duas strings que contém os mesmos caracteres na mesma ordem são considerados a mesma string. Por exemplo, o resultado da expressão abaixo é true.

"P" + "r" + "o" + "d" + "i" + "s" === "Prodis" // true
Escopo

Diferente de outras linguagens, os blocos (grupo de comandos entre chaves) não criam um novo escopo. Uma variável declarada dentro de um bloco é visível em qualquer lugar da função que contém esse bloco. Sendo assim, as variáveis não deveriam ser definidas nos blocos, e sim no começo da função.

Valores booleanos

false, null, undefined, string vazia “”, o número 0 e o número NaN são valores falsos. Todos os outros valores são considerados verdadeiro, inclusive true, a string “false” e os demais objetos.

Operador typeof

“number”, “string”, “boolean”, “undefined”, “function” e “object” são valores retornados por typeof. Para o uso de typeof com null ou uma matriz, o retorno é “object”, o que não é certo. Um teste melhor para detectar nulos é simplesmente:

myValue === null
Objetos

Números, strings e booleanos não são objetos, pois são imutáveis. Objetos são grupos mutáveis com índices. Matrizes, funções, expressões regulares e objetos são objetos.

Para criar novos valores de objetos, uma forma conveniente é criar um objeto literal, um par de chaves contendo zero ou mais pares nome/valor. Por exemplo:

var contact = {
  "email" = "pedro@bo.com.br",
  "phone" = "(11) 9999-9999"
}

Todo objeto é ligado a um protótipo de onde ele pode herdar propriedades. Todos os objetos criados de literais são associados a Object.prototype, um objeto que vem como padrão no JavaScript.

Funções

A melhor coisa que JavaScript possui é sua implementação de funções.

Funções são ligadas à Function.prototype, que está ligada à Object.prototype.

Funções podem ser armazenadas em váriaveis, objetos e matrizes. Elas podem ser passadas como parâmetros para funções e serem retornadas por funções. E como são objetos, funções também podem ter métodos.

Quando uma função é chamada e os parâmetros não coincidem, não há erro em tempo de execução. Se os valores informados excederem a quantidade de parâmetros, os valores excedentes são ignorados. Se o inverso acontecer, undefined será atribuído aos valores faltantes.

Uma função sempre retorna um valor. Se um valor não for fornecido no comando return, então undefined é retornado.

Ao invés de escopo de bloco, JavaScript possui escopo de função. Todos os parâmetros e variáveis definidos em uma função não são visíveis fora dela. É recomendável declarar todas as variáveis utilizadas em uma função no início do corpo da função, diferente de outras linguagens onde as variáveis geralmente são declaradas logo antes de sua utilização.

Partes péssimas e ruins

A dependência de variáveis globais é a pior parte do JavaScript, pois uma dessas variáveis pode ser alterada em qualquer parte do código e em qualquer momento, algo que pode complicar muito o comportamento de um programa.

O operador “+” é utilizado tanto para concatenar strings, quanto para somar números. Se você quer usá-lo para somar, precisa se certificar que os dois operandos são números. Caso contrário, esses operandos serão convertidos em strings. Veja o exemplo abaixo:

10 + 15 // 25
10 + "15" // "1015"

O valor NaN (not a number) é um tanto incoerente. O typeof não distingue entre números e NaN:

typeof(NaN) // "number"

E NaN não é igual a ele mesmo:

NaN === NaN // false
NaN !== NaN // true

No JavaScript, há dois grupos de operadores de igualdade:

  • Os bons: === e !==
  • E os maus: == e !=

Os bons funcionam como esperado: se dois operando tiverem o mesmo valor e forem do mesmo tipo, === retorna true e !== retorna false. Já os maus funcionam bem quando os operando são do mesmo tipo, mas quando eles são de tipos diferentes, eles tentam fazer coerção de tipo e coisas estranhas podem acontecer:

"" == "0" // false
0 == ""   // true
0 == "0"  // true

false == "false" // false
false == "0"     // true

false == undefined // false
false == null     // false
null == undefined  // true

" \t\r\n " == 0 // true

O melhor é sempre usar o grupo de bons operados de igualdade: === e !==.

JavaScript, Livros , ,

Desprenda-se de convenções de nomenclatura em nome de testes

21 de novembro de 2009

Eu compartilho da opinião de Jimmy Bogard, que diz que os nomes dos testes precisam descrever o que e o porque, a partir da perspectiva do usuário, onde o desenvolver possa ler o nome do teste e claramente entender o comportamento que é esperado.

Um teste unitário nada mais é que um método em uma classe, e tanto em C# como Java, existem convenções de nomenclatura de métodos.

Em C#, nome de métodos são declarados utilizando Pascal Case:

[TestMethod]
public void ProductShouldHaveAtLeastOneCategory()
{
  //Test implementation.
}

Já em Java, convencionou-se escrever métodos utilizando Camel Case:

@Test
public void productShouldHaveAtLeastOneCategory() {
  //Test implementation.
}

Muitas vezes, o nome desses testes (métodos) ficam um tanto longos, como os exemplos acima. Dessa forma, a legibilidade não é muito boa.

Seguindo um dos conselhos de Neal Ford, em sua apresentação 10 Ways to Improve Your Code, você pode deixar de lado as convenções de nomenclatura da linguagem em favor da legilidade dos nomes dos seus testes. Escreva o nome do teste como se fosse uma frase, nada de letras maiúsculas para cada palavra, e use “_” (underscore) para separar as palavras.

Veja como fica o exemplo acima em C#:

[TestMethod]
public void Product_should_have_at_least_one_category()
{
  //Test implementation.
}

E agora em Java:

@Test
public void product_should_have_at_least_one_category() {
  //Test implementation.
}

Não há nenhum mal em se desprender das convenções de nomenclatura de C# e Java em prol da legibilidade dos nomes dos testes. Afinal, testes são uma documentação executável e nós queremos uma documentação clara para nosso código.

TDD , , , , , , ,

Não use nulo no retorno de coleções

9 de junho de 2009

Quando você tiver um método em que o retorno é algum tipo de coleção, ou seja, qualquer classe que implemente IEnumerable ou uma de suas interfaces filhas, nunca retorne null.

Quando a lógica do seu método não tiver elementos para serem colocados na coleção de retorno, você deve retornar uma lista vazia, com zero elementos. Essa boa prática vai facilitar a vida do código que irá consumir seu método.

Vamos ver um exemplo de um método que retorne uma coleção:

public class BookService
{
    public IList<Book> FindBooksByTitle(string startsWith)
    {
        //Alguma lógica que não encontra nenhum livro.
        return null;

        //Código restante.
    }
}

E o código que consome o método FindBooksByTitle:

BookService bs = new BookService();

foreach (var book in bs.FindBooksByTitle(&amp;amp;quot;The history&amp;amp;quot;))
{
    //Faz alguma coisa com a variável book.
}

Do jeito que está, se nenhum livro for encontrado de acordo com o critério passado, o valor retornado será null. Consequentemente, na linha 3 do código consumidor será gerada uma exceção do tipo NullReferenceException, pois tentará iterar através do foreach em uma variável nula.

Como resolvemos isso? Ah, basta colocar uma verificação se o retorno do método é nulo:

BookService bs = new BookService();
IList<Book> books = bs.FindBooksByTitle("The history");

if (books != null)
{
    foreach (var book in books)
    {
        //Faz alguma coisa com a variável book.
    }
}

Errado! O código que consome o método não pode ficar responsável por fazer esse tratamento. Senão, todo código que consumir o método FindBooksByTitle precisará fazer essa verificação de retorno nulo antes de iterar na coleção. Essa responsabilidade tem de ficar dentro da classe BookService e não fora dela.

Consertando o exemplo para retornar uma lista vazia:

public class BookService
{
    public IList<Book> FindBooksByTitle(string startsWith)
    {
        //Alguma lógica que não encontra nenhum livro.
        return new List<Book>();

        //Código restante.
    }
}

Agora o código consumidor pode iterar sem erros, mesmo que não seja encontrado nenhum livro:

BookService bs = new BookService();

foreach (var book in bs.FindBooksByTitle("The history"))
{
    //Faz alguma coisa com a variável book.
}

.NET , , ,

10 maneiras de melhorar seu código, por Neal Ford

23 de abril de 2009

Vou aproveitar o embalo do post sobre Automatização que o Erich colocou no blog de Tecnologia da Locaweb, onde ele fala que Neal Ford, no seu último livro “The Productive Programmer“, escreveu um capítulo inteiro sobre o assunto.

No último mês de novembro, estive na QCon San Francisco 2008 e tive o privilégio de assistir à palestra
“10 Ways to Improve Your Code”
apresentada por Neal Ford.

São elas:

  1. composed method
  2. test-driven development, test-driven design
  3. static analysis
  4. good citizenship
  5. yagni: you ain’t gonna need it
  6. question authority
  7. slap: single level of abstraction principle
  8. polyglot programming
  9. every nuance
  10. anti-objects

Você pode assistir à palestra que agora está disponível no site da InfoQ:
http://www.infoq.com/presentations/10-Ways-to-Better-Code-Neal-Ford

Baixe também os slides da apresentação em PDF neste endereço:
http://qconsf.com/sf2008/file?path=/qcon-sanfran-2008/slides//NealFord_10_Ways_to_Improve_Your_Code.pdf

Arquitetura, Eventos, TDD , , , , , , ,