Páginas

sexta-feira, 8 de setembro de 2017

Impressões sobre a prova 70-532 (Developing Microsoft Azure Solutions)

Hoje passei na prova 70-532 da Microsoft, sobre desenvolvimento na plataforma Azure. Essa prova é um dos pré-requisitos para a certificação Microsoft Certified Solutions Associate: Cloud Platform. Vou aqui passar um pouco da minha experiência com a prova, como eu me preparei e algumas dicas.

Estrutura da prova


Já fazia algum tempo que eu não fazia uma prova de certificação da Microsoft e o formato da prova mudou um pouco. Nesta seção aqui vou explicar como é a dinâmica da prova, que provavelmente vale para outros testes de certificação da Microsoft também.

Foram 48 perguntas de vários tipos para um teste de tempo limite de 150 minutos. Essas perguntas são divididas em várias seções isoladas mas que compartilham o tempo geral. Quando eu digo isolada, quer dizer que uma vez respondidas as questões da seção, não se pode voltar nelas para se alterar. Ou seja, deve-se terminar por completo uma seção para que se possa acessar a próxima.

Existem dois tipos de seção: casos de estudo e perguntas gerais. A divisão da minha prova ficou em 4 seções de casos de estudo mais uma seção de perguntas genéricas.

Os casos de estudo, para mim, são chatos pois envolve todo um contexto no qual as perguntas da seção são feitas. Tem bastante coisa para ler. Mas existe uma estratégia para se lidar com eles e não acabar perdendo muito tempo: dê uma passada geral pela descrição do caso de estudo e seus detalhes, e depois vá direto para as perguntas. Aí lendo cada pergunta, você já sabe o que deve procurar de informação no texto do estudo de caso. Geralmente os dados que vão te ajudar a decidir a resposta não estão muito espalhados no texto.

Existem questões de vários tipos:
  • Tipo "sim ou não" - geralmente no começo dos casos de estudo, você deve falar se determinada solução irá resolver o problema descrito. Esse problema se repete em várias questões seguidas, sendo que a solução dada muda em cada uma das perguntas. Há também uma variação desse tipo de pergunta onde são apresentadas três afirmações que você deve informar se está certo ou errado.
  • Múltipla escolha - esse tipo de questão pede que você escolha uma ou mais alternativas como respostas. Quando se deve escolher mais de uma alternativa, é possível ter crédito parcial. Mas isso somente ocorre se estiver descrito na pergunta.
  • Escolher e ordenar passos - esse tipo de questão envolve ordenar os passos que são necessários para se fazer determinada operação.
  • Completar lacunas - geralmente associadas com código, nesse tipo de questão você tem várias opções para serem colocadas em lacunas. Esse tipo de pergunta também pode ter crédito parcial.


Tópicos relacionados


Na página oficial da prova, existe uma relação de assuntos que podem cair na prova: https://www.microsoft.com/en-us/learning/exam-70-532.aspx. Numa visão macro, são quatro tópicos que devem ser estudados:
  • Create and manage Azure Resource Manager Virtual Machines (30‒35%)
  • Design and implement a storage and data strategy (25‒30%)
  • Manage identity, application, and network services (15‒20%)
  • Design and implement Azure PaaS compute and web and mobile services (25–30%) 
Dentro de cada um existem subdivisões de assuntos. Mas existem coisas que podem cair e que não estão listados aqui! No meu exame caíram também conceitos de Cloud Services, que fazem parte do modelo antigo do Azure, o ASM, e que na teoria não deveria ser mais cobrado nesta prova, visto que ela recebeu uma atualização em Novembro de 2016 para trabalhar com o modelo ARM, mais novo. Outras coisas que caíram e que não estavam relacionadas são Automation Accounts, runbooks e implantação de Web Apps via GitHub. 


Material de estudo


Um dos problemas que vejo com essa certificação do Azure é que não existe um material compilado (livro oficial da certificação, por exemplo) que contemple tudo que é preciso para estudar e se preparar para esta prova. Talvez isso ocorra porque os recursos do Azure mudam com uma boa velocidade, fazendo com que coisas se tornem obsoletas rapidamente. Até existe um livro de referência ao exame 70-532, mas é relacionado ao modelo antigo e está obsoleto. É o livro do seguinte link (que aparece como indisponível para compra, provavelmente pelo motivo que eu citei): https://www.microsoftpressstore.com/store/exam-ref-70-532-developing-microsoft-azure-solutions-9780735697041.

