Como iniciar com Scrum - Bate papo com um futuro Scrum Master

Oi pessoal,

eu comecei a orientar uma pequena empresa parceira em como iniciar a implantação do Scrum. Abaixo reproduzo meu e-mail para o membro da equipe q será o Scrum Master. Comentários? Aguardo contribuições....tenho muito interesse em conhecer diferentes realidades....
Um abraço

--------------------
Minhas sugestões:
1) Você deve ser o Scrum Master da equipe
2) Estudar um pouco de scrum para entender o linguajar, e os conceitos.
a) o que é e qual é o papel do Scrum Master ( http://blog.eof.com.br/2008/03/06/qual-e-o-papel-do-scrum-master/ )
b) entender os principais conceitos: Product Backlog, Sprint Backlog. Sprint Planning Meeting, Sprint Review, Planning Pocker

3) Criar o Product Backlog. Para isso, você deve interagir com o cliente. Ele é o Product Owner, e é ele quem sabe como gerar o Product Backlog, e é ele quem sabe priorizar este backlog. Sugiro, se necessário, criar um product backlog para cada produto do projeto ( Admin, Carrinho de Compras, Barramento SOA, etc).

4) Criar um release Backlog para o release 1. Definir releases, junto com o cliente. Pegue o Product Backlog e quebre ele em dois ou três releases. Esses passos 3 e 4 são trabalhosos, e depende do seu esforço e do esforço do cliente. Você provavelmente vai ter umas 3 reuniões DE TRABALHO com ele, cada uma de umas 4 horas de trabalho. Diga a ele que é isso que você quer, que a empresa precisa: de uns 3 dias, de 4 hs, de trabalho conjunto seu e dele para gerar Product Backlogs e Releases Backlogs.

5) Crie um conjunto de cartas de baralho para cada integrante da equipe. Cada um tem que ter um jogo completo dessas cartas. Sugiro comprar uma cartolina mais grossa e fazer as cartas. Tipo isso aqui: http://www.flickr.com/photos/tlaukkanen/488795952/sizes/m/ ...... os números das cartas são esses mesmos: 0, 1/2, 1, 2, 3, 5, 8, 13, 20, 40, 100, e ?.

6) Junte toda a equipe e, juntos, façam um Planning Pocker, usando as cartas. Estimem cada item do backlog do Release 1. Como funciona este pocker:
- coloca-se no meio da mesa o item de backlog (ou fala-se o item).
- quem tiver dúvidas a respeito do item, pergunta, e as duvidas devem ser tiradas ali na hora. Todos devem entender o item de backlog.
- cada desenvolvedor escolhe uma carta. A carta representa os pontos de dificuldade de implementar o item de backlog. Um item muito facil de fazer é a carta 2. Um item dificílimo é a carta 40. As cartas menores que 2 e maior que 40 são para as exceções. Um item já feito recebe a carta ZERO.
- Após todos escolherem suas cartas, sem mostrar aos demais, todos juntos abrem suas cartas.
- Geralmente tem uma pessoa que escolhe uma carta de menor valor, e um outro que escolhe uma carta de valor mais alto. Por exemplo, um escolhe a carta 5 e outr escolhe a carta 20.
- O que escolheu o menor valor deve justificar porque escolheu um valor tao baixo. O que escolheu o maior valor deve fazer o mesmo: justificar.
- Após as justificativas, todos recolhem suas cartas e escolhem novamente outra carta (ou a mesma).
- Todos abrem suas novas cartas. Desta vez deve haver um consenso maior entre os participantes.
- Determine, finalmente, o valor de pontos deste item de backlog. O consenso é que determina. Se 4 escolheram a carta 13 e 1 escolheu a carta 20, 13 é o vencedor.
- E assim vai para todos os itens do backlog da Release 1. Faça na ordem de prioridade do backlog.

7) Marque um Sprint Meeting. Uma reunião com todos da equipe, você e o Product Owner (cliente).
a) a reunião é de 4hs de duração. Não mais do que isso. Se ela começar a passar de 4hs, interrompa a reunião. Uma das características do Scrum é o conceito de janela de tempo. O tempo é fixo. O que der pra fazer é feito, o que não der, não deu. Tanto para as reuniões, quanto para o tempo do Sprint (2 semanas).
b) O cliente pode repriorizar os itens do backlog, pois esses agora já estão estimados, e o cliente pode mudar a prioridade. O cliente deve determinar a ordem de prioridade dos itens deste backlog.
c) Nesta reunião apresenta-se a lista de itens do Release 1 Backlog para todos. Caso haja alguma dúvida por parte dos desenvolvedores, este é o momento de perguntar as dúvidas ao Owner. Pode-se até mudar as estimativas de pontos do item devido ao melhor entendimento do item. É importante a equipe perguntar TUDO: testes de aceitação, comportamento de tela, requisitos técnicos, etc). Você como Scrum Master tem o papel de provocar a equipe para perguntar e ter certeza de que a equipe está entendendo.
d) A partir desses, que já estão priorizados, a EQUIPE escolhe os itens que conseguirá se comprometer para a entrega ao final do Sprint. Quem diz o quanto consegue entregar é a equipe. Neste momento a equipe está se comprometendo a entregar aqueles itens de backlog. Com isso, criou-se o Sprint Backlog. A equipe deve considerar a completude da entrega: implementação, testes, documentação.
e) Pronto. Aqui então a equipe tem o Sprint Backlog. São os items que serão desenvolvidos no Sprint que se inicia.
f) Outro ponto importate é você, Scrum Master, não permitir que o cliente induza a equipe a aceitar mais itens do que conseguiria.
g) E finalmente: o Product Owner tem que se comprometer a não alterar o Sprint Backlog durante o sprint. Nessas 2 semanas que se iniciam, o Sprint Backlog NÃO muda.

