Skip to content

Latest commit

 

History

History
249 lines (184 loc) · 11.4 KB

README-pt-br.md

File metadata and controls

249 lines (184 loc) · 11.4 KB

#Introdução

O objetivo deste guia é apresentar um conjunto de boas práticas e diretrizes para uma aplicação AngularJS. Estas boas práticas são baseadas em:

  1. Código fonte do AngularJS
  2. Códigos fonte ou artigos que li
  3. Minha própria experiência

Nota: Este guia ainda é um rascunho, seu objetivo principal é ser construído pela comunidade, então ao contribuir você será muito apreciado por toda ela.

Neste guia você não vai encontrar diretrizes para desenvolvimento JavaScript. O que pode ser encontrado em:

  1. Guia JavaScript Google
  2. Guia JavaScript Mozilla
  3. Guia JavaScript Github
  4. Guia JavaScript Douglas Crockford

Para o desenvolvimento usando o AngularJS é recomendado o Guia JavaScript Google.

Na wiki do AngularJS no Github temos uma seção similar feita pelo ProLoser, você pode vê-la aqui.

#Índice

#Geral

##Estrutura de Diretório

Uma vez que uma grande aplicação AngularJS tem muitos componentes, é melhor estruturá-la em uma hierarquia de diretórios. Há duas abordagens:

  • Criando uma divisão alto nível por tipos de componentes e uma divisão baixo nível por funcionalidade.

Desta maneira a estrutura do diretório irá se parecer com:

.
├── app
│   ├── app.js
│   ├── controllers
│   │   ├── page1
│   │   │   ├── FirstCtrl.js
│   │   │   └── SecondCtrl.js
│   │   └── page2
│   │       └── ThirdCtrl.js
│   ├── directives
│   │   ├── page1
│   │   │   └── directive1.js
│   │   └── page2
│   │       ├── directive2.js
│   │       └── directive3.js
│   ├── filters
│   │   ├── page1
│   │   └── page2
│   └── services
│       ├── CommonService.js
│       ├── cache
│       │   ├── Cache1.js
│       │   └── Cache2.js
│       └── models
│           ├── Model1.js
│           └── Model2.js
├── lib
└── test
  • Criando uma divisão alto nível por funcionalidade e baixo nível por tipos de componentes.

Aqui está seu modelo:

.
├── app
│   ├── app.js
│   ├── common
│   │   ├── controllers
│   │   ├── directives
│   │   ├── filters
│   │   └── services
│   ├── page1
│   │   ├── controllers
│   │   │   ├── FirstCtrl.js
│   │   │   └── SecondCtrl.js
│   │   ├── directives
│   │   │   └── directive1.js
│   │   ├── filters
│   │   │   ├── filter1.js
│   │   │   └── filter2.js
│   │   └── services
│   │       ├── service1.js
│   │       └── service2.js
│   └── page2
│       ├── controllers
│       │   └── ThirdCtrl.js
│       ├── directives
│       │   ├── directive2.js
│       │   └── directive3.js
│       ├── filters
│       │   └── filter3.js
│       └── services
│           └── service3.js
├── lib
└── test
  • Quando criarmos uma diretiva, pode ser útil colocar todos os arquivos associados as diretivas (i.e. templates, arquivos CSS/SASS, JavaScript) em uma pasta única. Se você escolher usar este estilo, seja consistente e use-o em todo seu projeto.

      app
      └── directives
          ├── directive1
          │   ├── directive1.html
          │   ├── directive1.js
          │   └── directive1.sass
          └── directive2
              ├── directive2.html
              ├── directive2.js
              └── directive2.sass
    

Esta abordagem pode ser combinada com ambas as estruturas de diretórios acima.

  • O arquivo app.js contém definição de rotas, configurações e/ou inicializações manuais (se necessário).
  • Cada arquivo JavaScript deve conter apenas um componente. O arquivo deve ser nomeado com o nome do componente.
  • Use estruturas de projeto Angular como Yeoman ou ng-boilerplate.

Eu prefiro a primeira estrutura porque ela cria componentes comuns e fáceis de se achar.

Convenções sobre nomeação de componentes podem ser achadas em cada seção do componente.

##Otimizando o ciclo digest

  • Observe somente as variáveis vitais (por exemplo: quando se usar comunicação em tempo real, não utilize um loop digest para cada mensagem recebida).
  • Faça cálculos em $watch o mais simples que puder. Fazer cálculos pesados e lentos em um simples $watch irá atrasar toda a aplicação (o loop $digest é feito em 'single thread' por causa da natureza 'single thread' do JavaScript).

##Outros

  • Use:
    • $timeout ao invés de setTimeout
    • $interval ao invés de setInterval
    • $window ao invés de window
    • $document ao invés de document
    • $http ao invés de $.ajax