Para dar uma visão geral da plataforma, eu comecei estudando pelo seguinte curso no Udemy: https://www.udemy.com/70532-azure/. Para se ter um conhecimento geral ele é bom, mas tenha em mente que ele não provê a profundidade necessária que a prova pede. Então a ideia é terminá-lo o mais rápido possível para poder prosseguir com os demais materiais de estudo. A plataforma Udemy geralmente dá promoções nos seus cursos, então espere isso acontecer para comprar esse curso por uns R$ 30,00, senão fica muito caro. Outra coisa que também vi é que existe um curso do 70-532, do mesmo instrutor, que contém simulados para treinamento. Esse eu não fiz então não consigo recomendar, mas se ele estiver com desconto eu acho que vale a pena usá-lo.

Outra fonte para uma visão geral é o livro Microsoft Azure Essentials: Fundamentals of Azure, Second Edition, disponível grátis para download em https://blogs.msdn.microsoft.com/microsoft_press/2016/09/01/free-ebook-microsoft-azure-essentials-fundamentals-of-azure-second-edition/. Mas tome cuidado, pois existem informações que estão desatualizadas, como por exemplo o tempo disponível para o restore point-in-time do Azure SQL na camada Standard, que antes era 14 dias e agora já é 35 dias.

Aprofundando, recomendo assistir os cursos da plataforma https://openedx.microsoft.com/. São grátis e dão até certificados. Se tiver oportunidade também veja os vídeos de Azure que estão na plataforma Pluralsight (https://www.pluralsight.com/).