8) Iniciar o Sprint de 2 semanas. Durante este período, seria bom a visita do Product Owner (cliente) regularmente. De 3 em 3 dias, ou algo assim. Desta forma a equipe tem a oportunidade de tirar dúvidas.

9) O Sprint se inicia com uma reunião da EQUIPE, sem cliente. Nesta reunião, o objetivo é quebrar cada item de backlog em Tarefas técnicas:
a) Modelagem
b) Criação de scripts de Banco de Dados
c) Implementação de Regras de Negócio
d) Estudo e avaliação de tecnologia
e) Implementação de testes unitários
f) Implementação de testes de integração
g) documentação
h) Implementação de Telas (html, css, javascript)
etc
- Cada item do Sprint Backlog deve ser quebrado em Tarefas.
- esta reunião pode ser logo em seguida da reunião de Sprint Planning Meeting que ocorreu com o Owner. Pode marcar o Meeting de manhã, e a reunião da equipe para quebrar em tarefas a tarde.

10) Primeiro dia do Sprint:
a) Você, Scrum Master, promove o Daily Meeting, que é a reunião diária de 15 min, em pé! Tem que ser rápida. Aqui, cada um diz o que fez ontem, os problemas que está enfrentando, e o que fará hoje (ou amanhã). A própria equipe se organiza em dizer quem fará quais tarefas. Sempre em ordem de prioridade dos itens do backlog.

11) Você, Scrum Master, deve deixar visível o Burn Down Chart. Desenhe ele no quadro para todos verem. Atualize diariamente, assim todos acompanharão o andamento do Sprint. Veja um exemplo aqui http://www.mountaingoatsoftware.com/system/hidden_asset/file/53/BurndownBarchart.xls
- Neste gráfico, a barra representa o total de pontos que ainda faltam no Sprint.
- É importante diferenciar entre os pontos planejados do Sprint (que foram escolhidos pela equipe para formar o Sprint backlog), e os pontos que surgiram ao longo do Sprint. Coisas imprevistas que apareceram e tiveram que ser feitas. Essas, devem entrar como tarefas extras, e devem ficar evidente, para que o cliente entenda qualquer atraso ou não entrega do que foi acordado.

12) Diariamente faça o Daily meeting, com todos da equipe, em pé. 15 min. Se houver algum problema, algum impedimento, que esteja causando paralisia da equipe, você como Scrum Master deve solucionar isso.

13) Durante o Sprint de duas semanas, você poderia atuar como um projetista de Protótipo de Telas. Sente com o cliente, entenda os itens do backlog do Release 1 que não fazem parte do Sprint 1 (ou seja, vc estará planejando o sprint seguinte, enquanto a equipe trabalha no sprint atual). Você poderia ir criando protótipo de telas que seriam aceitos pelo cliente, e direcionariam o desenvolvimento da equipe. Power point é uma ferramenta simples e eficiente para isso. Mando um exemplo em anexo.

O que todos deveriam saber sobre Mysql

Nestes tempos de desenvolvimento com frameworks que tentam (e conseguem) facilitar muito nossa vida abstraindo detalhes de baixo nível, muitas vezes deixamos de nos preocupar com o que se passa lá por baixo.


Mas, em aplicações que tendem a crescer, que com o tempo vão deteriorando em performance, muitas vezes os problemas estão no banco de dados, na forma como acessamos o banco, em como construímos nossas queries...

Esta apresentação aqui, apresentada no Sun Tech Days 2009, é muito boa para quem usa Mysql.

Abcs

Grails e Cloud: desenvolvimento, deploy, execução e monitoramento. Ciclo completo com Grails na Nuvem.

No início havia muitas dúvidas se o Grails iria ser útil para aplicações grandes, ou de grande porte. Mas peraí, o que é uma aplicação grande? eBay é gigante. Se considerarmos uma medida, aí acho que podemos definir grande. Page-views por mês, por exemplo, pode ser uma medida, já que é fácil de saber, de monitorar, etc.

Um eBay tem algo em torno de 15 bilhões de page-views por mês. A globo.com tem uns 2 bilhões de page-views/mês. Um Peladeiro.com.br tem 1,2 milhão de page-views/mês. O Peladeiro é pequeno, Globo.com é grande, eBay é gigante. Pelo menos na minha opinião, sem muito exercício científico.

Além da medida de grande número de acessos, há também: grande volume de dados, necessidade de alta disponibilidade e redundância, escalabilidade, hot swap, cluster failover, etc, etc....

Aí voltamos a pergunta original: o Grails é bom para isso? Dá pra confiar que uma aplicação grails serve para uma demanda de uma aplicação de grande porte?


Alguns casos reais confirmam que a resposta é sim. Por exemplo, o Linkedin.com usa Grails para algumas partes. Este site tem as seguintes características: 22 milhões de membros, 1,2 milhão de novos membros por mês. Acho que o site mesmo, quando vc acessa linkedin.com, não é em grails, apesar de ser em java. Mas há partes feitas em Grails.

