Dev (Back & Front)ARTIGO

Desenvolvimento de workflow em aplicação web com Node.js

Contexto

O objetivo deste artigo é descrever um bom workflow para ser usado ao desenvolver aplicações web. Eu sempre leio conselhos sobre boas práticas de workflow, mas eles nunca agregam nada juntos, por isso vou fazer isso agora.

Desenvolvimento Direcionado para UI

Iremos seguir um estilo de Desenvolvimento Direcionado para Comportamento. Mais pra frente, iremos fazer uma aplicação web, então decidimos focar no usuário: começaremos escrevendo o código para a UI. Em seguida, para a UI e o backend, e iremos escrever nossos testes/especificações primeiro.

Technos

Como tecnologia iremos usar:

  • Node.js e seu framework Expess.JS devido à sua popularidade e para nos familarizarmos mais com eles.
  • A linguagem será Coffeescript devido à sua legibilidade.
  • Backbone será o framework UI.
  • Mongoose será o ODM.
  • Git o sistema de controle de versão.
  • Jasmine é o framework BDD para UI e Vows é o framework BDD para o backend.

Caso de uso

O app no qual eu irei aplicar o workflow será o Ponyo, um simples aplicativo que não faz nada além de criar e procurar por “categorias”. Para ilustrar o workflow, iremos adicionar um novo recurso: permitir a remoção de categorias.

Workflow

Aqui estão todos os passos que precisamos para fazer os desenvolvimentos corretos. É claro que na maior parte do tempo a pressão nos faz utilizar atalhos, mas é bom manter a maneira correta em mente. Mais para frente, esse workflow completo poderia ajudar a pensar sobre o que poderia ser otimizado/automatizado:

  1. Criar um branch
  2. Escrever especificações UI + commit
  3. Escrever especificações de código UI + commit
  4. Escrever código UI + commit
  5. Escrever especificações de recursos de backend + commit
  6. Escrever testes de recursos de backend + commit
  7. Escrever código de recursos de backend + commit
  8. Executar todos os testes
  9. Testar seu app manualmente
  10. Rebase branch
  11. Juntar branch + push
  12. Refatorar se necessário

Detalhes

1. Criar um branch

Primeiramente, não preocupe outros programadores com nossos commits, então vamos criar um branch chamado feature-delete-category.

Com Git

git branch feature-delete-category
git checkout feature-delete-category

2. Escrever especificações UI

