Páginas

segunda-feira, 28 de novembro de 2016

Impressões e dicas do PSM I

Recentemente, como meta de trabalho, eu tirei a certificação Professional Scrum Master I (PSM I). Hoje eu gostaria de passar algumas impressões e dicas que eu tive em relação à esse exame, bem como o material de estudo que eu usei, para as pessoas que estejam interessadas em estudar e encarar esta prova de certificação.

A certificação PSM I é a primeira no plano de carreira de um Scrum Master, dentro das disponíveis no Scrum.org. O Scrum.org é uma empresa de treinamento de Scrum fundada por Ken Schwaber, um dos dois criadores do Scrum. Não é a toa que esta é uma certificação bem reconhecida e aceita dentro do mercado e da comunidade, junto da CSM da Scrum Alliance.

Existem algumas diferenças entre estas duas certificações:

  • Para a CSM, é necessário fazer um curso com um instrutor associado e depois fazer uma prova. Na PSM, basta fazer uma prova online. Não fiz a CSM, mas pelo que li na Internet o nível de dificuldade dela é menor que o da PSM.
  • Enquanto a prova da PSM custa US$ 150,00 (em torno de R$ 500,00, em média da cotação atual), o curso da CSM saí por volta de R$ 2.000,00.
  • De tempos em tempos, é necessário renovar a certificação CSM, pagando uma taxa de US$ 100,00. Na PSM, não existe esta necessidade de revalidação.
Entre as duas, eu preferi a PSM pelo custo menor.

Sobre a prova