Onde eu quero chegar afinal? Meu ponto é que acho que atualmente o Grails chegou aonde queríamos que ele chegasse: está maduro o suficiente, estável, performance boa o suficiente, há ferramentas para desenvolvimento, e agora há serviços prestados por fornecedores que dão suporte ao deploy, execução e monitoramento de uma aplicação grails na Nuvem (Cloud).

Um grande player neste mundo de Cloud é a Amazon, com seu AWS . Mas como desenvolver uma aplicação Grails para rodar neste ambiente virtual? A nuvem está lá, mas você não vê. Tem solução poder computacional escalável, solução de storage, de banco de dados relacional na nuvem, e muito mais....
Mas como usar isso tudo? Como fazer uma aplicação Grails rodar nesta infra poderosa, mas complexa?

Aí que eu acho que a SpringSource está dando um show! Primeiro os caras inventam o Spring, que é solução para DESENVOLVIMENTO. Depois começam a expandir para servidores, que é solução para EXECUÇÃO. Depois fornecem solução para ferramentas ajudando mais ainda no quesito DESENVOLVIMENTO. Aí lançam produtos para gerenciar e monitorar (MONITORAMENTO). Por último, lançam um serviço que te ajuda executar aplicações java na infra de Cloud da Amazon: Cloud Foundry.

E por último, os caras compraram a G2One, que era a empresa responsável por Groovy e Grails. O resultado é: Grails tá pronto para rodar em tudo isso citado aí em cima.

Portanto, no momento presente, você pode desenvolver uma aplicação Grails usando tudo que este excelente framework oferece, pode usar os plugins de eclipse para Groovy e Grails que a SpringSource está desenvolvendo, pode fazer deploy, execução e monitoramento da applicação na nuvem da Amazon usando o CloudFoundry (ou o Cloud Foundry Plugin pra grails). Isso é excelente!!! Sua aplicação grails fica escalável, podendo usar instâncias com balanceamento de carga (load-balance) em diferentes zonas de disponibilidade, pode usar replicação master-slave para seu Mysql, pode usar SSL no apache, monitoramento e restart automático de servidores que falham, auto-escala de instâncias do EC2 da Amazon (pagando apenas pelo o que usa), pode usar backup automático de dados com snapshots.......... tudo isso para uma aplicação grails rodando na nuvem, e você gerenciando via Web.

Na teoria é lindo. Temos que ver na prática agora.
t+

Enviando emails formatados com Html e CSS - será que vai certinho?

Muito bom esta tabela que mostra o que cada cliente de email consegue mostrar corretamente em termos de CSS nos emails Html que vc envia.

http://www.campaignmonitor.com/css/

Ou seja, não adianta referenciar um arquivo CSS na tag link lá no header, pois nem todos os clientes levam isso em consideração. E nem tag style no header, e nem..... olhe o link acima.

Abcs
Felipe

Serviços do Grails, Transações e Rollback automático

Comprei o livro recente que saiu do Glen Smith, o Grails in Action. E, claro, comecei a ler. Ainda não terminei. Mas já valeu a compra e a dedicação de ler só pelo fato que eu descobri e não sabia:


Nos serviços do grails ( classes *Service.groovy, dentro do diretório services), que possuem Transação Declarativa , o default é cada método ser transacional. Isso significa que uma transação será iniciada antes do método do serviço começar a ser executado, e será finalizada (commit ou rollback) ao final.

O rollback acontece automaticamente quando uma Exception é lançada. O que eu não sabia era que apenas Runtime Exceptions fazem o rollback acontecer. Checked Exceptions não. Isso mudou minha vida! :-)

Eu fazia um try catch no controller, às vezes, pegando o tipo Exception no catch. Grave erro conceitual de cara né, mas pior ainda, pois eu estava contando com o rollback que poderia não acontecer.

Então amigos: apenas classes derivadas de RuntimeException fazem o rollback acontecer.

Abcs

Manubia.com.br - Controle Financeiro com Grails e, agora, com jQuery

É pessoal....

depois de algum tempo, tempão mesmo, usando a dupla Prototype + Scriptaculous.....depois de saber usar bem esta dupla, de ler livro e tudo..... resolvi abandonar totalmente a dupla e me render ao jQuery.

Deu um trabalho danado migrar o Manubia.com.br (site de controle financeiro) para o jQuery. Tem muita coisinha diferente. Mas no final das contas, estou gostando muito.

Alguns dos motivos de ter feito a migração:

  • jQuery tem um mundo plugins que resolvem diversos problemas que a gente precisa ficar catando pela web quando usamos Prototype + Scriptaculous.
  • o jQuery tem um projeto inteiro dedicado a interface gráfica: jQuery UI
  • formatação de campos de um formulário (formatar valor numérico com pontos e vírgulas, de forma internacionalizada): Masked Input Plugin
  • Calendário tipo Date Picker para campos de datas: jQuery UI DatePicker
  • Plugin para manipulação de comboboxes (select boxes).
  • No final das contas, a gente escreve menos código JavaScript do que com Prototype. Parece que fica mais limpo o código.
  • Tem um site dedicado aos plugins
  • De acordo com alguns benchmarks (um aqui, outro aqui), o jQuery tem uma performance melhor do que o Prototype (ou seja, os usuários é que ganham).
  • Eu tenho tudo que preciso em uma biblioteca só, não preciso usar parte de uma, parte de outra, etc... (pelo menos por enquanto, vamos ver até quando).