Para treinar, existe um simulado do Measure Up (http://www.measureup.com/70-532-Developing-Microsoft-Azure-Solutions-P5566.aspx). Eu acabei comprando o acesso a esse simulado pois fazia parte de um pacote promocional para a prova, mas acho que se fosse para comprar por fora eu não o faria. Ele é caro, o acesso mínimo é de US$ 99,00, e francamente eu esperava mais dele pois ele tem um foco fraco no conteúdo mais atual do Azure.

Por fim, o principal ponto para estudos: a própria documentação do Azure, em https://docs.microsoft.com/en-us/azure/. São muitos artigos, mas é o lugar para se estudar e se preparar para esta prova. Minha sugestão é pegar cada um dos tópicos e pesquisar páginas nessa documentação. Por exemplo, um dos tópicos relacionados com API Management é como se limitar o acesso às APIs colocando-se limites. Então, se se buscar no Google por "api management protect APIs with rate limits", se chega na página "Protect your API with rate limits using Azure API Management" (https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-product-with-rules).

Bom trabalho com os estudos e boa sorte na prova. Abraços!

quarta-feira, 8 de março de 2017

Princípio de substituição de Liskov

Uma das regras que ajudam a nortear o design de objetos é o Princípio de Substituição de Liskov. Esse preceito foi definido inicialmente por Barbara Liskov em 1987 mas ganhou maior divulgação ao compor o grupo de regras chamado SOLID exposto por Robert C. Martin no livro Agile Software Development: Principles, Patterns, and Practices.

Este princípio diz que se q(x) é uma propriedade demonstrável dos objetos x de tipo T. Então q(y) deve ser verdadeiro para objetos y de tipo S onde S é um subtipo de T. Um pouco confuso na primeira vez que se lê, mas que na prática atesta que eu posso substituir uma instância de uma classe por outra instância que seja de uma subclasse da primeira, sem que isso altere o comportamento do sistema.

Diagrama de classes mostrando uma subclasse sendo substituída como dependência de uma classe

Vamos usar um exemplo para poder explicar melhor. Veja a listagem de código abaixo. Ela simula um sistema de cálculo de imposto para venda de veículos. A classe Carro contém um método chamado CalcularValorImposto que recebe o valor do veículo e quando acionado faz todo o cálculo dos impostos devidos (ICMS, IPI, etc.), armazenando o resultado em propriedades do objeto.

IMPORTANTE: os cálculos aqui estão bem simplificados, na vida real a tributação é bem mais complexa...

Um desenvolvedor pode então criar a classe Taxi, herdando de Carro, para fazer o cálculo de imposto na venda de veículos para transporte comercial de passageiros, aproveitando assim outros métodos que a classe Carro tenha e que sejam comum para o sistema (o que não deveria ser o fator para a decisão em se utilizar herança). Taxistas têm uma série de isenções de impostos para fomentar sua profissão. Este desenvolvedor então sobrescreve o método CalcularValorImposto zerando o valor dos impostos que o taxista é desobrigado a pagar.

A princípio não existem problemas nessa implementação pois eu consigo fazer o cálculo do imposto para compra de carros e de taxis chamando o método CalcularValorImposto da respectiva instância. Mas há um problema. Veja que no nosso cliente, que no código de exemplo é uma classe de teste de unidade, quando fazemos a substituição da dependência Carro no método DeveCalcularValorImposto por uma instância de Taxi, a funcionalidade quebra.

Este exemplo de código, neste contexto, não atende o princípio de Liskov. A pós condição na chamada do método CalcularValorImposto quando é feita na classe Carro é ter todos os valores de impostos calculados (as propriedades ICMS, IPI, PIS e COFINS). Já a pós condição na chamada do mesmo método para a classe Taxi é ter algum dos valores dos impostos calculados dada a isenção. Note que a pós condição da classe Taxi é mais "fraca", menos restritiva. Ter uma pós condição mais fraca na subclasse é um dos indícios de violação do princípio de Liskov. Outro sinal seria se as pré condições da classe filha fossem mais restritivas.

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace LiskovNok
{
    public class Carro
    {
        protected const double ALIQUOTA_ICMS = 12;
        protected const double ALIQUOTA_IPI = 18;
        protected const double ALIQUOTA_PIS = 1.65;
        protected const double ALIQUOTA_COFINS = 7.6;
        public double ICMS { get; set; }
        public double IPI { get; set; }
        public double PIS { get; set; }
        public double COFINS { get; set; }
        public virtual void CalcularValorImposto(double valorBruto)
        {
            ICMS = valorBruto * ALIQUOTA_ICMS / 100;
            IPI = valorBruto * ALIQUOTA_IPI / 100;
            PIS = valorBruto * ALIQUOTA_PIS / 100;
            COFINS = valorBruto * ALIQUOTA_COFINS / 100;
        }

        public double Imposto
        {
            get { return ICMS + IPI + PIS + COFINS; }
        }
    }
    
    public class Taxi : Carro
    {
        public override void CalcularValorImposto(double valorBruto)
        {
            base.CalcularValorImposto(valorBruto);
            ICMS = 0;
            PIS = 0;
        }
    }

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void DeveCalcularValorImpostoCarro()
        {
            DeveCalcularValorImposto(new Carro());
        }

        [TestMethod]
        public void DeveCalcularValorImpostoTaxi()
        {
            DeveCalcularValorImposto(new Taxi());
        }

        private void DeveCalcularValorImposto(Carro sut)
        {
            sut.CalcularValorImposto(45000);
            Assert.AreEqual(17662.5, sut.Imposto);
        }
    }
}

Agora vamos ver um exemplo onde a regra de Liskov é atendida. Vou mostrar ainda utilizando as classes Carro e Taxi mas com um contexto diferente.

Na listagem de código seguinte, vemos um sistema que faz o cálculo de estimativa de distância entre dois pontos no mapa para um sistema estilo Waze. A classe Carro faz isso através do método CalcularEstimativas onde recebe dois pontos (objetos da estrutura Coordenada que traz a latitude e longitude) e faz a estimativa. Por simplicidade, no nosso exemplo, eu fiz o cálculo traçando uma linha reta e usando o teorema de Pitágoras, mas sabemos que na vida real um carro percorre ruas e avenidas fugindo do trânsito, então um sistema real a estimativa de distância seria mais apurada.

Já quando adicionamos a classe Taxi neste sistema, além da distância também calculamos a estimativa de custo que esse trajeto trará para o usuário. Fazemos isso no mesmo método CalcularEstimativas. Novamente por simplicidade eu considerei como resultado da conta um valor inicial da bandeirada de R$ 4,50 mais R$ 2,75 de cada unidade de distância percorrida.

