segunda-feira, abril 27, 2015

Fase 2 do projecto Sky Store está no ar

Foi há 11 meses que comecei a trabalhar no projecto Sky Store. Quando entrei no projecto já este tinha iniciado o desenvolvimento da 2ª fase e apesar da adaptação não ter sido tão rápida como gostaria, olhando agora para trás tenho de compreender que a dimensão do projecto torna difícil uma adaptação mais rápida.

Estamos a falar de um projecto de múltiplas equipas, em diversos fusos horários, com requisitos que nos obrigam a pensar tudo ao detalhe pois temos de servir milhões de utilizadores, nada pode ser deixado ao acaso. Foi a primeira vez, em já 10 anos que levo de trabalho nesta área, que senti que a qualidade final era o mais importante, que não havia cá prazos loucos impossíveis a cumprir, que não havia necessidade de fazer noitadas e fins-de-semana, porque tudo é planeado com rigor e com tempo para fazer as coisas bem.

Apesar de todas as equipas seguirem a mesma metodologia de desenvolvimento, com pequenas nuances entre elas, vou falar um bocadinho mais em concreto da minha equipa, a equipa do Core. A equipa do Core, e traduzindo é a equipa responsável pela parte mais nuclear da aplicação, somos a equipa com menos visibilidade para o utilizador final e ao mesmo tempo somos a equipa mais crítica porque somos o início de tudo e se nós falhamos vamos comprometer o trabalho de todas as outras equipas. O nosso foco principal é desempenho, segurança e estrutura da aplicação, estamos ainda algo longe dos frontends com os utilizadores finais.

As equipas utilização Scrum como metodologia de desenvolvimento, dailys, retrospectives, demos, planeamentos, desenvolvimento iterativo, etc. Isto facilita muito a integração de uma pessoa nova, a comunicação constante, o envolvimento com tudo o que se está a passar, ajuda imenso a começar a perceber rapidamente as várias características do projecto. Foi a primeira vez que trabalhei efectivamente com uma metodologia ágil de desenvolvimento e se tinha alguns pontos de interrogação iniciais porque na teoria parecia-me que as premissas era algo fortes, depois com o decorrer dos tempos percebi que realmente funcionava porque as regras acabam por ser mais flexíveis e adaptadas ao perfil da equipa.

Por falar em equipa, apesar de algumas alterações na estrutura ao longo destes 11 meses a equipa é composta por 1 scrum master, responsável por ser a cola entre os elementos da equipa e entre a nossa equipa e as restantes, 2 testers que essencialmente garantem a qualidade de tudo o que é feito e 6 developers que desenvolvem o código. Nada disto é estanque, nada disto é muito rígido, todos nós podemos desempenhar ou ajudar no papel de outra pessoa, há liberdade e flexibilidade para que isso aconteça, o que é óptimo na perspectiva que o conhecimento está disseminado pelos diversos elementos da equipa não tornando ninguém indispensável, e mesmo estando alguém de férias ou não podendo vir trabalhar por um outro motivo o trabalho dessa pessoa pode ser feito por outro elemento. Claro que isto só é possível não pela metodologia mas pela qualidade dos elementos da equipa que devo dizer são excepcionais. Já tive alguns colegas de trabalho que acho que são muito bons mas foi a primeira vez que numa equipa tão grande consigo dizer que o poder de decisão, a autonomia e a qualidade do resultado final de todos os elementos da equipa é elevadíssima.

Ao início foi mesmo intimidativo, o receio de errar, de não estar ao nível das expectativas, de não conseguir acompanhar esta equipa, costumo dizer que deixei de ser o tubarão do lago para ser um peixinho no oceano, foi mesmo a sensação que tive nos primeiros tempos. Mas todos eles me ajudaram imenso, sempre disponíveis, sempre a ajudar com agrado, por isso acabei por me conseguir adaptar, sentido-me hoje como mais um elemento válida desta equipa.

E o resultado deste trabalho foi para o ar no dia 15 deste mês, a 2ª fase deste projecto foi lançada para os utilizadores do Reino Unido e da República da Irlanda, e foi a passagem a produção mais tranquila que alguma vez tive ainda para mais dada a dimensão do projecto, e isto só foi possível pela qualidade do trabalho final que por sua vez foi possível pelo bom planeamento e prazos realistas de desenvolvimento. Este projecto podia ser um case study para 99% dos projectos desenvolvidos em Portugal, como fazer as coisas bem feitas em prazos realistas traz muito menos dores de cabeça a nível de suporte e a nível da satisfação do cliente final. Neste momento já estamos numa fase avançada do desenvolvimento da fase 3 que trará algumas novidades interessantes à plataforma, mas quanto a isso ainda não posso falar, só espero que o resultado final a nível de qualidade se mantenha.

segunda-feira, abril 20, 2015

Meia maratona da areia 2015

A meia maratona da areia foi a última prova de treino antes do Half Ironman de Lisboa, mais uma vez estou numa altura em que estou a dar alguma intensidade de treino por isso não esperava um grande resultado. Esta é uma prova que gosto de fazer, há muito espaço para correr sem acotovelanços, a paisagem é relaxante e em alguns casos até nos faz abstrair do sofrimento, e depois apesar de ser no areal é uma prova bastante rápida em que o areal não faz assim tanta mossa como se julga inicialmente.