É isso. Acho que o Manubia ganhou com este investimento que fiz... No fundo mesmo, eu precisava era do formatador numérico para campos input. Aí achei o plugin de jQuery...isso foi a gota d'água pra eu migrar. (Eu já tava p da vida por estar usando o date picker do Open Rico)

Abcs
Felipe

Filtro do Grails para impor SSL (https) a determinadas páginas

Olá pessoal,


hoje andei pesquisando a respeito de uso de certificados SSL com uma aplicação grails. Afinal, está chegando a hora de impor o uso de SSL (https) meu novo site de controle financeiro, o Manubia.com.br .

Então ao pesquisar o assunto, encontrei uma classe de um grails Filter que pode me ajudar muito em forçar determinadas URLs a usarem SSL e outras não. Por exemplo, uma página que mostra dados não confidenciais, não precisa usar SSL (https). Já uma página que mostra ou recebe um formulário confidencial DEVE usar SSL.

Aí vai o Filter. Ainda não testei, mas parece certinho.

Abcs

/**
* Created by IntelliJ IDEA.
* User: danielhonig
* Date: Jan 23, 2009
* Time: 4:27:10 PM
* To change this template use File | Settings | File Templates.
*/

import org.codehaus.groovy.grails.commons.ConfigurationHolder

class SSLFilters {
// Set these to your HTTP/HTTPS ports
def defaultPortHTTP = 80
def defaultPortHTTPS = 443

static def SSLRequiredMap = ConfigurationHolder.config.SSLRequiredMap

def shouldUseSSL(controllerName, actionName) {
// User actions use SSL
if (SSLRequiredMap[controllerName]!=null) {

//If * then all actions are secured
if (SSLRequiredMap[controllerName][0] == '*')
return true

//else look for specific action
if (SSLRequiredMap[controllerName].contains(actionName))
return true
}
false
}

def filters = {
sslFilter(controller: "*", action: "*"){
before = {
def controller = controllerName
def action = actionName
log.debug("SSLFilter: ${params?.controller}.${params?.action}")
def url = null

// SSL off by default
def useSSL = shouldUseSSL(controllerName,actionName)

log.debug("${controller}.${action}, useSSL:$useSSL")

// Get redirected url
url = getRedirectURL(request, params, useSSL);

// If redirect url returned, redirect to it
if (url) {
redirect(url: url)
return false;
}

return true;
}
}
}

def getRedirectURL = {request, params, ssl ->
log.debug("getRedirectURL: $ssl")

// Are we there already?
if (request.isSecure() == ssl)
return null;

def protocol
def port

// Otherwise we need to flip
if (ssl) {
protocol = 'https'

// If using the standard ports, don't include them on the URL
port = defaultPortHTTPS
if (port == "443")
port = ""
else
port = ":${port}"
}
else {
protocol = 'http'
// If using the standard ports, don't include them on the URL
port = defaultPortHTTP
if (port == "80")
port = ""
else
port = ":${port}"
}

log.debug("Flip protocol to $protocol")

def url = request.forwardURI
def server = request.serverName
def args = paramsAsUrl(params)
url = "$protocol://$server$port$url$args"

log.debug("getRedirectURL - redirect to $url")

return url;
}

def paramsAsUrl = {params ->
int ii = 0
String args = ""
params.each
{k, v ->
if (['controller', 'action', 'id'].find {k == it})
return;

if (ii)
args += "&"
else
args += "?"

args += "$k=$v"
ii++
}

return args

}
}

Controle Financeiro e Planejamento Financeiro com Grails e Prototype

Mês passado eu e um grande amigo, e meu sócio neste projeto, lançamos um site para controle financeiro pessoal: www.manubia.com.br


O site foi todo desenvolvido com Grails e a dupla Prototype/Scriptaculous.

Tenho me questionado se não deveria mudar para jQuery. Eu vi um benchmark e acabo ficando na dúvida. Alguém prefere o jQuery ao invés do Prototype?

Em fim..... o sistema do Manubia foi ótimo de ser feito com o Grails. É incrível a produtividade do Grails, todos os plugins (estou usando authentication plugin, mail plugin e o mail-confirmation plugin). E bastante efeito visual e ajax com o Prototype e o Scriptaculous. Tá ficando legal.

Sobre o sistema em si, é um sistema de controle financeiro, onde você pode inserir suas transações, ou importar arquivo do seu banco, e em seguida pode categorizar todos os seus gastos. Feito isso, o sistema apresenta gráficos muito interessantes comparando seus gastos ao longo dos meses, resumo de suas contas , entre outros. É muito interessante pois assim você tem visibilidade dos seus gastos, e pode, portanto, fazer um planejamento financeiro para a sua família.

Eu importei meus dados dos últimos 4 meses, e foi ótimo pois consegui, junto com minha esposa, descobrir nossos ralos financeiros. Assim poderemos fechar esses ralos e poupar um pouco mais...

Abcs
Felipe

Instalador para Mac de uma aplicação Java

Excelente artigo de como criar um installer para Mac de uma aplicação Java. Como esse artigo me salvou legal, copio ele aqui, só pra não perder.

How to Create a Mac OS X Installer for a Java Application
(Updated for Mac OS X 10.5 — Leopard)