Estamos fazendo Desenvolvimento Direcionado a UI, então primeiramente escreva as especificações de código do lado do cliente. Então, verifique com o seu browser (aqui está a URL: http://localhost:3000/tests/) que a entrada Jasmine falha.

Com Jasmine

1 describe 'Category deletion', ->
2 it 'When I display newly created category', ->
3 expect(false).toBeTruthy()
4 it 'And I click on delete category button from a category page', ->
5 expect(false).toBeTruthy()
6 it 'Then it brings me back to category list', ->
7 expect(false).toBeTruthy()
8 it 'And deleted activity is no more in the list', ->
9 expect(false).toBeTruthy()

Com Git, commit

git commit tests/categories.coffee -m "Add specs for category deletion."

3. Escrever especificações de código UI

Agora que você sabe o que quer fazer, você pode escrever testes correspondentes e verificar que eles falham.

Com Jasmine

01 describe 'Category deletion', ->
02 it 'When I display newly created category', ->
03 runs ->
04 $("#category-jasmine").click()
05 waits(500) # Waits to be sure that everything is done before testing
06 it 'And I click on delete category button from a category page', ->
07 runs ->
08 $("#delete-category-button").click()
09 waits(500) # Waits to be sure that everything is done before testing
10 it 'Then it brings me back to category list', ->
11 runs ->
12 expect($("#category-list").length).not.toEqual 0
13 it 'And deleted activity is no more in the list', ->
14 runs ->
15 expect($("#category-jamsine").length).toEqual 0

Com Git, commit

git commit tests/categories.coffee -m "Add tests for category deletion."

4. Escrever código UI

Agora iremos escrever o código UI, é necessário saber o que esperamos do servidor. Adicionamos um botão ao template exibindo uma categoria, então codificamos o comportamento do botão. Depois, verificamos se nossos testes ainda falham (o backend não suporta requisições para exclusão). Finalmente, fazemos o commit.

Modifique o template com Eco

1 <p>
2 <a id="delete-category-button" href="#home">
3 Delete category<br />
4 </a>
5 </p>

Escreva o comportamento com Backbone

01 categoryViewTemplate = require('../templates/category_view')
02 Category = require('../models/category').Category
03
04 class exports.CategoryView extends Backbone.View
05 id: 'category-view'
06
07 constructor: ->
08 super()
09
10 render: (category) ->
11 $("#nav-content").html null
12 $.get "/categories/#{category}/", (data) =>
13 $("#nav-content").html categoryViewTemplate(category: data)
14 @model = new Category data
15 @deleteButton = $("#delete-category-button")
16 @deleteButton.click(@onDeleteButtonClicked)
17
18 onDeleteButtonClicked : (event) =>
19 event.preventDefault()
20 @model.destroy
21 success: ->
22 app.routers.main.navigate(&quot;home&quot;, true)
23 error: ->
24 alert "An error occured, category was probably not deleted."
25 app.routers.main.navigate("home", true)

Com Git, commit

git commit public/ -m "Add deletion button to UI"

5. Escrever especificações de recursos de backend

Agora sabemos que precisamos de um recurso para deletar uma categoria, então vamos escrever nossa especificação de recurso de exclusão de categoria e commit.

Com Vows

01 .addBatch
02 'DELETE /categories/category-02/':
03 topic: () ->
04 apiTest.del 'categories/category-02/', @callback
05
06 'response should be with a 200 OK': (error, response, body) ->
07 assert.ok false
08 'GET /categories/category-02/':
09 topic: () ->
10 apiTest.get 'categories/category-02/', @callback
11 'response should be with a 404 Not Found': (error, response, body) ->
12 assert.ok false
13 'DELETE /categories/category-02/':
14 topic: () ->
15 apiTest.del 'categories/category-02/', @callback
16 'response should be with a 404 Not Found': (error, response, body) ->
17 assert.ok false

Com Git

git commit test/ -m "Add backend resources specs"

6. Escrever especificações de testes de backend

Agora escreveremos nosso código de teste, apenas checamos que os códigos HTTP retornados são os esperados e que uma vez que a categoria é deletada, ela não pode ser mais alcançada. Então, fazemos o commit.

Com Vows

01 .addBatch
02 'DELETE /categories/category-02/':
03 topic: () ->
04 apiTest.del 'categories/category-02/', @callback
05
06 'response should be with a 200 OK': assertStatus 200
07 'GET /categories/category-02/':
08 topic: () ->
09 apiTest.get 'categories/category-02/', @callback
10 'response should be with a 404 Not Found': assertStatus 404
11 'DELETE /categories/category-02/':
12 topic: () ->
13 apiTest.del 'categories/category-02/', @callback
14 'response should be with a 404 Not Found': assertStatus 404

Com Git

git commit test/ -m "Add backend resources specs code"

7. Escrever código de recurso backend

Agora escrevemos o código: adicionamos uma nova rota que irá linkar para um novo recurso dedicado à exclusão de categoria. Então, fazemos o commit.

Com Express

1 app.del "/categories/:category/", routers.deleteCategory

Com Express e Mongoose

01 exports.deleteCategory = (req, res) ->
02 categoryProvider = new CategoryProvider
03
04 categoryProvider.getCategory req.params.category, (err, docs) ->
05 if err
06 console.error(err.stack)
07 res.json 'An error occured', 500
08 else if docs.length > 0
09 docs[0].remove (err) ->
10 if err
11 console.error(err.stack)
12 res.json 'An error occured', 500
13 else
14 return res.json success: true
15 else
16 res.json 'I dont have that', 404

Com Git

git commit test/ -m "Add category deletion resource"

8. Executar todos os testes

Executamos todos nossos testes backend e UI no browser e estamos satisfeitos de ver que todos eles funcionam.

Com Vows

vows --spec test/resources.coffee

9. Testar seu app manualmente

Depois de ter lançado todos os seus testes, teste sua aplicação como um usuário normal. O BDD é ótimo, mas nunca irá substituir o teste manual, normalmente deixamos passar alguma coisa que não é revelada pelos nossos testes.

A exclusão de categorias é possível

10. Rebase branch

Queremos adicionar nossos commits como fizemos na última versão do branch master, então usamos o comando rebase.

Com Git

git rebase master

11. Merge branch

Então podemos juntar nossos recursos no master trunk. Um push no branch master irá validar que nosso trabalho terminou!

Com Git

git checkout master
git merge feature-delete-category
git push
git branch -d feature-delete-category

12. Refatorar se necessário

O Desenvolvimento Direcionado para UI tem a boa vantagem de não permitir que você desenvolva recursos inúteis, mas ele não permite pensar na melhor maneira de desenvolver seu backend. Então você provavelmente precisará de alguma refatoração. Felizmente, com seus testes, a refatoração será mais fácil e segura. Além disso, padrões que você vir quando desenvolver sua UI, te levam a pensar sobre qual refatoração corresponde melhor às suas necessidades.

?

Artigo publicado originalmente por Frank Rousseau em https://gelnior.wordpress.com/2011/12/27/web-application-development-workflow-with-node-js/ sob a licença Creative Commons by-2.0.

Adora brincar com aplicativos web, entendê-los e construí-los desde que fez seu primeiro site, em 1997. Já trabalhou com várias situações na web, como o webradio, uma ferramenta para gerenciamento de projetos e um site de publicações.

Ver perfil