Arranquei forte e fiquei integrado num grupo de 10 atletas que seguiam logo a seguir ao pequeno grupo dos primeiros. Ao fim de 2 quilómetros íamos a um ritmo de 4min/km, estava a correr solto e bem mas decidi não continuar naquela loucura, no ano passado paguei bem caro um ritmo idêntico no início e depois fui a arrastar-me nos últimos 5 quilómetros. Fui progressivamente desacelerando até encontrar o meu ritmo de conforto. Cada vez que alguém passava por mim tentava seguir na cola a ver se o meu corpo de sentia à vontade com o ritmo. Até que por volta dos 7km chegou ao pé de mim a 1ª mulher e curiosamente o ritmo era mesmo aquele que eu procurava.

Fomos seguindo juntos a um ritmo que não era totalmente confortável mas era o ritmo certo para seguir, ao darmos a volta para começarmos o retorno íamos com cerca de 46 minutos, se o o ritmo se mantivesse acabaríamos a rondar a 1h32m o que não era nada mau para quem ia fazer um treino. Por volta dos 12km a rapariga vira-se para mim e diz-me - "Não é preciso estar a acompanhar-me, faça a sua corrida" - eu respondi que o ritmo era bom e que não lhe estava a fazer nenhum favor por estar a acompanhá-la, e a pensar para mim - "Vê lá é se não te lembras de dar nenhum esticão senão fico aqui apeado!".

Chegou uma altura em que começámos a ultrapassar outros atletas que estavam em quebra o que soube mesmo bem para o moral. Enquanto isso também começava o efeito miragem, que já tinha presenciado no ano anterior, como aquilo é o areal em linha recta começamos a ver a meta a alguns quilómetros de distância e apesar de parecer que é já ali ainda falta muito. Senão estamos mentalizados para isso o efeito pode ser terrível, como me aconteceu o ano passado que desmoralizei totalmente. 

À entrada do último quilómetro vem um atleta em recuperação que encosta a nós, respira atrás de nós por uns 10 segundos e arranca, nessa altura deixei-me estar com a minha companheira de corrida, foi a única altura que teria feito diferente se fosse um homem o meu companheiro de corrida. Nos últimos 400 metros vem mais um atleta totalmente em esforço e passa por nós e mais uma vez penso - "Vá lá aproveitem hoje que é o meu dia da boa vontade!" -  caso contrário e da maneira que me estava a sentir bem, a minha ponta final era rápida o suficiente para não me deixar ultrapassar por aqueles dois atletas.


Apesar de ter perdido aqueles lugares se calhar teria perdido muito mais tempo senão tivesse aquela excelente companhia durante a prova, por isso achei justo acompanhar a primeira mulher até à meta deixando-a cortar fita da chegada mesmo à minha frente. O resultado final foi de 1h33m06s acabando no 36º lugar em cerca de 200 atletas...nada mau para um treino. Aparentemente para o ano esta prova vai ter a distância maratona também, provavelmente será uma prova que vou inserir no meu calendário, veremos...

Dados da minha prova:
  • Tempo final: 1h33m06s
  • Tempo médio por quilometro: 4m25s/km
  • Velocidade média: 13,6km/h

sexta-feira, abril 17, 2015

Quem pode acabar um Ironman

Depois de ver o vídeo seguinte não tenho qualquer dúvida que qualquer pessoa consegue acabar um Ironman, gordo, velho, mulher, deficiente, não há nenhuma desculpa que me consigam arranjar para uma pessoa que consiga andar independentemente não consiga fazer um Ironman. Para algumas pessoas pode ser mais difícil, pode requerer uma preparação mais cuidada, pode significar um risco maior em termos físicos, mas a força de vontade é que manda. Quem sabe para o ano não seja eu a ter a alegria de cortar pela primeira vez a meta de um Ironman...

segunda-feira, abril 13, 2015

Passar o nome de uma coluna ou tabela como parâmetro num prepared statement

Vou começar por dizer que o que o título diz é parvo, sim é parvo, não porque não dá jeito ou porque a ideia é parva, mas simplesmente porque não é possível fazer. Se quiser fazer algo como o que está em seguida é para esquecer não é possível fazer:

SELECT @column FROM @table

Agora há uma forma mais ou menos elegante de resolver este problema. O que queremos ao termos prepared statements é evitar sql injection, esse é o verdadeiro problema. Então a solução passa por validar se a tabela e a coluna existem na nossa base de dados, e assim até validamos se a query é válida.
       private void AssertValidTableAndColumnName(SqlConnection connection, 
                    SqlCommand cmd, string table, string column)
       {
           cmd.CommandText = "SELECT COUNT(*) FROM SYS.TABLES WHERE NAME = @table";
           SqlParameter tab = new SqlParameter("table", SqlDbType.NVarChar, 500);
           tab.Value = table;
           cmd.Parameters.Add(tab);

           cmd.Prepare();
           int count = (int)(cmd.ExecuteScalar());

           if (count == 0)
           {
               throw new ArgumentException("Invalid table name", table);
           }
           
           cmd.CommandText = @"SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
                                WHERE  TABLE_NAME = @table
                                AND COLUMN_NAME = @column";
           SqlParameter col = new SqlParameter("column", SqlDbType.NVarChar, 500);
           col.Value = column;
           cmd.Parameters.Add(col);

           cmd.Prepare();
           count = (int)(cmd.ExecuteScalar());

           if (count == 0)
           {
               throw new ArgumentException("Invalid column name", column);
           }
       }

Temos assim a garantia que tanto a tabela como a coluna existem, se não existirem a aplicação enviará uma excepção. No meu caso quis mesmo que a aplicação terminasse, mas podemos não ser tão radicais e simplesmente retornar um booleano indicando o sucesso. Basta agora fazer uma query normal sem haver a preocupação que haja sql injection.

[...]
AssertValidTableAndColumnName(connection, cmd, table, column);
cmd.CommandText = string.Format("SELECT id,{1} FROM {0}", table, column);
[...]