With some simple steps you can turn your Java Swing program (.jar) into a proper Mac OS X application with a native installer. The instructions below step you through the process from scratch with a sample program called
SCREENSHOT
ICONS
"It's Showtime!" which simply displays the current time. Once you have successfully completed the tutorial with the sample Java program, modify the steps to work for your Java program.

1) Install Xcode

ScreenApple's Xcode suite includes development tools you'll need to bundle and package a Java program. First, download Xcode for Mac Development (version 3.1.1 or later) and open the downloaded .dmgfile. Now run the "XcodeTools.mpkg" file and complete the Xcode installation with all the default options.

Before continuing to the next step, it's a good idea to perform a "Software Update..." to make sure your OS files are current.

2) Launch Unix Terminal

ScreenUsing "Finder" go into "Applications" and then open the "Utilities" folder. Scroll down until you see "Terminal". Open "Terminal" and you're now at the Unix prompt.

3) Make Project Folder

ScreenAt the Unix prompt, enter these two commands:
mkdir ItsShowtime
cd ItsShowtime
The first command creates a folder called "ItsShowtime", and the second command moves you into the new folder.

4) Write Some Java Code

ScreenMac OS X comes with a simple but effective text editor called Pico. Use the following command to create and edit a new Java file:
pico ShowTime.java
Enter the following code:

ShowTime.java

import java.util.Calendar; import javax.swing.*; public class ShowTime { public static void main(String[] args) { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setTitle("It's Showtime!"); f.getContentPane().add(new JLabel( Calendar.getInstance().getTime().toString())); f.pack(); f.setVisible(true); } }

Use to exit Pico.

5) Compile Java Program

ScreenBack at the Unix prompt, compile your Java program into a class file:
javac ShowTime.java
ls -la
We could run the class file directly, but a class file is cumbersome. Instead we will create an executable JAR file.

6) Make Executable JAR

ScreenBefore we make an executable JAR file, we need a manifest file to indicate which class contains the "main" function. We'll use Pico again:
pico MainClass.txt
Our manifest file will only have one line:

MainClass.txt

Main-Class: ShowTime

Exit Pico and use the following "jar" command to create the "ShowTime.jar" file:
jar cmf MainClass.txt ShowTime.jar *.class
ls -la
Now test your executable JAR with the following command:
java -jar ShowTime.jar
The "It's Showtime!" window with the current time should display in the upper left corner of the screen. Click the red dot to exit the program.

While the manual commands for steps #5 and #6 above work fine, you can automate them using Ant with this build.xml file.

7) Create Application Icon

ScreenThe default icon for an executable JAR is a coffee cup. To add a custom icon, we need to use the "Icon Composer".

Download and save () this sample PNG image to the "Desktop": ShowTime.png

Then move the file into the "ItsShowtime" folder with the following command:
mv ../Desktop/ShowTime.png .
Now we can create the icon file.

Steps:
  1. Use "Finder" to navigate into the "Developer:Applications:Utilities" folder and double-click "Icon Composer".
  2. Go back to "Finder" and navigate to your "ItsShowtime" folder (which is in your home folder).
  3. Drag the "ShowTime.png" image file into the "128" box on the "Icon Composer" screen. When prompted about sizes, choose "Copy to all smaller sizes" and then click the "Import" button.
  4. Go into the "File" menu and select the "Save" option. Then deselect the "Hide extension" option and save as "ShowTime.icns".
  5. Quit "IconComposer".
Next we'll create a Mac application (with your new icon).

8) Bundle the JAR

ScreenUsing "Finder", navigate into the "Developer:Applications:Utilities" folder and double-click "Jar Bundler".

Steps:
  1. For the "Main Class:", use the "Choose..." button and go to and choose "ShowTime.jar".
  2. Check the "Use Macintosh Menu Bar" option.
  3. Use the "Choose Icon..." button to choose the "SnapBackup.icns" file (you'll need to navigate to the very top-level folder and then into the "Users" folder and your home folder to eventually find the "ItsShowtime" folder).
  4. Click the "Properties" tab and enter "1.0" into the "Version:" field.
  5. Also enter "1.0" into the "Get-Info String:" filed.
  6. Click the "Create Application..." button.
  7. Navigate into the "ItsShowtime" folder.
  8. In the "File:" field, enter "Show Time".
  9. Click the "Create" button.
  10. Quit "Jar Bundler".
You now have a proper Mac application. Next we'll create an installer for your application.

9) Create Mac Installer

ScreenUsing "Finder", navigate into the "Developer:Applications:Utilities" folder and double-click "PackageMaker".

Steps:
  1. In the "Organization:" field on the "Install Properties" window, enter "com.centerkey". Then click "OK".
  2. In the "Title:" field enter "Show Time".
  3. Go to the "Project" menu and select "Add Contents...". Navigate to "ItsShowtime" folder and select "Show Time".
  4. Click on the "Contents" tab. Check the "Include root in package" option and click the "Apply Recommendations" button.
  5. Now click the "Build" (hammer) button. In the "Save As:" field, enter "ShowTimeInstaller.pkg". Click the "Save" button and then the "Return" button.
  6. Go to the "File" menu and select "Save". In the "Save As:" field, enter "ShowTime.pmdoc" and then click "Save".
  7. Quit "PackageMaker".
Your installer is done, but it's not yet download friendly.

10) Put Installer on a Web Page

ScreenBefore putting the installer on the web, we need to zip it up into a single file. Use "Finder" to navigate to the "ItsShowtime" folder. Create a zip of "ShowTimeInstaller.pkg" using the "Compress" option on the menu.