Isto fará seus testes mais fáceis e em certos casos irá prevenir comportamentos inesperados (por exemplo, se você perder $scope.$apply em setTimeout).

  • Automatize seu fluxo de trabalho utilizando ferramentas como:

  • Use promises ($q) ao invés de callbacks. Isso tornará seu código mais elegante e limpo, e o salvará do inferno de callbacks.

  • Use $resource ao invés de $http quando possível. Um alto nível de abstração irá lhe salvar de redundância.

  • Use um pré-minificador AngularJS (como ngmin ou ng-annotate) para prevenir problemas depois da minificação.

  • Não use globais. Resolva todas as dependências usando a Injeção de Dependências.

  • Não polua seu $scope. Somente adicione funções e variáveis que irão ser usadas nos templates.

#Módulos

Há duas maneiras comuns de se estruturar os módulos:

  1. Por funcionalidade
  2. Por tipo de componente

Atualmente não há uma grande diferença, mas a primeira forma parece mais limpa. Também, se os módulos 'lazy-loading' forem implementados (fora do roteiro AngularJS atualmente), isso irá melhorar a performance da sua aplicação.

#Controladores

  • Não manipule DOM com controladores. Use diretivas para isso.

  • O nome do controlodor é dado pela sua funcionalidade (por exemplo shopping cart, homepage, admin panel) e o adicional Ctrl no final. Os controladores são nomeados no formato UpperCamelCase (HomePageCtrl, ShoppingCartCtrl, AdminPanelCtrl, etc.).

  • Os controladores não devem ser definidos como globais (não importa que AngularJS permita isso, é uma má pratica pois polui o namespace).

  • Use a sintaxe de array para as definições do controlador:

      module.controller('MyCtrl', ['dependency1', 'dependency2', ..., 'dependencyn', function (dependency1, dependency2, ..., dependencyn) {
        //...body
      }]);
    

Use este tipo de definição para evitar problemas com minificação. Você pode gerar automaticamente o array de definição a partir de um padrão usando ferramentas como ng-annotate (e uma tarefa grunt grunt-ng-annotate).

  • Use os nomes originais das dependências dos controladores. Isso irá ajudá-lo a produzir um código mais legível:

      module.controller('MyCtrl', ['$scope', function (s) {
        //...body
      }]);
    

é menos legível que:

    module.controller('MyCtrl', ['$scope', function ($scope) {
      //...body
    }]);

Isso é especialmente aplicado a um arquivo que contenha muito código que se faça necessário rolar (usar o scroll) por ele. Pois é provável que você esqueça qual variável está amarrada em qual dependência.

  • Faça os controladores o mais enxuto possível. Resuma as funções normalmente usadas no serviço.

  • Comunique entre controladores diversos usando o método de invocação (possível quando os elementos filhos querem se comunicar com os pais) ou $emit, $broadcast e $on métodos. As mensagens emitidas ($emit) e transmitidas ($broadcast) devem ser mantidas minimamente.

  • Faça uma lista de todas as mensagens que são passadas usando $emit, $broadcast e administre-as cuidadosamente por causa da coalisão de nomes e possíveis erros.

  • Quando você precisar formatar dados, encapsule a lógica de formatação em um filtro e declare isso como uma dependência:

      module.filter('myFormat', function () {
        return function () {
          //body...
        };
      });
    
      module.controller('MyCtrl', ['$scope', 'myFormatFilter', function ($scope, myFormatFilter) {
        //body...
      }]);
    

#Diretivas

  • Nomeie suas diretivas no padrão lowerCamelCase
  • Use scope ao invés de $scope na sua função de link. Na compilação, pós/pre funções link que você tenha, definem os argumentos que irão ser passados quando a função é invocada, você não será capaz de muda-los usando DI (injeção de dependências). Este modelo também é usado no código fonte do AngularJS.
  • Use prefixos customizados para suas diretivas para previnir colisões de nomes com bibliotecas de terceiros.
  • Não use ng ou ui prefixos pois eles estão reservados para o uso do AngularJS e AngularJS UI.
  • Manipulações DOM devem ser feitas somente através de diretivas.
  • Crie um escopo isolado/independente quando você for desenvolver componentes reutilizáveis.

#Filtros

  • Nomeie seus filtros no padrão lowerCamelCase
  • Faça seus filtros o mais leve possível. Eles são chamados frequentemente durante o loop $digest então criando filtros lentos você irá atrasar sua aplicação.

#Serviços

  • Use camelCase (lower ou upper) para nomear os serviços.
  • Encapsule as 'business logic' nos services.
  • Serviços encapsulando 'business logic' são preferencialmente um service ao invez de umfactory
  • Para cachear a 'session-level' você pode usar $cacheFactory. Isto deve ser usado para cachear resultados de requisições ou computações pesadas.

#Templates

  • Use ng-bind ou ng-cloak ao invés de simplesmente {{ }} para prevenir conteúdo piscando.
  • Evite escrever código complexo no template.

#Roteamento

  • Use resolve para solucionar as dependências antes que o 'view' seja mostrado.