Vejam o que acontece no cliente, representado aqui pelo método DeveCalcularEstimativaDistancia. Não importa se eu passo um objeto do tipo Carro ou Taxi, a funcionalidade não vai quebrar! Neste caso, a pós condição da classe Taxi não se enfraqueceu. A classe Carro calcula a distância e a classe Taxi calcula a distância e o preço, ou seja, ela faz uma coisa a mais. A substituição de objetos ocorre sem problemas aqui, demonstrando que este exemplo agora atende o princípio de Liskov.

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace LiskovOk
{
    public struct Coordenada
    {
        public double Latitude;
        public double Longitude;
        public Coordenada(double latitude, double longitude)
        {
            Latitude = latitude;
            Longitude = longitude;
        }
    }

    public class Carro
    {
        public double Distancia { get; set; }
        public virtual void CalcularEstimativas(Coordenada pontoInicial, Coordenada pontoFinal)
        {
            double cateto1 = pontoFinal.Latitude - pontoInicial.Latitude;
            double cateto1AoQuadrado = Math.Pow(cateto1, 2);
            double cateto2 = pontoFinal.Longitude - pontoInicial.Longitude;
            double cateto2AoQuadrado = Math.Pow(cateto2, 2);
            Distancia = Math.Sqrt(cateto1AoQuadrado + cateto2AoQuadrado);
        }
    }
    
    public class Taxi : Carro
    {
        public double Valor { get; set; }
        public override void CalcularEstimativas(Coordenada pontoInicial, Coordenada pontoFinal)
        {
            base.CalcularEstimativas(pontoInicial, pontoFinal);
            Valor = 4.5 + Distancia * 2.75;
        }
    }

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void DeveCalcularEstimativaDistanciaComCarro()
        {
            DeveCalcularEstimativaDistancia(new Carro());
        }

        [TestMethod]
        public void DeveCalcularEstimativaDistanciaComTaxi()
        {
            DeveCalcularEstimativaDistancia(new Taxi());
        }

        private void DeveCalcularEstimativaDistancia(Carro sut)
        {
            sut.CalcularEstimativas(new Coordenada(0, 0), new Coordenada(12, 9));
            Assert.AreEqual(15, sut.Distancia);
        }
    }
}

A regra de Liskov é importante pois ela serve para confirmar se estamos fazendo um uso correto da herança de classes, sempre olhando o contexto geral da aplicação. Se não atendermos este princípio, pode ter certeza que alguma besteira está sendo feita. Herdar uma classe somente para reaproveitar códigos utilitários seria um exemplo de erro cometido.

Toda herança depende de um contexto. No primeiro exemplo, o contexto não permite que se tenha subclasses visto que são cálculos totalmente diferentes, não estão relacionados.

Lembre-se sempre de ponderar bem quando se está usando herança: se as pré condições não estão sendo fortificadas; se as pós condições não estão sendo enfraquecidas. Só dessa maneira podemos deixar o sistema melhor desenhado, o que reflete melhor o negócio que ele atende e facilita as manutenções futuras.

Mais para frente eu pretendo comentar de outros princípios do SOLID. Até a próxima!

segunda-feira, 6 de março de 2017

Permissão para busca em listas do SharePoint com acesso anônimo

Um problema recente que tivemos com um portal baseado em SharePoint foi a falta de retorno de registros do mecanismo de busca nativo para usuários anônimos. Haviam listas personalizadas que continham informações e que quando um usuário autenticado fazia a busca, esses dados eram trazidos como resultado. Já quando a busca era feita por um usuário anônimo (no caso, na parte do portal exposta na Internet), esses dados não vinham.

Após uma análise do log, descobriu-se que esses resultados eram removidos na hora de validar a segurança, ou seja, o SharePoint via que o usuário anônimo não tinha permissão para visualizar os dados dessas listas.

Para resolver este problema, foi necessário quebrar a herança de permissão das listas e dar o acesso faltante para o usuário anônimo poder visualizar os dados na busca. Para isto, foi utilizado o script PowerShell abaixo.

$web = Get-SPWeb "http://urldosite"
$list = $web.TryGetList("nome da lista")
$list.BreakRoleInheritance($true)
$list.AnonymousPermMask64= $list.AnonymousPermMask64 -bor ([int][Microsoft.SharePoint.SPBasePermissions]::AnonymousSearchAccessList)
$list.Update()

Depois de executar, foi necessário pedir para o SharePoint reindexar a lista e executar o processo de crawling incremental. Esta permissão AnonymousSearchAccessList, como o nome diz, faz com que os dados de determinada lista fiquem disponíveis para o processo da busca. Outras permissões que podem ser associadas à objetos no SharePoint podem ser encontradas neste link do MSDN: https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spbasepermissions.aspx

[]'s

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!