Logging com Grails 1.1

Hoje fiquei tentando entender a configuração do Logging no grails 1.1...pois mudou um pouco.

Tem um bom exemplo aqui, que eu reproduzo abaixo.


log4j = {

appenders {
console name:'console', threshold:Level.ERROR,
layout:pattern(conversionPattern: '%p %d{ISO8601} %c{4} %m%n')
rollingFile name:"rollingFileTrace", threshold:Level।TRACE, maxFileSize:1048576,
file:logFile+'Trace।log', layout:pattern(conversionPattern: '%p %d{ISO8601} %c{5} %m%n')
rollingFile name:"rollingFileDebug", threshold:Level।DEBUG, maxFileSize:1048576,
file:logFile+'Debug.log', layout:pattern(conversionPattern: '%p %d{ISO8601} %c{5} %m%n')
rollingFile name:"rollingFileError", threshold:Level.ERROR, maxFileSize:1048576,
file:logFile+'Error.log', layout:pattern(conversionPattern: '%p %d{ISO8601} %c{5} %m%n')
}

error console, rollingFileDebug, rollingFileError, rollingFileTrace:
'org.codehaus.groovy.grails.web.servlet', // controllers
'org.codehaus.groovy.grails.web.pages', // GSP
'org.codehaus.groovy.grails.web.sitemesh', // layouts
'org.codehaus.groovy.grails."web.mapping.filter', // URL mapping
'org.codehaus.groovy.grails."web.mapping', // URL mapping
'org.codehaus.groovy.grails.commons', // core / classloading
'org.codehaus.groovy.grails.plugins', // plugins
'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
'org.springframework'

debug rollingFileDebug, rollingFileTrace:'org.hibernate',
'com.britetab',
'BootStrap',
'org.apache.ddlutils'

trace rollingFileTrace:'org.hibernate.SQL',
'org.hibernate.type',
'flex.messaging.services'

warn console,rollingFileDebug,rollingFileTrace:'org.mortbay.log',
'org.hibernate.tool.hbm2ddl'

root {
trace 'rollingFileTrace'
debug 'rollingFileDebug','rollingFileTrace'
error 'console','rollingFileError','rollingFileDebug','rollingFileTrace'
additivity = true
}
}

Infraestrutura e arquitetura do Digg

Muito interessante a apresentação de Joe Stump, que é o arquiteto líder do Digg.

Ele apresenta diversos problemas de escalabilidade enfrantados pelo Digg, e mostra algumas das estratégias e tecnologias usadas e ainda serão usadas. Ex.:
Será que um dia eu trabalharei num site que precisa de tanto? Mas o que é tanto? Bom, no caso deles (Digg), os números são mais ou menos esses:
  • 35.000.000 milhões de Uniques por mês
  • 3.500.000 de usuários
  • 15.000 requests / segundo
  • Centenas de servidores
Abcs

Web Sites de Alta Performance, Parte 3: Faça menos Requests HTTP

Este é o terceiro post da série Web Sites de Alta Performance. Esta série é baseada no livro de Steve Souders, High Performance Web Sites. Você pode ler a parte 1 e parte 2.

Como vimos no primeiro post desta série, apenas de 10% - 20% do tempo de carregamento de uma página é gasto com a geração do HTML que vai para o browser. Os outros 80% - 90% são gastos carregando os demais componentes da página (imagens, css, javascript, etc).

Portanto, uma primeira otimização que ataca estes 80% - 90% é diminuir o número de Requests HTTP que a sua página faz.

Quando você acessa uma página web, colocando o endereço da página no browser, esta página carrega o seu HTML que, por sua vez, faz outros Requests HTTP para carregar os demais componentes necessários: arquivos javascript, arquivos CSS, imagens, flash, etc. Para cada componente, é um novo Request Http que está sendo feito. E uma requisição Http tem todo um overhead do próprio protocolo Http. Ao diminuir o número de Requests, você está diminuindo o tempo total de carregamento da sua página.

Para conseguir diminuir o número de Requests, algumas coisas podem ser feitas:
  1. Uso de Image Maps:
    Image Map permite que se tenha apenas uma imagem com múltiplos links nesta imagem. Ou seja, não é necessário, ao criar uma toolbar por exemplo, ter várias imagens, uma para cada link. É possível ter apenas uma imagem maior, cujas partes desta imagem possuem diferentes links. Isso é feito através do uso de Image Map.

  2. Combinar arquivos em um único:
    Ao invés de fazer 4 requisições para 4 diferentes arquivos de JavaScript (JS), você pode combinar os 4 arquivos em um único, e fazer apenas uma requição Http. Em sendo um engenheiro de software, isso me parece estranho, pois vai contra a modularização. Mas, se pudermos ter esta modularização em tempo de desenvolvimento, e e combinar estes arquivos em tempo de deploy, teremos assim o melhor dos dois mundos.
    A mesma coisa vale para arquivos CSS: é possível combinar os diferentes arquivos CSS em um único. Combinar arquivos pode ser desafiador quando os scripts e arquivos css variam de página para página, mas tentar fazer esta junção em um único arquivo pode ser vantajoso. Se você conseguir fazer esta combinação automaticamente como parte do seu processo de Deploy, isso pode ficar transparente para o desenvolvedor, e assim conseguir fazer menos Requests HTTP, melhorando a performance final da sua página.
    Numa situação ideal, sua página poderia ter apenas um arquivo javascript e um arquivo CSS.
    Em algumas situações em que a página faz uso de diferentes bibliotecas javascript e ainda possui scripts próprios, a combinação pode dar ganhos em torno de 40% no carregamento da página.

  3. CSS Sprites
    CSS sprites é uma técnica usada para se criar apenas um arquivo de imagem que conbina várias imagens que serão usadas independentes umas das outras através de estilos CSS. Ou seja, existe apenas um arquivo de imagem que é resultado da combinação de algumas imagens a serem usadas independentemente. Para conseguir usar cada parte da grande imagem de forma a mostrar apenas a parte que interessa de cada vez, usa-se estilos CSS. Por exemplo:

    Desta forma, podemos ter uma imagem grande de, por exemplo, 200px por 200px, mas estamos apresentando apenas uma parte dela, de 26 por 26 px.
    O uso de CSS Sprites, combinado com o uso de Cache de imagens, é uma excelente forma de usar múltiplos ícones em uma página, porém fazendo apenas um Request para carregar a única imagem grande. Você pode ver mais a respeito deste assunto no artigo de Dave Shea chamado "CSS Sprites: Image Slicing's Kiss of Death".
