quarta-feira, 23 de dezembro de 2009
Bjarne Stroustrup também lê o "Micos"
quinta-feira, 17 de dezembro de 2009
Papai Noel, me dê usuários no Natal
Ter usuários é uma benção. Se você não tem usuários, todo seu esforço foi em vão, inútil, jogado fora. Todo sistema quer ter usuários pra provar pra si mesmo que merece existir. Não ter usuários resulta em aposentadoria precoce.
Ao mesmo tempo, ter usuários é uma maldição terrível. A partir do instante em que o primeiro deles clica o primeiro botão no seu sistema novinho em folha e recém-lançado, seus problemas começam. Os problemas são:
1. Dados
Enquanto não há dados de ninguém no seu sistema além das coisas engraçadinhas que você colocou lá nos seus testes, você pode mudar e desmudar o que quiser. Quando aparece a primeira informação de verdade, você passa a ter problemas. Não é mais possível fazer aquelas pequenas ou grandes mudanças sem pensar no efeito das mudanças sobre os dados que estão lá. Infelizmente o efeito é muitas vezes devastador: além de mudar seu sistema, você precisa transformar os dados existentes em dados que tem as propriedades novas que você quer. Tudo isso, é claro, enquanto seus usuários não param de jogar dados que você não quer pra dentro do seu banco de dados.
A solução: ao projetar seu sistema, antecipe as dificuldades de migração de dados e crie mecanismos para fazê-la facilmente. Por exemplo, garanta que sua camada de modelo é capaz de duplicar toda escrita em dois canais diferentes e ler de ambos também. Assim, você conseguirá fazer uma transição suave durante a qual tudo é escrito nas duas bases de dados. Quando isso estiver funcionando, você pode desligar a escrita na base antiga e ir copiando os dados para a base nova, enquanto o sistema continua funcionando e lendo das duas bases.
2. Comportamentos
Seus usuários vão se esforçar pra aprender a usar seu sistema. Como não desistiram, presumo que seu sistema seja bom. Acontece que se você mudar qualquer coisa que atrapalhe o esforço que eles investiram no aprendizado, eles vão te odiar, mesmo que a mudança tenha sido pra melhor. Aliás, não importa o que você faça, alguém sempre vai odiar.
Imagine que seus usuários tinham um limite ridiculamente pequeno de dados que podiam guardar no seu site. Imagine agora que de um dia pro outro você acabe com os limites e permita uso ilimitado. Toda funcionalidade permaneceu inalterada. Eu aposto o dinheiro que você quiser que algum infeliz vai reclamar e dizer que preferia quando tinha limites, pois forçava ele a se organizar melhor. A vida é assim.
A solução: como eu queria ter uma solução pra esse problema... o máximo que se pode fazer é tornar cada atualização a menor possível. Se você quer fazer várias atualizações, contenha-se e faça uma de cada vez para dar aos usuários o tempo pra se acostumarem com a nova forma de se usar o sistema. Se você quer fazer mudanças radicais, permita que os usuários retornem ao modo antigo de ser, pelo menos durante um tempo.
3. Comunicação
Você mudava qualquer coisa e só tinha de virar pro lado e avisar pro seu colega que a mudança estava pronta. Agora não é mais tão simples assim. Os usuários não entendem quando coisas mudam sem explicações. Toda vez que alguma coisa relevante mudar (tipo toda semana) você vai ter de dar um jeito de explicar aos usuários. O problema é que é difícil ser ouvido. Ninguém quer ler seu blog e ninguém lê as mensagens que você coloca na página de login. Se você deixa um espaço na página principal do seu sistema pra avisos importantes, os usuários logo desenvolvem cegueira seletiva e param de ver o que está lá.
A solução: se quiser mesmo comunicar com seu usuário, varie. A regra básica é colocar seu comunicado o mais próximo possível do local em que o usuário vai usar o que está escrito. Se é uma funcionalidade nova, coloque um "novo!" discreto ao lado do botão ou seja o que for. Um balão estilo estória em quadrinhos apontando para a novidade também é uma boa. Deixe que o comunicado seja uma surpresa. Outra coisa importante é deixar que o usuário retire o comunicado da tela e que ele não apareça mais.
Há outros problemas, é claro, mas esses ficam pra outros posts. Os micos de realejo vão dar uma parada para os feriados e férias, mas voltaremos no final de Janeiro a todo vapor.
Boas festas!
sexta-feira, 4 de dezembro de 2009
Quem faz a manutenção do seu sistema?
Só pra definir e situar todo mundo, manutenção de software é o nome que se dá para a fase do ciclo de vida de um sistema que começa no instante em que o sistema é colocado em funcionamento. É comum se classificar em três os diferentes tipos de manutenção. O primeiro tipo é a manutenção corretiva, ou seja, corrigir bugs. O segundo tipo é a manutenção evolutiva, ou seja, acrescentar novas funcionalidades. O último tipo é a manutenção adaptativa, que significa mudar o sistema para se adaptar a mudanças no ambiente em que ele funciona - por exemplo, porque saiu o Internet Explorer 9 e seu sistema ficou todo quebrado.
Não gostei do artigo. Os problemas que os autores usam para motivar seus argumentos não são reais. O artigo até seria bom se tivesse sido escrito em 1989, mas vinte anos depois as coisas são diferentes. Na era da internet, todo software é software em evolução. Não existe mais o conceito de software que não é criado com a evolução e manutenção em mente. Nunca trabalhei em uma empresa que não achasse isso importante e não tentasse planejar de acordo.
É claro que existem problemas interessantes envolvendo a manutenção de software. Hoje vou falar sobre um deles: quem deve fazer a manutenção. Na semana que vem falarei sobre outros.
Primeiro, preciso fazer uma confissão. Eu adoro fazer manutenção. Corrigir bugs então, nem se fale. Posso passar dias, principalmente bugs em código que eu não escrevi. Não, eu não estou sendo irônico, eu sei que a maioria dos programadores detesta isso. Pois pra mim não tem nada mais divertido. Quando estou procurando bugs em código que eu não conheço, eu me sinto um detetive investigando um mistério. Preciso tentar descobrir o que o código faz, por que faz o que faz, o que estava passando pela cabeça do programador que o escreveu. E no final tem um prêmio concreto: remover o bug! Bom demais.
Também gosto muito de fazer a evolução de código que eu não escrevi. Gosto de olhar para o design do sistema e tentar pensar em um design mais adequado à mudança que eu quero fazer. Não tenho a mesma motivação para mudar código que eu mesmo fiz. Eu olho para aquilo e penso no trabalho que já deu pra escrever, e não quero mudar tudo de novo. Quando o código não é meu, não tenho esse bloqueio.
Bom, voltando ao assunto. É comum entregar a manutenção de sistemas existentes aos desenvolvedores menos experientes, deixando os programadores que tem super-poderes livres para trabalharem nas novas idéias que vão render um trilhão de dólares. Para mim, isso é um erro. Deixar a evolução nas mãos de pessoas que não conhecem bem os motivos por trás das decisões que levaram o sistema a ser como é leva inevitavelmente à degradação acelerada da qualidade do código. O desenvolvedor que faz mudanças pontuais sem levar em consideração o design geral do sistema torna o código cada vez menos estruturado.
Quando projetamos um sistema novo, temos um grau elevado de liberdade para tomar decisões técnicas. Existe um número quase infinito de caminhos corretos que vão levar ao sistema que queremos construir. Fazer manutenção, por outro lado, implica em trabalhar com muitas restrições. Existem muitas maneiras de se fazer o que precisa ser feito, mas poucas maneiras corretas.
A não ser que seu objetivo seja abandonar o sistema a curto prazo em prol de um novo sistema que está sendo desenvolvido, deixe que os melhores programadores cuidem dele. Assim ele vai crescer com saúde e alegria.
Ah, tem uma exceção: eu acho que corrigir bugs é a melhor forma de introduzir um novo desenvolvedor a um sistema existente. É uma tarefa concreta que exige que o programador aprenda muito sobre as entranhas do código e sobre o design dos componentes. É só garantir que todas as mudanças serão revisadas por um desenvolvedor experiente para que o exercício não vire um problema depois.
terça-feira, 1 de dezembro de 2009
Se Fernando Pessoa também fosse mico
Fazer um software e reconhecê-lo mau depois de feito é uma das tragédias da alma. Sobretudo é grande quando se reconhece que essa obra é a melhor que se podia fazer. Mas ao escrever um software, saber de antemão que ele tem de ser imperfeito e falhado; ao está-lo escrevendo estar vendo que ele é imperfeito e falhado _isto é o máximo da tortura e da humilhação do espírito. Não só as linhas que escrevo sinto que me não satisfazem, mas sei que as que estou para escrever me não satisfarão, também. Sei-o tanto filosoficamente, como carnalmente, por uma entrevisão obscura e gladiolada. (...) E o maior castigo é o de saber que o que escrevo resulta inteiramente fútil, falhado e incerto. Em criança escrevia já meus códigos. Então escrevia-os muito maus, mas julgava-os perfeitos. Nunca mais tornarei a ter o prazer falso de produzir o programa perfeito. O que escrevo hoje é muito melhor. É melhor, mesmo, do que o que poderiam escrever os melhores. Mas está infinitamente abaixo daquilo que eu, não sei porquê, sinto que podia _ou talvez seja, que devia_ escrever. Choro sobre os meus códigos maus da infância como sobre uma criança morta, um filho morto, uma última esperança que fosse.Vai me dizer que não concorda com o nosso Fernando Pessoa imaginário?
Por sugestão do Hermes, adaptei este texto de Fernando Pessoa substituindo 'versos' por 'linhas de código' ou apenas 'código'. Também substituí 'obra' por 'software' ou 'programa', e a parte que eu não consegui simplesmente aplicar um
sed 's/verso/código/' | sed 's/obra/programa/'
removi.Por favor, não me crucifique pelo, digamos, plágio! Vai me dizer que nunca copiou-e-colou um código e aplicou alguns
sed
para acertar os detalhes?sexta-feira, 27 de novembro de 2009
Pare de escrever testes inúteis
Primeiro e menos grave, ter uma cobertura de testes alta dá uma falsa sensação de segurança. Se temos 80% de cobertura, então 80% do código não tem erros, certo? Não exatamente. O que estamos medindo é cobertura de comandos, que é a forma mais fraca de cobertura. Eis um exemplo simples:
if ((a > 0) || (b < 0)) { c = 0; } else { c = 1; }
Bastam dois testes, um com a==0 e outro com a==1 para cobrirmos todas as linhas. No entanto, se houver um erro na segunda cláusula (se tivesse de ser b > 0, por exemplo), nossos testes não detectarão o erro. Um testador experiente sabe que tem de testar as duas cláusulas, mas um inexperiente pode ser ludibriado pela medida de 100% de cobertura desse código e pensar que não há nada mais a fazer.
Segundo e mais grave, há testes que simplesmente não fazem sentido. Já vi inúmeros testes em que o testador está simplesmente repetindo todo o comportamento da classe sendo testada. Quando se usa frameworks como EasyMock ou Mockito, fica ainda mais fácil cometer esse erro. Esses frameworks nos permitem verificar se determinados métodos estão sendo chamados com certos parâmetros. Se só o que o método faz é chamar os métodos x, y e z, o que acaba acontecendo é que o teste unitário simplesmente verifica se x, y e z são chamados nessa ordem. Qual é o erro que pode ser encontrado por esse teste unitário? Nenhum. Só o que acontece é que quem modificar o método vai ter de modificar seu clone do mal nos testes unitários.
Imagine uma classe de modelo cujo objetivo é receber estruturas de dados internas e convertê-las em chamadas ao banco de dados. Como testar essa classe? Fazendo um mock do banco, chamando a classe com alguns valores concretos, e observando que o banco está sendo chamado com os valores corretos. Qual o valor de se fazer esse teste? Quase nenhum. O único valor é que você está efetivamente duplicando a funcionalidade que você fez na classe original e, se as duas implementações forem diferentes, você vai ter de olhar pra ver qual das duas está errada. É uma versão do fenômeno da segunda vez.
Quando faz sentido fazer testes de unidade, então? Pra mim, só quando a classe tem lógica interna, ou seja, toma decisões ou faz alguma computação real que pode ser observada externamente. O ideal é poder observar as mudanças no estado no sistema, e não o seu fluxo de controle. Traduzindo:
int metodo(int a) { int b = w(a); z(b); if (b > 0) { return x(b); } else { return y(b); } }
Como deve ser um teste para esse método? Deve ser um teste caixa-preta. O teste deve testar os valores retornados são compatíveis com diferentes valores de entrada de a. Nada mais. Para isso precisamos entender o que w(a), x(b) e y(b) retornam. E z(b)? Como sempre é executado, não faz sentido testá-lo. E devemos verificar se x(b) ou y(b) foram chamados? Na minha opinião, não. Devemos é saber se os valores de retorno esperados são equivalentes aos recebidos.
O bom teste deve desafiar o código sendo testado. Deve criar várias situações distintas e observar se o código reage de acordo com o desejado. Quanto mais forte o desafio, mais útil o teste. Desafios fracos criam testes fracos.
E daí, onde quero chegar com tudo isso? daí que criar e manter testes tem um custo, e esse custo não é trivial. Vamos então à lei de Torsten sobre testes unitários:
Todo teste unitário deve trazer valor a longo prazo maior que seu custo de criação e manutenção.Aqui, o valor do teste é proporcional ao desafio que ele faz ao código testado.
Resumindo, é OK não chegar nem perto de 100% de cobertura. Teste apenas o que faz sentido, lembre-se que nem todo teste é útil. E quando fizer sentido, teste direito, não se esqueça de testar nenhum caso importante só porque já cobriu todos os comandos.
quinta-feira, 26 de novembro de 2009
Ajude a definir seus direitos na internet, não deixe para o Frederico Pandolfo.
Lá eu fiquei sabendo de uma iniciativa super interessante: o Marco Civil da Internet. O marco civil é uma iniciativa do governo em definir direitos e responsabilidades do usuário de internet no Brasil. É o contrário da Lei Azeredo, que queria começar definindo quais são os crimes antes de definir quais são os direitos.
O mais legal é que está sendo feito de forma realmente democrática. A proposta de projeto está publicada no site e qualquer pessoa pode inserir seus comentários em cada seção do projeto. Há um debate muito interessante acontecendo, mas acho que pouca gente ainda sabe disso. Durante o painel, um representante do Ministério da Justiça explicou o esforço sendo realizado e me pareceu que o governo está realmente atento ao debate e levando a sério. O resultado do debate será transformado em anteprojeto de lei e levado para votação.
Quem é Frederico Pandolfo? Ninguém sabe, mas ele é responsável por quase um quarto de todos os comentários no site. Se você não quer que o Frederico Pandolfo decida quais serão seus direitos legais, vá agora mesmo ler a proposta e deixe lá seus comentários.
sexta-feira, 20 de novembro de 2009
Faça outra coisa
terça-feira, 17 de novembro de 2009
Um dia depois do outro
Viajar é bom mas é sempre difícil quando a gente volta, leva um tempo pra conseguir retomar as atividades. Aliás, nem é preciso viajar. Muitas vezes começar de manhã cedo já é complicado. Eu às vezes enrolo o quanto posso, lendo meu Google Reader, respondendo e-mail, tudo menos pegar no código.
Uma coisa que me ajuda muito a pegar firme de manhã é não terminar no dia anterior. Essa dica me deram quando eu estava escrevendo - pare um parágrafo no meio, sabendo como quer continuar, mas não continue. No dia seguinte, pegue aquele parágrafo pra terminar e fica fácil continuar escrevendo. A inércia está em começar algo novo.
O mesmo se aplica à programação. Eu agora nunca vou pra casa deixando o programa arrumadinho. Sempre fica algum erro de sintaxe, algum bug não corrigido, algum método sem terminar. No dia seguinte eu sei exatamente o que fazer e de repente me vejo trabalhando e não enrolando.
Sabe aquela vontade de "só terminar isso aqui que eu vou embora?" Não termine! Se você é do tipo procrastinador como eu, deixe pra terminar amanhã o que você começou a fazer hoje. Sua produtividade vai aumentar bastante.
quinta-feira, 12 de novembro de 2009
Remédio pior que a doença
sexta-feira, 6 de novembro de 2009
O que você faria diferente?
- Faça o que você gosta. Nao adianta ganhar dinheiro ou ter prestígio se você vai passar a maior parte das horas da sua vida fazendo coisas que não quer.
- Fazer o que gosta não é suficiente. É preciso ter certas competencias como gostar de aprender, comunicar-se bem em português e inglês, saber trabalhar em equipe e, naturalmente, ter uma base forte de fundamentos da computação, principalmente algoritmos e estruturas de dados.
- Se quiser fazer mestrado, faça agora. Se quiser fazer uma pós latu sensu, faça daqui a cinco anos quando tiver mais experiência. Doutorado, só se você quiser muito mesmo.
- Não tema o desemprego, tema sim as fracas condições de trabalho e salários oferecidos ao profissional de informática. Cabe a você informar o mercado de que esse profissional não é uma peça intercambiável da sua empresa. É melhor estar desempregado do que em um emprego ruim, pois ficar em um emprego ruim mostra ao mercado que empregos assim são aceitáveis.
- Eu não faria um MBA.
- Eu não deixaria de fazer meu doutorado, apesar de não ter seguido carreira acadêmica.
- Eu não trocaria de profissão.
quinta-feira, 29 de outubro de 2009
Do desencontro entre universidade e indústria - parte 3 - seus professores
Porque veja bem, ensinar não é trabalho. Eu mesmo me cansei de ouvir alunos perguntando se eu "trabalhava ou só dava aulas?" Tanto que parei de dar aulas e fui trabalhar, mas isso é outra estória.
O fato é o seguinte: fazer e ensinar são duas coisas completamente diferentes. Para ser bom em um não é preciso ser bom no outro, nem vice-versa. O fato da sua professora que te ensina design patterns nunca ter de fato usado um design pattern para resolver um problema que ela teve no trabalho dela é totalmente irrelevante. As questões são: ela sabe o que está falando? ela sabe te mostrar um exemplo que te ajude a entender o que ele está falando? quando você não estiver entendendo nada, ela sabe te pegar pela mão e te fazer perguntas e mostrar o caminho até você entender? Pois é isso que ela precisa saber.
Muito maior do que o problema da falta de experiência prática dos seus professores é a falta de incentivo para que sejam bons professores. Em universidades de pesquisa isso é gravíssimo. Há excelentes professores, mas excelentes porque querem ser e não porque ganham algo com isso. Se um professor de repente tem uma reunião cancelada e tem o dia inteiro livre pela frente, é muito melhor para a carreira dele investir aquele dia em pesquisa do que investir em melhorar as disciplinas que ele leciona. Não há incentivo para a excelência no ensino.
Nas universidades de ensino também não há incentivos. Qual a diferença em termos de carreira entre um professor que faz o mínimo para não ser mandado embora e um que dá o seu sangue e seus fins de semana para garantir que os alunos estão tendo a oportunidade de aprender algo importante? A resposta é que não há nenhuma diferença.
Se você é aluno, você tem professores que passam seus dias pensando em formas melhores de educar. Se você se importe com a falta de experiência de mercado deles, esqueça isso e comece a pensar em incentivos para eles se dedicarem mais a vocês, porque hoje eles tem poucos.
quarta-feira, 28 de outubro de 2009
Do desencontro entre universidade e indústria - parte 2 - o mundo real
Where are students supposed to learn about version control, bug tracking, working on teams, scheduling, estimating, debugging, usability testing, and documentation? Where do they learn to write a program longer than 20 lines?Dá pra resumir em uma frase: "os alunos não aprendem a desenvolver sistemas de médio/grande porte."
É claro que não. Só há uma forma de aprender a se trabalhar em uma equipe que faz um sistema de grande porte - trabalhando. Trabalhando durante meses e meses a fio. Se envolvendo com requisitos, projeto, repositórios de controle de versões, rastreamento de bugs, deadlines, milestones e tudo mais. Um professor pode até falar a respeito dessas coisas para introduzir o vocabulário, mas não haverá fixação sem a prática.
E por que não fazer isso na sala de aula? Por que não dedicar o último semestre de um curso de quatro anos inteiramente a um grande projeto realizado por todos os alunos em uma grande equipe? Os professores seriam os clientes e gerentes. Creio que com uns oito professores trabalhando juntos, conseguiríamos tocar uma equipe de 40 desenvolvedores inexperientes. Por que não fazer isso? Não parece uma boa idéia?
Primeiro problema: avaliação individual.
O objetivo de uma universidade não é só ensinar. É também entregar atestados chamados "diplomas" que atestam a quem interessar possa que o indivíduo que o carrega tem certas competências. É por isso que até hoje fazemos provas escritas quando todo mundo está careca de saber que essa é uma das piores formas de se avaliar competências - ainda não encontramos forma melhor que funcione quando temos mais de 5 alunos por professor.
Mesmo que cada um dos oito professores use o tempo que lhes sobra depois de gerenciar a equipe (se é que vai sobrar algum) para avaliar os alunos em algum quesito como qualidade do código, uso do repositório, produtividade, adesão à especificação, etc., etc., continua dificílimo avaliar cada aluno individualmente. As tarefas que cada um fará nunca serão homogêneas ou equivalentes, mas os alunos tem de ser avaliados segundo os mesmos critérios.
Segundo problema: qual projeto?
Coloque-se por um instante no lugar de um dos professores que está planejando esse lindo curso de um semestre. Antes do semestre começar, você e seus colegas tem de resolver as seguintes questões:
- Especificar detalhadamente um sistema que possa ser desenvolvido por 40 pessoas trabalhando 20 horas por semana durante 4 meses. Não erre suas estimativas nem pra mais, pois os alunos não podem ficar ociosos no final do semestre, nem pra menos, pois os alunos devem ser capazes de concluir o projeto para ficarem motivados.
- Preparar um laboratório com o ambiente de desenvolvimento, instalando e configurando todas ferramentas de controle de versões, acompanhamento de bugs, IDEs de desenvolvimento e tudo mais.
- Elaborar cronogramas detalhados com entregas bem definidas distribuidas por todo o semestre.
- Definir os critérios de avaliação e dividir as tarefas de gerência entre os professores participantes.
Terceiro problema: caos
Um projeto de 40 pessoas é caótico, não adianta querer que seja diferente. É preciso lidar com problemas pessoais, atrasos de umas equipes que prejudicam outras, problemas no ambiente de desenvolvimento, conflitos interpessoais e dezenas de outras coisas que acontecem no mundo real. Só que um curso universitário precisa de ordem e previsibilidade, caso contrário nada funciona.
Imagine os professores se reunindo para avaliar os alunos ao final do projeto:
Prof. Feliz: "Ufa! Não saiu nada como planejamos mas foi ótimo porque os alunos entenderam como funciona o mundo real. Mas que nota vamos dar pro Zé? Ele não fez nada."
Prof. Chato: "Ele não fez nada porque o João atrasou a entrega e ele teve de esperar. Não podemos penalizá-lo por isso."
Prof. Feliz: "Então que nota vamos dar pro João por ter atrasado?"
Prof. Chato: "Tem de ser altíssima apesar do atraso, só não atrasou mais porque o João carregou a equipe dele nas costas depois que a Vó da Elaine ficou doente. Ele é o melhor de todos."
Prof. Feliz: "Mas ninguém gosta dele! Ele quer fazer tudo e tolhe os colegas. Temos de levar isso em conta."
Sentiram? São nuances demais para se transformar em uma nota objetiva entre 0 e 100.
Até daria pra se fazer algo desse tipo em uma universidade, não é impossível. Só que nenhuma universidade que eu conheço tem os recursos necessários para se implementar um projeto desses com sucesso, e nenhum professor recebe o suficiente pra passar pela dor de cabeça que isso vai dar.
Tem ainda outro argumento que eu não usei mas que foi usado em um painel de discussões que assisti a muuuitos anos atrás, em que meu prof. José Nagib respondeu da seguinte forma a um comentário de um representante da indústria, semelhante ao comentário do Joel:
"Nós não sabemos ensinar isso que vocês querem. Vocês é quem tem de ensinar."Acho que é um bom jeito de encerrar o tópico de hoje.
Amanhã falarei sobre a capacitação dos professores.
terça-feira, 27 de outubro de 2009
Do desencontro entre universidade e indústria - parte 1 - conhecimento inútil
Ora, tem mais de vinte anos que eu escuto a mesma ladainha e, francamente, já me cansei. Os argumentos da indústria de software, representada aqui pelo Joel, são os seguintes:
- Os alunos só aprendem teorias que não tem utilidade prática
- Os alunos não aprendem a colaborar, a trabalhar em grupo, a depurar código, a documentar, a usar ferramentas, ou qualquer coisa que faça parte de um projeto real de software
- Os professores não tem nenhuma experiência com engenharia de software "de verdade."
- "Por que eu tenho de implementar uma pilha? Qualquer linguagem de programação moderna já vem com pilhas prontas e eu nunca nunca nunca vou ter de implementar uma pilha na vida."
O bom professor então dá um tapa na cabeça do aluno e diz, "É claro que não. Você precisa é aprender a escrever uma estrutura de dados; a encapsular informações; a definir uma interface; a manipular apontadores. É isso que você está fazendo. Vai trabalhar e para de reclamar."
- "Por que eu estou aprendendo Scheme? Ninguém no mercado usa Scheme!"
Porque programação funcional não é restrita a uma linguagem. É uma forma pensar e estruturar programas extremamente útil que pode ser feita em qualquer linguagem. Se você conseguir programar em Scheme, temos uma chance de você entender que forma é essa.
- "Eu trabalho e sei que na prática ninguém segue esses processos todos, é impossível."
Claro que ninguém segue. Você não vai usar esses processos do jeitinho que vem no livro. O que você vai fazer é destilar de lá algumas boas práticas que vão te ajudar a resolver problemas específicos em momentos diferentes. E mais, vai aprender o vocabulário necessário pra entender o que te dizem quando estiverem falando sobre projetos de verdade.
Continua na parte 2.
terça-feira, 20 de outubro de 2009
Sistema operacional 100% livre de erros? Bah!
O artigo descreve um sistema operacional embarcado desenvolvido por seis desenvolvedores em seis anos que "está 100% livre de erros de programação". Mais adiante no artigo encontramos a frase chave: "O sistema de verificação garante que o kernel atende inteiramente a toda a sua especificação." Se você ainda não viu a falácia no argumento, leia o post "a mesa errada".
Estar de acordo com a especificação não dá a menor garantia de que um programa não tem erros. O que garante é que há duas descrições equivalentes de um sistema - a especificação e o código. Se houver erros na especificação, haverá erros no código. Pior - a especificação é certamente uma abstração do código, ou seja, há inúmeros detalhes no código que não são tratados na especificação. Qualquer erro presente nesses detalhes não será apanhado pela verificação.
Não estou dizendo que a verificação formal é inútil, muito pelo contrário. É útil, como aponta o artigo, para garantir certas propriedades, como por exemplo garantir que um loop nunca terá valores fora de um intervalo específico, ou talvez garantir que todo objeto alocado será liberado mais tarde. Mas dizer que garante que o sistema não tem bugs é uma grande bobagem. Certamente é culpa do repórter, nenhum pesquisador sério alegaria isso sobre seu trabalho.
O artigo deveria se chamar "primeiro sistema operacional com 100% de conformidade à sua especificação está pronto" ou, melhor ainda, "primeiro sistema operacional que teve alguma especificação está pronto!"
ATUALIZAÇÃO: De fato, os autores do artigo original sabem o que estão falando e não falam nada sobre ausência de bugs - http://www.cse.unsw.edu.au/~kleing/papers/sosp09.html
Cadê os clássicos da "literatura de códigos"?
Por exemplo, o que diz essa função?
void saveAgendaAsCSV(List
String csv = new StringBuilder(MAX_CSV_SIZE);
for (user in agenda) {
csv.append(user.name);
csv.append(",");
csv.append(user.phone);
csv.append(",");
csv.append(user.email);
csv.append("\n");
}
return csv;
}
O novato diz que ela itera sobre os membros de uma lista de usuários e retorna um string com todos os dados dos usuários, um por linha. O programador experiente diz que ela converte uma lista de usuários ao formato CSV, para ser exportada. O grande programador sabe que essa função implementa a liberdade de dados que a aplicação permite. O novato sabe como a função trabalha. O experiente sabe o que a função faz. O grande sabe por que ela existe.
Todo código conta uma estória. O programador precisa saber ler além das simples linhas de código e entender a estória. Que estória esse trecho de código conta?
if (userId != 0) {
associarUsuarioAoGrupo(userId, groupId);
} else {
throw new RuntimeException("User id should not be zero.");
}
Desiste? A estória é a seguinte: um dia, houve um bug que levou horas para encontrar. O culpado era um id de usuário no banco de dados que valia zero, quando isso deveria ser impossível. Ao invés de descobrir como o problema aconteceu e corrigir o erro real, garantindo que isso nunca mais aconteça, o programador preferiu acreditar que o erro acontecerá de novo e está se defendendo para a próxima vez.
O que queremos estudar é a compreensão de textos, algo muito mais complexo do que sintaxe. Na escola estudamos o livro O Velho e o Mar, que pode ser apenas um conto de pescador, mas aprendemos que é uma alegoria que permite inúmeras interpretações sobre a condição humana. Assim precisa ser com a leitura de código - precisamos ensinar ao aluno a enxergar no código não só a estrutura de comandos, mas o projeto e arquitetura do sistema, assim como seus requisitos.
Só que implementar isso é bem mais difícil do que parece. Não acho que é suficiente uns alunos lerem o código dos outros. Como disse a Guta, eles precisam ler bons códigos. Mas de onde vamos tirar esses bons códigos?
Talvez eles venham da comunidade de código aberto, mas a verdade é que ainda não temos a resposta para essa pergunta. A comunidade acadêmica precisa coletar uma amostra significativa de bons sistemas para serem estudados - o equivalente a uma biblioteca de clássicos da literatura. Esses sistemas podem ser estudados por várias gerações de alunos e servirem como bons exemplos.
Vai dar um trabalhão, mas quanto mais esperarmos pra começar, mais vai demorar. Mãos à obra, então!
domingo, 18 de outubro de 2009
Fred Brooks no Brasil esta semana
Fred Brooks estará no IME/USP para lançamento da versão em português de seu clássico livro "O Mítico Homem-Mês". Ele irá proferir (em inglês) a palestra "Colaboração e Telecolaboração em Projetos: o quanto o modelo Bazar se aplica".
Inscrições gratuitas em http://www.caelum.com.br/brooks
Autor de O Mítico Homem-Mês chega ao Brasil para o lançamento da edição comemorativa
No dia 21 de outubro, em São Paulo, a editora Campus-Elsevier promove ações para o lançamento do clássico da literatura sobre Engenharia de Software. Frederick Brooks fará palestra no evento, que tem início às 14h, ministrada em inglês, com o tema “Colaboração e Telecolaboração em Projetos: o quanto o modelo Bazar se aplica", no auditório Antônio Gilioli, do IME-USP, na Cidade Universitária. Este evento conta com o apoio de Caelum, CCSL-USP e Locaweb. O autor também participa da noite de autógrafos, que acontece, às 19h, na livraria Saraiva, do Shopping Higienópolis. Os interessados pela palestra poderão se inscrever gratuitamente através do site www.caelum.com.br/brooks.
O Mítico Homem-Mês foi considerado a primeira obra literária de grande impacto que expôs claramente as peculiaridades da indústria de software. Nesta edição, ampliada, o autor apresenta três novos capítulos e os pensamentos mais atuais sobre o tema, além de uma retrospectiva sobre as principais mudanças ocorridas desde o lançamento da primeira edição, em 1975.
Com uma rica mistura de fatos sobre o assunto e opiniões que provocam reflexão, Brooks oferece sua visão e experiência para todos aqueles que lidam com a gestão de projetos complexos. Comemorando 20 anos desde a publicação original, ele adicionou novos pensamentos e conselhos. De acordo com especialistas, o clássico se tornou leitura indispensável à formação de todos os profissionais que estão envolvidos diariamente com projetos de software e seu gerenciamento.
Conhecido como o “pai do sistema IBM /360”, tendo atuado em seu desenvolvimento como gestor de projeto e, depois, como gestor do projeto de software do sistema operacional /360 durante sua fase de arquitetura, Frederick P. Brooks Jr. é professor patrono de Ciência da Computação na Universidade da Carolina do Norte, em Chapel Hill, nos Estados Unidos. Graças a esse trabalho, Brooks, Bob Evans e Erich Blow receberam a Medalha Nacional de Tecnologia em 1985. Em Chapel Hill, Dr. Brooks fundou o Departamento de Ciência da Computação, do qual foi presidente entre 1964 e 1984. Atuou no Comitê Nacional de Ciência e no Comitê Científico de Defesa. Atualmente, suas áreas de ensino e pesquisa estão relacionadas à arquitetura de computadores, aos gráficos moleculares e aos ambientes virtuais.
sexta-feira, 16 de outubro de 2009
Objetivos te ajudam a dizer não
O que quer dizer ser "o melhor"? Objetivos não mensuráveis são inúteis.
Um pouco mais concreto, mas ainda vago demais. Se você conseguir quantificar o que quer dizer com "mais produtivas", pode ser bom.
Esse parece perfeito, não parece? É bem claro, nada ambíguo e facilmente mensurável. Qual o problema, então? O problema é que ele não é útil para se tomar decisões no dia-a-dia. Pense em todas as decisões pequenas ou grandes que você toma no seu trabalho. Agora pense que a pergunta que norteia cada decisão é, "isso vai me ajudar a ter 10 mil usuários ativos?" A resposta honesta em quase todos os casos é "sim," pois presumo que você está decidindo sobre algo que vai melhorar seu sistema, e pode-se argumentar sobre qualquer tipo de melhoria que ela ajudará a atrair novos usuários. Se seu objetivo não te ajuda a dizer "não" durante uma decisão, ele não é útil.
O mesmo caso do exemplo anterior. Em que esse objetivo me ajuda a tomar alguma decisão importante?
Sem comentários.
Ah, muito bem. Então não é pra melhorar a usabilidade, nem criar novas funções, nem reduzir o número de erros, nem... entendi.
Esse não é tão fácil de se medir, mas dá um foco claro. Quero incluir joguinhos tipo quebra-cabeça no site. Devo? Bom, isso vai ajudar as pessoas a conversarem mais? Provavelmente não. Então não deve.Quanto menos abrangente um objetivo, mas útil ele lhe será, tanto no trabalho quanto na vida. Opa, me desculpem, trabalho é vida, mas isso é tópico pra outro post.
quinta-feira, 15 de outubro de 2009
Medidas são úteis, sim
ATUALIZAÇÃO 1: Me esqueci de avisar desde o início que estou falando de medidas DE USO de um sistema e não medidas DE DESENVOLVIMENTO do sistema, que são bem mais inúteis.
ATUALIZAÇÃO 2: Faltou uma utilidade óbvia - dimensionamento de capacidade. Depois que você mede algo por algum tempo, muitas vezes consegue extrapolar valores futuros para a medida, o que te ajuda a planejar a quantidade de recursos de que você vai precisar.
quarta-feira, 14 de outubro de 2009
Malcolm Gladwell e os usuários que não sabem inovar
"Na década de 70, se você perguntasse às pessoas que tipo de molho de espaguete elas queriam, nenhuma delas teria dito que queria um molho grosso com pedaços de tomate, mas era isso mesmo que um terço delas queria."
terça-feira, 13 de outubro de 2009
Quem são seus ídolos na engenharia de software?
Por exemplo, é impossível estudar computação, programação e não admirar Knuth. Aliás, conhecem o trabalho dele no livro 3:16? E no livro "Things a Computer Scientist Rarely Talks About"? Pois é, a contribuição do Knuth é muito maior do que "The Art of Computer Programming". Bom, mas o Knuth é um cientista muito conhecido. E engenheiro de software muito conhecido? Você conhece algum? Alguém que se entitula engenheiro de software de formação não vai ter ninguém, mas e de vocação?
Eu diria que o meu ídolo na engenharia de software é sem dúvida o Michael Jackson pelas contribuições dele à engenharia de software como um todo, mas principalmente por tornar muito clara a definição de requistos e especificações de software conforme o post da mesa errada. Michael Jackson é o melhor autor de se ler na engenharia de software. Após conhecer as idéias dele sobre a engenharia de software como um todo eu passei a compartilha-las e divulgá-las. Apesar do Michael Jackson ter atuado fortemente na indústria de desenvolvimento de software eu diria que atualmente ele se concentra mais na academia. Então minha outra pergunta é: quem é seu ídolo praticante de engenharia de software? Ou seja, quem está na indústria de desenvolvimento que você admira muito por suas contribuições ao corpo de conhecimento da Engenharia de Software?
Minha resposta é o Martin Fowler. Tive a oportunidade de ver o Martin Fowler falar em diversas OOPSLAs e ele é muito convincente sobre a prática da engenharia de software pois vive os problemas no seu dia-a-dia de desenvolvedor. Pelas suas contribuições em termos de padrões de análise, de arquitetura, refatorações e injeção de dependência, ele também é meu ídolo. E você, quem são seus ídolos na engenharia de software? Vou listar alguns engenheiros famosos, escolha o seu: David Parnas, Bertrand Meyer, Grady Booch, James Rumbaugh, Ivar Jacobson, Tom deMarco, Barry Boehm,
Kent Beck, Fred Brooks, a "gangue dos quatro" (Gamma, Helm, Johnson, Vlissides), Rebecca Wirfs-Brock, Pamela Zave, Mary Shaw... devo estar me esquecendo de vários. Quem mais você colocaria nessa lista?
Saiba o que fazer com suas métricas
Até aí tudo bem. Acredito que os números não mentem. Se suas medições indicam que seu site leva em média 2 segundos para servir uma página, então é isso aí. Se você fizer uma mudança e de repente ele leva só um segundo para servir, então sua mudança funcionou. Perfeito.
O problema é a parte de usar os dados para tomar decisões. Aí o buraco é beeeem mais embaixo, e merece a formulação da primeira lei de Torsten para métricas em software:
Qualquer decisão errada pode ser justificada com base em dados reais.Deixe-me exemplificar. Suponha que meu sistema permite que os usuários façam duas coisas: peneirar e espetar. Minhas métricas mostram que as pessoas peneiram com frequência 10 vezes maior do que espetam, e mostram também que a medida que o tempo passa, os usuários estão peneirando e espetando cada vez menos por dia, em média.
Agora suponha que eu preciso decidir o que fazer nos próximos seis meses, dentre as seguintes três opções:
- Melhorar a função de peneirar.
- Melhorar a função de espetar.
- Implementar uma nova função, sacudir.
- As pessoas preferem peneirar, então se melhorarmos essa função, vão peneirar muito mais e o ganho será muito maior;
- A função de espetar está claramente ruim quando comparada com a de peneirar, então se a melhorarmos teremos um grande ganho;
- Peneirar e espetar não tem mais a mesma atração, então precisamos de algo novo para atrair os usuários.
Uma métrica só deve existir quando se sabe como ela será usada para tomar decisões
Métricas não associadas a decisões são prejudiciais ao projeto.
Métricas não são grátis. Tem um custo para se implementar e para se manter. Antes de investir nelas, tenha certeza que o investimento terá retorno garantido.
sexta-feira, 9 de outubro de 2009
O usuário não sabe inovar
"Nosso plano é guiar o público ao invés de perguntar a eles que produtos eles querem. O público não sabe o que é possível, mas nós sabemos." --- Akio Morita, co-fundador da Sony
"Se eu tivesse perguntado aos meus clientes o que eles queriam, eles teriam dito que queriam um cavalo mais rápido." --- Henry Ford, fundador da Ford Motor Co.A conhecida frase do Ford e a não-tão-conhecida frase do Morita dizem a mesma coisa - se você quer inovar, não consulte seus usuários. Desde que comecei a trabalhar com sistemas que são feitos para milhões de usuários, já vi centenas de respostas para a pergunta "o que você gostaria que o sistema tivesse?" e nunca, NUNCA, vi uma resposta que fosse extremamente útil, original, criativa, e que já não estivesse na nossa lista de coisas para fazer.
Os usuários tem 3 tipos de idéias para te dar:
- Melhorias no sistema atual - em geral o usuário tem certas dificuldades em realizar tarefas com seu sistema, e sabe sugerir maneiras de reduzir as dificuldades. Em geral esse tipo de comentário é muito útil para você achar deficiências no sistema, mas via de regra as sugestões de solução que o usuário tem pra dar não são boas - leia "a mesa errada" pra entender isso.
- Integrações - "bem que podiam integrar esses dois sistemas" é super comum. Em geral o usuário não sabe bem o que teria a ganhar com a tal integração; o que eles querem é não ter de ir aos dois sites. O problema é que o site que você usa para controlar sua dieta não tem nada a ver com o site do bolão do campeonato.
- "Seria legal" - essa é a mais perigosa; o usuário vislumbra uma possibilidade concreta e revolucionária, que ninguém usaria. "Seria legal demais se o orkut mandasse um scrap de aniversário para os meus amigos automaticamente!" Seria sim. Assim você não ia ter de mandar parabéns pra ninguém, e no dia do seu aniversário você receberia 200 mensagens idênticas, uma de cada amigo seu, e passaria o dia que deveria ser feliz xingando porque tem de ficar apagando o lixo que apareceu na sua página de recados. Leia "voce está fazendo errado".
- Mostrar que o seu sistema não é tão fácil de usar quanto você imaginava. Já assisti a testes de usabilidade dos meus sistemas e é desesperador - de repende você percebe que aquele botãozinho que você julgava trivial de se entender não quer dizer nada pra ninguém.
- Mostrar que sua idéia não é tão boa assim. Use a estratégia do açougueiro, que é a seguinte: sempre que você for comprar carne no açougue, pergunte ao açougueiro se a carne está boa; se ele disser que não está, não compre. Da mesma forma, discuta sua idéia inovadora com o maior número de pessoas que você puder. Se a grande maioria te disser que não se interessaria, então não implemente. Se disserem que é interessante sim e que usariam, não acredite e pergunte mais. Não tenha medo, ninguém vai roubar sua idéia, ela não é tão boa assim.
Confie no seu taco, valide suas idéias com seus usuários, e bola pra frente.
quarta-feira, 7 de outubro de 2009
A programação orientada a aspectos está morrendo
A programação orientada a aspectos (POA) surgiu oficialmente com esse nome em um artigo de 1997, mas é fruto de diversos trabalhos anteriores. A idéia da POA é simples e vem do conceito de metalinguagem. Qualquer chamada de método pode ser interceptada e substituida por outra. Por exemplo, você pode criar um cache simplesmente interceptando todas as chamadas ao seu modelo (no sentido MVC) e, antes de executá-las, verificar se o dado solicitado está no cache. Isso permite que você insira e retire funcionalidades no seu sistema sem alterar sua arquitetura.
Eu comecei a me interessar pela área em 1995, quando comecei meu doutorado. Acompanhei bem de perto e fiz minha dissertação nessa área. De volta ao Brasil, escolhi a POA como tema de uma disciplina de tópicos em engenharia de software, que lecionei três vezes na PUC. Ainda tenho a apostila que escrevi online se alguém se interessar, mas aviso que está desatualizada.
Depois disso, perdi o contato com a área e outro dia resolvi ver como estava progredindo. O que encontrei não foi muito animador. A POA ainda existe como área de pesquisa em universidades mas na prática não acontece muita coisa. A única conferência na área, a International Conference on Aspect-Oriented Developement, continua acontecendo mas parece haver pouco interesse. Na edição desse ano foram 19 artigos acadêmicos e 4 vindos da indústria, mas os autores são praticamente os mesmos que eu via na década passada, ou seja, a área atraiu pouca gente nova.
O pior, no entanto, é a evidência dada pelo Google Trends:
O interesse na busca "aspect-oriented programming" tem caído constantemente desde 2004, e olhe que em 2004 eu já sentia o interesse bem menor do que em 1999-2001, quando o tema estava mais em voga. Infelizmente a indústria nunca abraçou a POA, imagino eu que pela necessidade de um compilador específico. Eu mesmo já vi nos projetos de que participei várias oportunidades de se empregar a POA com sucesso, mas trocar o compilador do projeto inteiro para resolver alguns pequenos problemas? Acho que não.
Pelo menos a área deixa um legado. Hoje há técnicas como dependency injection que são derivadas diretamente dos conceitos introduzidos pela POA, chegando a frameworks modernos como o Guice. Mesmo assim, é triste ver algo no qual investi tanto tempo sumindo por falta de interesse. Até que a idéia era boa.
A lição que fica é: não se apaixone por novas tecnologias, pois é bem provável que elas desapareçam daqui a dez anos.
segunda-feira, 5 de outubro de 2009
É melhor concentrar sua literatura em bons códigos
Eu ensino revisão de código em engenharia de software. Nesse momento os alunos precisam parar de escrever código e precisam ler e entender código. Isso só é feito bem no final do curso quando eles já estão perto de se formarem. Será que se eu ensinasse aos alunos primeiro a ler e entender código (leitura de texto seguida de compreensão de texto) para depois ensiná-los a escrever código (redação de texto) eles escreveriam códigos melhores ou mais fáceis de serem compreendidos?
Em linguagem natural, quanto mais livros você lê, melhor você passa a escrever, pois tem uma gama variada de estilos para seguir. Código também não é diferente. Quanto mais experiente você fica na leitura do código melhor você entende e pode escrever ou dar manutenção no código dos outros. Vejam o resumo deste artigo do David Garlan e outros:
Pouco se sabe sobre como desenvolvedores pensam sobre o design durante tarefas de mudanças em código, ou sobre como o conhecimento de design de desenvolvedores experientes os ajuda a trabalhar de modo mais eficaz. Realizamos um estudo de laboratório em que treze desenvolvedores trabalharam por três horas tentando entender o design de uma aplicação de código livre com 54 mil linhas de código. Os participantes tinham entre 0 e 10.5 anos de experiência e foram agrupados em três "experts" e dez "principiantes." Observamos que os participantes passaram seu tempo aprendendo, criticando, explicando, propondo e implementando fatos sobre o código, como "getFoldLevel tem efeitos." Os fatos serviam vários papéis, como sugerir mudanças, restringir mudanças e prever o tempo de investigações adicionais necessárias para se efetuar uma mudança. As diferenças entre experts e novatos incluiram o fato de os experts terem explicado a causa fundamental do problema de design e terem feito mudanças para consertá-lo, enquanto as mudanças dos novatos atacavam apenas os sintomas. Os experts não leram mais métodos mas também não visitaram alguns métodos não-relacionados em que os principantes perderam tempo tentando entender. Experts falavam sobre o código em termos de abstrações como "caching", enquanto os novatos descreviam o código de comando em comando. Os experts foram capazes de implementar uma mudança mais rapidamente que os principiantes. Também perceberam problemas que os principiantes não encontraram e foram capazes de explicar fatos que os principiantes não conseguiram. Todos esses achados tem implicações interessantes para futuras ferramentas.
Se você entende código melhor com o passar dos anos e com a experiência adquirida, eu acredito que você também automaticamente passa a escrever código melhor. Isso com certeza porque você já leu muito mais código e eu espero que seja código de qualidade que você está tendo acesso para leitura. Infelizmente, por mais que eu possa explicar isso para os alunos na universidade, são só os anos de leitura e compreensão de código que os tornarão melhores escritores de código.
A mesa errada
Se você é matematicamente orientado, pense assim: os requisitos delimitam o universo total de soluções aceitáveis para um problema, e a especificação determina um ponto específico nesse universo.
Ninguém, mas praticamente ninguém mesmo na minha experiência entende bem e põe em prática essa diferença. Todo mundo começa descrevendo a solução - escrevem "deve haver uma janela para fotos e outra para vídeos" ao invés de "fotos e vídeos não devem ser misturados visualmente". A primeira frase já assume muitos fatores a respeito da solução. A segunda deixa em aberto a forma como o efeito desejado (separar fotos e vídeos) vai ser implementado.
Se não temos bem claro em nossas mentes qual o problema que queremos resolver, as chances são enormes de implementarmos a solução errada. Passei anos absorvendo o conceito de que primeiro temos de entender o que o sistema deve fazer para depois decidir como fazê-lo. Mesmo assim, na hora de colocar em prática, fiz tudo errado. Foi assim:
Quando voltamos do Canadá, trouxemos nossas mesas de trabalho. Eram mesas simples, feitas de um suporte de metal com quatro pernas e uma tampa de madeira parafusada em cima do suporte. Acontece que na hora de despachar a carga, um dos suportes teve de ficar pra trás e veio um suporte e duas tampas.
Aí eu chamei um serralheiro pra me construir um novo suporte. Me achando muito espertinho, dei a ele o suporte que veio e disse que queria outro exatamente igual àquele. Assim ele fez e algum tempo depois, muito mais do que havia prometido, é claro, ele me entregou um suporte que era idêntico ao primeiro nos mínimos detalhes.
Imagine minha surpresa ao perceber que os furos dos parafusos do suporte novo não alinhavam com os furos da tampa de madeira. Irado, já ia ligar para o serralheiro quando resolvi tentar com a outra tampa de madeira... e os buracos se alinhavam perfeitamente. As duas tampas de madeira eram ligeiramente diferentes.
Entenderam meu erro? Eu especifiquei ao serralheiro a solução para o meu problema - quero um suporte igual ao outro. Ao invés disso, eu deveria ter especificado o problema - preciso de um suporte de metal que sirva com essa tampa de madeira, e que tenha 80cm de altura, pra alinhar com a outra mesa. Eu achei que sabia a solução, mas a solução estava errada dado o problema.
Incontáveis sistemas de software são inúteis porque seus desenvolvedores não entendem o problema que o software vai ser usado para resolver. E o seu?
sábado, 3 de outubro de 2009
É melhor ser esquecido
Difícil é escrever código que humanos entendem"
Neste momento, entender o que você quis dizer com aquele emaranhado de if blocks aninhados até o quinto nível transformará uma simples tarefa em um pesadelo. Por isso, recomendo, preze pela clareza do seu código, escreva para os outros entenderem, não para você.
Leia, releia, leia, releia! Tenha certeza que o que está escrito é o que você quis dizer. Mesmo nos momentos de emergência. Lembre-se, emergências sempre existirão, o projeto sempre estará atrasado, mas quem vai pagar o preço das linhas de código mal escritas será você... ou o próximo micoderealejo.
Por outro lado, bastarão poucas linhas mal escritas para que você seja odiado. E durante as horas perdidas para entender, consertar ou melhorar aquelas linhas que, por alguma emergência do momento, você decidiu escrever de qualquer maneira, desejarão que seus dedos sejam dilacerados, um a um, lentamente, para que nunca mais você escreva uma linha de código se quer!
sexta-feira, 2 de outubro de 2009
Síndrome do N-ésimo Sistema
A Guta escreveu sobre o Fenômeno da Segunda Vez, pelo qual um software escrito pela segunda vez é muito melhor do que a versão original, e eu descaradamente me ofereci pra escrever sobre um fenômeno com raízes similares, mas com efeito negativo.
Quando minha equipe estava começando a reescrever um sistema grande para torná-lo mais fácil de gerenciar e estender, conversávamos empolgadamente sobre nossas ideias para a nova arquitetura. Fomos interrompidos por um membro de outra equipe: "vocês não têm medo de cair na Síndrome do Segundo Sistema"?
Fred Brooks define a Síndrome do Segundo Sistema assim:
[Um arquiteto que desenha seu primeiro sistema] sabe que não sabe o que está fazendo, e então o faz com cuidado e de forma reprimida. Enquanto desenha seu primeiro trabalho, ocorre-lhe um enfeite após o outro. Ele vai guardando esses enfeites para usá-los "da próxima vez". Cedo ou tarde o primeiro sistema é terminado, e o arquiteto [...] está pronto para construir um segundo. Esse segundo sistema é o mais perigoso que um arquiteto desenha. [...] A tendência geral é exagerar no projeto, usando todos os enfeites e ideias que foram cuidadosamente descartados da primeira vez.
Embora não tenhamos caído na Síndrome do Segundo Sistema, acabamos caindo numa versão generalizada do problema que eu chamo de Síndrome do N-ésimo Sistema (N > 2). O desenvolvedor que sofreu com o (N-1)-ésimo projeto usa sua experiência recente para dizer: "Não vou cometer nenhum dos erros daquele outro projeto. Agora tudo vai ser diferente".
Nessa síndrome, os ex-membros de um projeto conhecem todos os seus defeitos e pontos de falha. Sabem como o contato de diferentes pessoas e novos requisitos com o código afeta sua qualidade. E decidem, "na-na-não; dessa vez nós vamos fazer tudo direitinho". No processo de tentar fazer tudo direitinho, acaba-se introduzindo uma hipertrofia de inovações, verificações e restrições que permitem que a complexidade do sistema "caiba" na cabeça de quem o projeta. Os ex-sofredores com aquele código ruim e processo esquisito do (N-1)-ésimo sistema tentam melhorar seu ambiente de trabalho e criam novas regras e restrições também no N-ésimo processo de desenvolvimento para melhorar sua vida.
Na prática, como diz meu gerente favorito, isso significa que os erros cometidos no N-ésimo projeto são totalmente novos. As restrições no processo cujo objetivo era melhorar a vida de todos acabam criando grilhões que tornam os desenvolvedores insatisfeitos e menos produtivos. A nova arquitetura faz com que a qualidade do código comece bem, mas logo chegam aqueles novos requisitos que vão transgredir essa arquitetura só um pouquinho, mas cujo custo-benefício é obviamente vantajoso para o usuário.
Com o tempo, o lado "custo" da balança de vários pequenos requisitos vai se somando e ficando mais pesado, e o N-ésimo sistema vira um monstro pior do que o anterior - ele não só contém tantas transgressões à arquitetura original quanto o projeto N-1, mas a nova arquitetura e o novo processo de desenvolvimento são tão restritivos e complexos que o código e o ambiente de trabalho ficam piores do que os do sistema anterior.
O Fenômeno da Segunda Vez
O artigo do Torsten sobre o Oráculo de Requisitos me fez lembrar do meu professor número um de requisitos: Dan Berry. Em várias situações de discussão sobre desenvolvimento de software eu me lembro dele se referindo ao fenômeno da segunda vez. Este fenômeno diz que a primeira vez que você escreve o software você está realmente é pensando e entendendo melhor sobre o problema. Na segunda vez é que você consegue acertar a solução do problema pois já o entendeu de forma mais abrangente e profunda e agora sabe de todas ou quase todas as suas implicações.
Fui então pesquisar se o Dan tinha alguma vez publicado sobre o fenômeno da segunda vez. Encontrei um artigo dele com a Jeannette Wing, uma pesquisadora famosa na área de métodos formais que eu também admiro muito. Bom, o artigo deles é de 1985 e foi publicado na Lecture Notes in Computer Science, volume 186, e pode ser encontrado neste link.
Os seguintes parágrafos do artigo descrevem bem a idéia do fenômeno da segunda vez:
“Nós observamos um número de projetos de software bem sucedidos. Alguns foram desenvolvidos através de um método que nós chamamos de especificação e outros foram desenvolvidos por um método que nós chamamos de prototipagem e outros ainda foram desenvolvidos por outros métodos que nós não discutimos neste artigo. ... Em um primeiro estágio do desenvolvimento, o produto do método utilizado, tanto a especificação quanto o protótipo, foram completamente verificados com o auxílio de uma ferramenta automática e possivelmente até mesmo executados. O segundo estágio do desenvolvimento de ambos foi a implementação, na qual o que foi aprendido no primeiro estágio foi aplicado para produzir uma versão de produção do software. O que foi comum aos dois métodos é o que chamamos de fenômeno da segunda vez. Isto é, a qualidade do software de produção que foi entregue representa a segunda passada sobre o problema que segue a primeira passada feita com uma descrição formal e verificada por uma máquina. No caso da especificação, ela foi feita formalmente e foi verificada com o auxilio de um programa de verificação. No caso do protótipo, o seu programa é formal e foi verificado por um compilador ou interpretador, pelo ambiente de execução e pelos usuários rodando o programa.
Nós nos perguntamos se o fator mais importante no sucesso destes projetos era o fato de o software entregue ser uma segunda iteração depois de uma primeira iteração verificada por uma máquina. Ou seja, nós sugerimos se este fenômeno da segunda vez é mais crítico para determinar o sucesso de um projeto do que qualquer outro fator que pode surgir dos métodos de especificação e prototipação em si. “
Então, na minha opinião o fenômeno da segunda vez do Dan Berry e da Jeannette Wing e o que disse o Fred Brooks, "Planeje jogar um sistema fora, você jogará de qualquer jeito" são conclusões bastante semelhantes.
quinta-feira, 1 de outubro de 2009
Persistir ou jogar tudo fora?
- Lei da mutação contínua: um sistema em uso deve sofrer modificações constantes ou degradar em sua eficácia;
- Lei da complexidade crescente: um programa de computador que é modificado se torna cada vez menos estruturado; as mudanças aumentam a entropia e complexidade do programa.