Ok, mas como prova da PSM I? É simples, basta ir até o site do Scrum.org (https://www.scrum.org/Assessments/Professional-Scrum-Master-Assessments), escolher a opção para "Buy PSM I Assessment", pagar com um cartão de crédito internacional e em pouco tempo (no meu caso foi quase que instantâneo) chegará uma senha por e-mail para ser usada para o acesso à prova online.

A prova consiste em 80 questões para serem feitas em 60 minutos, tudo em inglês. Vale lembrar que a senha de acesso é válida para uma tentativa, então se falhar no teste, terá que pagar novamente. As perguntas são de múltipla escolha, do tipo:
  1. Única alternativa correta
  2. Escolha N alternativas corretas
  3. Marque todas as alternativas corretas
Quando eu fiz a prova, não encontrei nenhuma questão que não desse o número de alternativas que deveriam ser escolhidas. Não sei se foi questão de sorte mas isso foi muito bom pois tive mais segurança de dar uma resposta excluindo as alternativas incorretas.

A prova é feita pela Internet, não há nenhuma necessidade em se ter uma web cam para gravar o candidato ou nem nenhum artifício para verificar a identidade. Inclusive, é possível consultar qualquer material durante o teste, mas fique atento pois 60 minutos é corrido. Cada pergunta deve ser respondida em média em 45 segundos, o que não dá muito tempo para pesquisar e pensar na melhor resposta se já não souber do assunto. Se não sabe a resposta, assinale o que sentir mais confortável, marque a questão para revisão e pule para a próxima. Para piorar, o sistema da prova tem um refresh de página cada vez que se avança, ou seja, a usabilidade não é das mais modernas, o que gera uma apreensão toda vez que a página demora um pouco para carregar.

Dicas das questões


Existem palavras nas perguntas que fazem toda a diferença. Por exemplo, se a pergunta for "quem deve estar presente nas reuniões diárias (daily meetings)", a resposta será diferente se a questão fosse "quem pode estar presente nas reuniões diárias (daily meetings)". A diferença é entre "dever" (must / should) e "poder" (can). Qualquer pessoa pode estar presente nas reuniões diárias, mas somente o Development Team é que é obrigado a estar. Outra questão é a diferença entre "estar presente" (attend) e "participar" (participate). Todas as pessoas podem estar presentes mas elas não participam da reunião, ou seja, elas não podem falar nada, só acompanhar. A daily meeting é um evento do Scrum exclusivo para o Development Team. O Scrum Master pode participar dela se ele também foi um desenvolvedor.

Muitas das alternativas das questões podem ser eliminadas somente olhando os termos que não constam no Scrum Guide. Por exemplo, coisas como Sprint 0, que seria uma sprint inicial para ajustar sistema de controle de versão, alocar recursos, etc; ou Hardening Sprint, que seria um tipo de sprint executada de tempos em tempos para corrigir bugs ou melhorar código. Esse tipo de coisa, apesar de fazer sentido num primeiro momento, não existe no Scrum. O mesmo vale de alternativas que sugerem subdivisões de papéis dentro do Development Team: testadores, arquitetos e líderes de desenvolvimento. Isso não existe no Scrum, a equipe é multidisciplinar e por isso todas as responsabilidades desses papéis que eu citei são de todos os desenvolvedores. Outra pegadinha envolve dizer que existe algum período de tempo livre entre duas sprints. Isso não acontece: assim que uma sprint termina, com a reunião de retrospectiva, uma nova começa, com a reunião de planejamento.

Em 2016 o Scrum Guide foi atualizado e com isso abriu-se possibilidade de novos assuntos entrarem nas questões. Mais especificamente a respeito dos valores do Scrum: Commitment (comprometimento), Focus (foco), Openness (abertura), Respect (respeito) e Courage (coragem). Na prática apenas uma questão bem simples apareceu no meu exame sobre isso, bastando conhecer quais eram os valores do Scrum. Mas é possível que existam outras questões que abordem esse assunto.

Fora do Scrum Guide, alguns assuntos podem ser abordados. Podem existir questões que envolvem aspectos mais voltados ao desenvolvedor (TDD, continuous deployment, etc.), mas no meu exame não apareceu nada a respeito. Outro assunto que entrou pouco na minha prova era relacionado a escalar o Scrum, ou seja, o uso de Scrum em vários times e sua coordenação. Mas nada que precisasse de conhecimentos a respeito do framework Nexus (descrito no site do Scrum.org). Basicamente as questões eram a respeito de gerenciar as dependências entre times (que afinal é o grande desafio quando se escala o Scrum).

Cuidado com os conceitos de trabalho que você tem atualmente, pois eles podem ir de encontro com o que o Scrum prega.  Se uma questão disser que um gerente atribui tarefas para o time de desenvolvimento, isso a princípio parece correto já que isso é normal no dia à dia de qualquer empresa tradicional. Mas isso não é verdade para o Scrum. As equipes são auto gerenciáveis. De maneira similar, Scrum Master não é um líder de equipe no sentido de ser um chefe que dita como as coisas devem ser feitas. Cuidado também com material antigo. Os termos "cerimônias" e "Scrum Grooming", entre outros, não são mais utilizados.

Por último, para fixar conceitos eu sugiro fazer alguns cartões contendo informações sobre os eventos do Scrum. Liste todos e coloque quem são os participantes obrigatórios e opcionais, qual o tempo limite de cada um, quais são os artefatos de entrada e saída esperado.

Material de Estudo


Abaixo estou listando o material de estudo que usei para a prova.
  • Scrum Guide 2016 - ler, reler e entender. Esta é a fonte primordial da prova e compreendê-lo é essencial. É disponibilizado em vários idiomas. Eu sugiro ler uma vez em português e depois sempre em inglês, para não ter problemas com termos traduzidos.
  • Scrum Narrative and PSM Exam Guide: All-in-one Guide for Professional Scrum Master (PSM 1) Certificate Assessment Preparation (English Edition) - é um livro que explica todo o Scrum Guide voltado para a prova de certificação, além de conter várias questões para praticar.
  • Scrum - a arte de fazer o dobro de trabalho na metade do tempo - comecei lendo este livro, que explica as origens do Scrum e seu uso em ambientes fora do desenvolvimento de software. Não o classifico como uma leitura essencial para a certificação, mas ajuda muito ao explicar o porquê de alguns conceitos.
  • Scrum and XP from the Trenches - 2nd Edition - este é um livro grátis bem interessante, pois coloca uma visão prática do Scrum. Sugiro seguir com a segunda versão, pois o autor Henrik Kniberg comenta seu próprio livro inclusive fazendo críticas à ele. Só tome cuidado para não misturar as técnicas que ele descreve como parte do Scrum.
  • Open Assessments - estes simulados são oferecidos pela própria Scrum.org e muitas das questões caem na prova (sim, as mesmas questões, por volta de 10% da prova aliás). O nível de dificuldade delas é menor que a maioria das questões da prova mas mesmo assim são um bom ponto de validação de como você está preparado para fazer o teste.
  • Simulado de Mikhail Lapshin - é um simulado grátis disponível na Internet. As perguntas são de nível de dificuldade bem próximo ao que cai no exame.
  • PSM I Preparation Practice Exams (MPlaza) - são exames simulados muito parecidos com o acima. 250 questões para praticar e o autor é bastante acessível para tirar dúvidas. O produto é pago, mas peça por um desconto que eles dão.
Em relação aos simulados, faça-os após ler pelo menos o Scrum Guide para poder tirar o melhor proveito possível. Tente entender porque determinada alternativa é a correta e porque as outras não são. Dependendo da questão, se ela for muito subjetiva, você pode não concordar com a resposta. Neste caso utilize os fóruns do Scrum.org para que possa ver a opinião de outras pessoas.

Boa sorte!


terça-feira, 22 de novembro de 2016

.NET Core versus Chrome 54 - Invalid request line

Com o recente lançamento de uma nova versão do .NET Core, a 1.1 (https://blogs.msdn.microsoft.com/dotnet/2016/11/16/announcing-net-core-1-1/), fui correndo atualizar um projeto que estou trabalhando para poder experimentar as novas funcionalidades.

Este é um projeto que expõe várias API (WebAPI), e por isso eu uso a ferramenta Postman (https://www.getpostman.com/), dentro do Chrome, para simular as requisições.

Entretanto, ao atualizar o projeto e suas respectivas bibliotecas e colocá-lo para rodar, ao acessá-lo tanto pelo Chrome (ele tem uma página inicial, não é só API) quanto pelo Postman, o erro abaixo começou a aparecer.

info: Microsoft.AspNetCore.Server.Kestrel[17] Connection id "0HL0J500CHGCA" bad request data: "Invalid request line: <0x16><0x03><0x01><0x00><0xB9><0x01><0x00><0x00><0xB5><0x03><0x03><0xD0><0x95>yq6<0x92><0xCA>6v<0xA9><0x0A>" Microsoft.AspNetCore.Server.Kestrel.BadHttpRequestException: Invalid request line: <0x16><0x03><0x01><0x00><0xB9><0x01><0x00><0x00><0xB5><0x03><0x03><0xD0><0x95>yq6<0x92><0xCA>6v<0xA9><0x0A>

Muito frustrante. Tentei até voltar a versão do .NET Core para 1.0. As chamadas continuaram dando erro, só que desta vez a mensagem era diferente.

Microsoft.AspNetCore.Server.Kestrel: Information: Connection id "0HL0J555RROF" bad request data: "Malformed request: MethodIncomplete"
Microsoft.AspNetCore.Server.Kestrel.BadHttpRequestException: Malformed request: MethodIncomplete

No Chrome, a mensagem era ERR_SSL_PROTOCOL_ERROR. Achei estranho pois a URL que eu acesso é http://localhost:5000/, sem SSL. Ao monitorar a chamada pelas ferramentas de desenvolvimento do Chrome, percebi que estava sendo retornado um código 307, pedindo para que a requisição fosse redirecionada para usar HTTPS.

Ferramenta de monitoração de rede do Chrome mostrando requisição 307 mandando o browser ir para url com https


Perdi boa parte do meu final de noite procurando uma forma de resolver, e acabei desistindo. Hoje, encontrei um bug aberto no Github do projeto do Kestrel: https://github.com/aspnet/KestrelHttpServer/issues/1217

Era exatamente o mesmo problema que eu tive! Em resumo, o problema é com a última versão do Chrome, a 54, pois eu conseguia trabalhar com a versão 53 sem problemas neste projeto com o .NET Core 1.0.

A solução para o problema é simples: ao invés de utilizar o endereço no localhost, se eu fizer a chamada apontando para o IP 127.0.0.1, tudo funciona normalmente!

Com isso, pude voltar a trabalhar tranquilo no projeto e fazer os testes. Quem estiver com esse mesmo sintoma, sugiro tentar mudar o endereço.

Obs. No mesmo bug no Github, é sugerido remover a entrada "localhost" das configurações do Chrome em "chrome://net-internals/#hsts", mas como trocar o endereço já funcionou para mim, eu nem fui atrás disso.

Abraços!

terça-feira, 1 de novembro de 2016

Publicando WebJobs no .NET Core no Azure com VSTS

Dentro de uma Web App do Azure, WebJobs permitem que códigos sejam executados em segundo plano. Por exemplo, se a aplicação web tem um processo pesado, ao invés de rodá-lo no contexto da Web App, podemos incluir um pedido de execução em uma fila do Azure Storage e o WebJob, rodando de tempos em tempos, executaria essa rotina. Isso diminui a carga de trabalho e aumenta o tempo de resposta das requisições web.

Um WebJob pode rodar desde um script, como JavaScript ou Python, a uma aplicação do tipo console em .NET (um aplicativo do tipo linha de comando). Essa execução pode ser contínua, com este aplicativo rodando interruptamente; ou agendado, executando em um intervalo pré-configurado.
Quando trabalhamos com nuvem, um aspecto importante é a agilidade em se implantar novas versões, e para conseguir isso a automação é um requisito essencial. Dentro da plataforma Microsoft, podemos utilizar as ferramentas de build e release do Visual Studio Team Services.

Um WebJob criado com .NET Core sendo implantado via VSTS é o cenário que vou descrever neste post. Existem artigos que demonstram como fazer isso com situações diferentes, por exemplo, a automação de implantação de WebJobs criados com o Azure SDK, mas que não é compatível hoje com o .NET Core (https://azure.microsoft.com/en-us/documentation/articles/websites-dotnet-deploy-webjobs/#overview) ; ou a criação de um WebJob com o .NET Core mas sem a explicação de como automatizar seu deploy no VSTS (https://blog.kloud.com.au/2016/06/08/azure-webjobs-with-dotnet-core-rc2/). O que quero aqui é suprir esta lacuna.

Vale citar que conforme as ferramentas e bibliotecas forem sendo atualizadas para suportar o .NET Core, é provável que num futuro breve este procedimento que vou descrever não seja o mais indicado. Mas até lá podemos fazer dessa maneira.


Os fontes


A solução é composta por um projeto web, um projeto do tipo console application e um projeto do tipo library que compartilha código entre os demais projetos. Este terceiro não é necessário, mas eu preferi fazê-lo por conta de organização e reutilização de código.

Este projeto está hospedado em uma conta do Visual Studio Team Services, utilizando Git como repositório de controle de fontes. Esta característica também não é necessária, poderia ser utilizado o TFS.

Configuração do build


É nesta parte que está o “pulo do gato”. Basicamente, o que eu faço após a compilação e publicação de ambos os projetos é copiar os artefatos do WebJob para dentro da estrutura de pastas do web site. Dessa forma, quando o site for publicado, o WebJob vai junto. Isso porque o conteúdo de um WebJob é armazenado dentro do próprio site, na pasta App_Data\jobs\{tipo}\{nome}, onde {tipo} refere-se à forma com que o WebJob será executado (continuous para jobs que executam sem parar; triggered para jobs que executam agendados ou manualmente) e {nome} sendo a identificação do job. É bem simples!

Abaixo estão todos os passos que eu usei para o processo de compilação e geração de pacote para instalação. Estou passando todos os detalhes deles inclusive com imagens, que é para ficar fácil de configurar uma nova definição de build.

Restaurar pacotes via comando dotnet (Command Line task)
Tool: dotnet
Arguments: restore

Compilar solução XXX.sln via Visual Studio
Solution: **\XXX.sln
Platform: $(BuildPlatform)
Configuration: $(BuildConfiguration)
Visual Studio Version: Visual Studio 2015

Publicar web site via comando dotnet (Command Line task)
Tool: dotnet
Arguments: publish -c $(BuildConfiguration)

Publicar WebJob via comando dotnet (Command Line task)
Tool: dotnet
Arguments: publish -c $(BuildConfiguration) $(Build.SourcesDirectory)\Site\src\XXX.Jobs\project.json

Copiar build do WebJob para pasta do web site (Copy Files task)
Source folder: Site/src/XXX.Jobs/bin/$(BuildConfiguration)/netcoreapp1.0/publish/
Contents: **
Target folder: Site/src/XXX.Web/bin/$(BuildConfiguration)/netcoreapp1.0/publish/App_Data/jobs/triggered/ProcessadorBatch/

Zipar arquivos em pacote de implantação (Archive Files task)
Root folder (or file) to archive: Site/src/XXX.Web/bin/$(BuildConfiguration)/netcoreapp1.0/publish/
Prefix root folder name to archive path: não
Archive type: zip
Archive file to create: website.zip
Replace existing archive: sim

Copiar pacote de implantação para área de staging (Copy Files task)
Source folder:
Contents: **/*.zip
Target folder: $(Build.ArtifactStagingDirectory)

Publicar artefatos na área de drop (Publish Build Artifacts task)
Path do publish: $(Build.ArtifactStagingDirectory)
Artifact Name: drop
Artifact type: Server


Configuração do release


A saída do build é um arquivo zip com tudo que é necessário para uma implantação completa do site, inclusive os WebJobs colocados nos caminhos corretos. 

Deploy Website to Azure
Azure Subscription (Classic): XXX (é o que liga a conta do VSTS com a conta do Azure)
Web App Location: Brazil South (você pode definir a região que melhor te atender)
Web App Name: XXX (onde será hospedado o site, no Azure)
Web Deploy Package: $(System.DefaultWorkingDirectory)\**\*.zip

Feitas essas configurações, basta solicitar a execução do build e do release, e o VSTS irá compilar e implantar o site e seus WebJobs.
Obs. Se o WebJobs for do tipo continuous, ele irá começar a rodar assim que o deploy terminar.

[]'s

terça-feira, 14 de junho de 2016

Aplicação Android Xamarin compilada no VSTS não inicia no celular

Estou estudando desenvolvimento mobile na plataforma Xamarin, e durante alguns testes meus, utilizando o Build do VSTS (Visual Studio Team Services), a minha aplicação Android compilada na nuvem simplesmente não funcionava quando instalada no celular.

Para depurar a inicialização dela, resolvi utilizar a ferramenta Android Device Monitor, que pelo Visual Studio pode ser acessada no menu Tools > Android > Android Device Monitor. Com o celular conectado na USB do meu PC e com a depuração ativada (no Android, em Settings > Developer Options > USB debbuging), eu consegui identificar o problema através do log.

A mensagem "You MUST run 'zipalign' on base.apk", logo depois de uma mensagem de erro do Mono, já disse tudo: faltou ativar o zipalign no momento em que o meu apk foi assinado.



Depois de ativar essa opção no Build que estou utilizando e efetuar nova compilação, a aplicação passou a abrir sem erros.


quarta-feira, 10 de fevereiro de 2016

SharePoint: problema em consulta de termos via JavaScript

O SharePoint tem um serviço de termos que pode ser usado tanto como navegação como classificação de itens (colocando tags em documentos, por exemplo).

Esse serviço de termos, chamado Managed Metadata Service, pode ser acessado através de uma API que pode ser consumida através de JavaScript.

Em uma funcionalidade na qual precisávamos acessar um conjunto de termos específico para popular um controle na tela, começamos a ter o erro abaixo quando a solução foi implantada no ambiente de testes.

Cannot read property 'toString' of null

O erro a princípio é simples de identificar, existe uma chamada do método toString em uma string que não recebeu nenhum valor. O problema é que esse erro dá dentro da biblioteca JavaScript do próprio SharePoint.

O código utilizado nessa chamada é o abaixo.

var termSetName = "NOME_TERMO";
var locale = 1046; //pt-BR
var clientContext = SP.ClientContext.get_current();
var taxonomySession = SP.Taxonomy.TaxonomySession.getTaxonomySession(clientContext);
var termStore = taxonomySession.getDefaultSiteCollectionTermStore();
var termSets = termStore.getTermSetsByName(termSetName, locale);
var termSet = termSets.getByName(termSetName);
var terms = termSet.getAllTerms();
clientContext.load(taxonomySession);
clientContext.load(termStore);
clientContext.load(termSet);
clientContext.load(terms);
clientContext.executeQueryAsync(function onSuccess() { 
    var enumerator = terms.getEnumerator(); 
    while (enumerator.moveNext()) { 
        var spTerm = enumerator.get_current(); 
        var name = spTerm.get_name(); 
        var id = spTerm.get_id(); 
        // ... 
    }
}, function onFailure(args) { 
    console.log(args.get_message()); 
});

Depois de analisar e comparar os ambientes, chegamos na raiz do problema: a obtenção do term store. Veja que no código estamos dizendo, na linha 5, para recuperar o term store padrão do site collection. Há uma outra forma de obter o term store, através do seu nome, mas havíamos decidido usar o padrão pois foi um código de exemplo que encontramos e funcionou!

A diferença dos ambientes foi uma configuração no serviço de termos:


Após selecionar a opção "This service is the default storage location for column specific term sets" nas propriedades do serviço, a solução começou a funcionar no ambiente de testes! Dessa maneira, há um term storage a ser usado no momento da chamada do método getDefaultSiteCollectionTermStore, cuja ausência aparentemente era a causa do problema.

Isso depois foi formalizado com o cliente, para que no ambiente de produção não haja esse tipo de erro.

[]'s