A conclusão aqui, então, é: FAÇA MENOS REQUESTS HTTP.

Web Sites de Alta Performance, Parte 2: Visão Geral de HTTP

Este é o segundo post da série Web Sites de Alta Performance. Esta série é baseada no livro de Steve Sourders, High Performance Web Sites. Caso não tenha lido o primeiro, leia aqui.

Antes de apresentar cada coisa que pode ser feita para diminuir o tempo de resposta das suas páginas, vou fazer uma breve introdução sobre o protocolo HTTP, e principalmente as partes do Hypertext Transfer Protocol (HTTP) que podem afetar a performance.

A versão mais usada do protocolo é o HTTP/1.1. Mas ainda hoje alguns browsers e servidores ainda usam o HTTP/1.0.  Este é um protocolo cliente/servidor feito de requisições e respostas (Requests e Responses). O browser envia um Request por uma determinada URL, e o servidor que hospeda esta URL retorna com um Response. Os tipos de Requests são GET, POST, HEAD, PUT, DELETE, OPTIONS e TRACE. Focaremos no tipo GET que é o mais comum.

Um Request do tipo GET possui uma URL seguida de headers. Um Response contém um código de status (Status Code), headers e um corpo (body).  Veja um exemplo abaixo, onde a primeira parte é o Request, e a segunda o Response:

GET /js/algumScript.js
HTTP/1.1
Host: meudominio.com
User-Agent:Mozilla/5.0(...) Gecko/20061206 Firefox/1.5.0.9
------------------------------------------------------------
HTTP/1.1
Content-Type: application/x-javascript
Last-Modified:Wed, 22 Feb 2006 04:15:54 GMT
Content-Length: 355

var f = function(){}....

Compressão

O tamanho da Response pode ser reduzido  usando algum tipo de compressão caso ambos, browser e servidor,  tenham suporte para tal compressão. O browser diz que tem suporte a compressão para o servidor usando o header Accept-Encoding. O servidor, por sua vez, diz ao browser que a Response está com compressão ao usar o header Content-Encoding. Por exemplo, o browser pode enviar a Request com o header:
Accept-Encoding: gzip,deflate
Enquanto que o servidor envia a Response com o seguinte header:
Content-Encoding: gzip

Não entrarei em mais detalhes agora, fica aqui apenas esta visão geral mesmo.

Requests Condicionais

Caso o browser tenha uma cópia de um componente (CSS, Javascript, Imagem, ...) no seu cache, mas não sabe ao certo se esta cópia ainda está válida, um Request Condicional é enviado pelo browser. Caso a cópia do cache ainda seja válida, então o browser usa esta cópia local e não baixa novamente o componente, tornando o tempo de resposta mais rápido para o usuário final.

Normalmente o browser sabe se o componente é válido ou não através da data que o componente foi modificado pela última vez. E ele sabe esta data através do header Last-Modified presente na Response. Veja no exemplo de Response acima que foi usado deste header.

Para realizar um Request condicional, o browser envia o Request com o header If-Modified-Since, cujo valor é a data presente na última response no header Last-Modified.  Caso o componente não tenha sido modificado desde esta data, o servidor envia um Response com status code "304 Not Modified", e não envia body nenhum, resultando num Response mais rápido. No HTTP/1.1 ainda existem os headers ETag e If-None-Match para a realização de Requests condicionais. Mas não falarei em detalhes desses no momento.

Expires

Os Requests condicionais e status code 304 ajudam muito no tempo de resposta dos componentes de uma página, porém eles ainda precisam de um ciclo Request/Response entre o browser e servidor. o header Expires elimina esta necessidade deixando bem claro para o browser o prazo de validade do componente, e assim deixando para o browser a mensagem de que ele pode usar a cópia local que ele tem, até a data presente no Expires, sem fazer nenhum Request.

Keep-Alive

O protocolo HTTP é baseado no protocolo Transmission Control Protocol (TCP). No início, nas primeiras implementações de HTTP, cada Request precisava abrir uma nova conexão Socket. Isso era ineficiente pois muitos Requests HTTP de uma mesma página são feitos para um mesmo servidor. As conexões persistentes (Persistent Connections), tambéem conhecidas como Keep-Alive no HTTP/1.0,  foram criadas, então, para resolver esta ineficiência de abrir e fechar várias conexões Socket para um mesmo servidor. Portanto, browsers e servidores podem usar o header Connection para indicar o suporte ao Keep-Alive. Tanto o Request como o Response podem conter:
Connection: Keep-Alive

No HTTP/1.1, o header Connection: Keep-Alive não é mais necessário, mas muitos browsers e servidores ainda usam.

No HTTP/1.1, o que é apropriado de ser usado é o chamado Pipelining, que permite múltiplos Requests numa mesma conexão Socket, e é mais performático do que Persistent Connections. Porém, Pipelining não é suportado pelo Internet Explorer, pelo menos até a versão 7 do IE. E também não é ativado por padrão no Firefox até a versão 2. Por enquanto, então, Keep-Alive ainda é a forma mais eficiente de usar conexões socket para HTTP. Ao se tratar de HTTPS, isso é aida mais importante, pois estabelecer uma nova conexão HTTPS é ainda mais demorado.

O protocolo HTTP tem ainda muitos outros detalhes que podem ajudar a tornar suas páginas mais rápidas, mas não vou entrar em outros detalhes aqui. 

Este post foi apenas uma visão geral do protocolo HTTP. Não mostrei ainda como aplicar algumas técnicas que fazem uso dos conceitos apresentados aqui. Isso fica para os próximos capítulos desta série. Abcs

Web Sites de Alta Performance, Parte 1: A Regra do 80-20 da uma Página Web

Este post é o primeiro de uma série que irei denominar de Web Sites de Alta Performance. Esta série é inspirada e baseada no livro High Performance Web Sites de Steve Souders, na posição de Chief Performance Yahoo!. O livro é fino, leve e bastante objetivo. Esta série tem o objetivo de resumir as técnicas apontadas por Souders.


Assim como diversos engenheiros de software que conheço, eu já me dediquei bastante a otimizações no lado do servidor, como melhorias no uso de memória e índices de bancos de dados, etc. Porém, para a maioria de páginas web, menos de 20% do tempo de resposta para o usuário final é gasto levando o HTML de resposta do servidor para o browser. Portanto, ao otimizar algo no lado do servidor, você estará otimizando algo que consome menos de 20% do tempo total de resposta.

Para conseguir resultados visíveis para seus usuários, é preciso atacar a causa dos 80% restantes do tempo de resposta. Esta série mostra conceitos que explicam o funcionamento de páginas web e algumas técnicas capazes de tornar suas páginas mais rápidas.

Analisando a performance de uma página

Para você conseguir ver como uma página qualquer é carregada e o tempo que ela gasta para ser carregada, vou sugerir o uso do browser Chrome do Google. Ele possui uma ferramenta de análise recursos carregados pelo browser (resources). Ao abrir o Chrome, acesse o site que deseja. Vá ao menu cujo ícone é uma folhinha (ao lado direito da barra de endereço do Chrome), selecione Desenvolvedor e em seguida Console Javascript. O Console possui dois itens principais: Elements e Resources. Clique em Resources. Agora, vá para a janela do browser e e dê um Refresh. Após carregar a página novamente, volte para a janela do Console e veja o resultado.
É possível ver muito claramente quais são todos os recursos carregados pelo browser para que a página final seja apresentada corretamente para o usuário: Html da página em si, imagens, arquivos CSS, arquivos Javascript. Cada recurso desse é um request feito ao servidor para que ele seja encontrado e baixado. Uma ferramenta de análise desses recursos sendo baixados é muito importante para podermos ver como nossa página está hoje e como ela estará depois de aplicadas as técnicas que serão expostas nesta série de posts do meu blog. Acho que o Firefox também deve ter algum plugin que fornece este tipo de informação.

O que essas ferramentas irão fornecer é uma visão como a da figura abaixo (que é a análise do carregamento da home do www.yahoo.com):


Afinal, porque uma página demora para ser apresentada?

Ao analisar o carregamento de uma página (com uma dessas ferramentas citadas acima), é possível ver que uma página comum (como por ex.: www.yahoo.com), ao ser carregada pela primeira vez no browser (sem nada no cache), gasta pelo menos 80% do tempo de carregamento total com os componentes da página (imagens, arquivos css e javascript, etc). Quando eu digo carregamento total, quero dizer:
  • Request de cada componente;
  • Requests que não ocorrem em paralelo (scripts não são baixados em paralelo);
  • Parse de Html, CSS e Javascript;
  • Renderização final
Ver onde que o tempo é gasto é desafiador. Mas ver onde que ele não é gasto é fácil: o tempo de carregamento de uma página não é gasto em sua maioria no download do documento HTML que é gerado pelo processamento do servidor, incluindo lógica de programação no servidor, acesso a banco de dados, etc.

Portanto, a regra para se manter em mente aqui é: APENAS DE 10% - 20% DO TEMPO DE CARREGAMENTO DE UMA PÁGINA É GASTO COM A GERAÇÃO DO HTML QUE VAI PARA O BROWSER. OS OUTROS 80% - 90% SÃO GASTOS CARREGANDO OS DEMAIS COMPONENTES DA PÁGINA.


Servindo JavaScript e CSS com velocidade

Vale a leitura.

São dicas de como diminuir o tamanho dos arquivos Javascript e CSS, e como fazer algumas coisas para os browsers fazerem o Cache corretamente desses arquivos.


Abcs