Por Luís Soares para o Pplware
É importante analisar os projetos de software que correm mal. Nem sempre são resultado dos prazos impossíveis ou de maus gestores. Geralmente é um somatório de factores que entra numa espiral causa-efeito. Tentarei agora identificar alguns erros comuns dos programadores (também aqui me incluo). Tais erros não são exclusivos do programador júnior. De facto, alguns são cometidos mais frequentemente pelo programador sénior.
Por outro lado, não se pretende aqui falar em más práticas de programação mas sim de soft skills e de gestão pessoal.
Os papéis do Programador
A palavra ‘programador’, neste artigo, é usada para representar ‘developer’ (já que ‘desenvolvedor’ não é muito usado em Portugal). Vejo um developer não só como um técnico, mas como um engenheiro de software:
- Opera em várias stacks do software: interface, lógica de negócio, bases de dados, …
- Pode ter diferentes responsabilidades: sys. admin., tester, designer de interfaces, etc.
- Passa pelas várias fases do projeto: pré-estudo, desenho da solução, implementação, etc.
É também um gestor, pois:
- Nem sempre um chefe está presente.
- O chefe não deve realizar microgestão (gestão de subtarefas).
- Há metodologias em que nem existe o chefe (ex: Scrum) e todos o são.
Um programador também é um cientista: coloca, testa e descarta hipóteses, optando por algo com base em factos. Demonstra ceticismo perante afirmações infundadas.
Por fim, é um consultor: usa a sua experiência para aconselhar, reconhecendo padrões e propondo soluções. É um ser social que deve respeitar o cliente e o ambiente do projeto em causa. Sem essa componente, é o chamado code monkey.
Comecei por falar em culpa; na verdade, a culpa não é de quem erra, mas sim de quem não tem humildade para reconhecer os erros e nem os tenta corrigir. Um bom programador reconhece os seus defeitos e limitações em vez de os desconhecer ou ignorar; deve ser humilde para realizar esta introspeção, não achando que sabe tudo e assim melhorando no dia-a-dia.
Estimativas idealistas
«Faço isso em 2h»
Por vezes, os programadores falham nas estimativas por uma questão de orgulho: prometem que são capazes de entregar algo em pouco tempo quando, na realidade, isso aconteceria apenas em condições perfeitas e ideais (o que é muito raro; há sempre problemas). Estimar algo é difícil por natureza (o Scrum, com as suas estimativas relativas em vez de absolutas, pode aligeirar isso) e reconhecê-lo é o primeiro passo para minorar o problema.
É certo que os programadores são muitas vezes pressionados a prometer prazos impossíveis. No entanto, quando no fim esses prazos não são cumpridos, foi o gestor que ficou a perder (com o projeto prejudicado e a equipa cansada e desmotivada). Se o resultado final seria semelhante, mais valia ter sido realista. Será preferível viver na feliz ilusão ou no realismo sólido dos prazos? É preferível criar falsas expectativas? O programador deve tentar, progressivamente, incutir estas ideias nos seus superiores.
Alienação do negócio
«Não tenho nada a ver com isso»
Alguns programadores ficam de tal forma empedernidos no código que perdem a ligação ao negócio. Seja porque estão a fazer algo muito complexo, porque estão a gostar muito ou porque simplesmente não querem saber. Muitas vezes não lhes é explicado o negócio em que está inserido, mas outras, ele também não procura saber mais. Contudo, o programador, acima de tudo, é um engenheiro de software, pelo que é geralmente contratado para resolver problemas do negócio, e não para simplesmente programar.
Fazem-me alguma confusão ofertas de emprego do estilo “especialista em JavaScript”, quando o que uma empresa devia procurar era um especialista em frontend muito bom em JavaScript (talvez haja exceções a esta afirmação). A empresa poderia ter mais a ganhar com alguém com uma noção mais abrangente de como as peças se encaixam.
Delegação da culpa
«A culpa é do utilizador»
Programar, por mais gratificante que seja (e por mim falo), é apenas uma ferramenta ao serviço do projeto/produto e, por conseguinte, da empresa/cliente. Em última análise, programa-se para o utilizador (nem sempre assim é, mas regra geral, e especialmente em sistemas de informação), pelo que as nossas ações devem envisioná-lo direta ou indiretamente.
Culpar o utilizador (“ele que atualize o browser”, “não são muito inteligentes”, “ele é que não viu o botão”, …), além de nada fazer para resolver o problema, desculpabiliza os verdadeiros culpados que não conhecem o seu público-alvo. Por outro lado, descaracteriza a profissão, pois os utilizadores são a razão da existência dos sistemas de informação e dos consultores informáticos.
“Não fui eu que fiz isso”
Por outro lado, há casos em que o programador, por não ter sido ele a fazer e/ou não ser da sua área, se descarta e/ou oferece resistência a mexer em algo. Admite ignorância sobre um assunto para fugir à realização de uma tarefa. Passado algum tempo, adquire a chamada “visão em túnel” do negócio.
O que o programador deve perceber é que,“no fim do dia”, todos são de todas as áreas e todos são da empresa. Todos devem lutar pelo bem do projeto, pelo que não devem haver “lugares marcados”. O bem de um é o bem de todos e há que evitar que as agendas pessoais interfiram no sucesso dos projetos. Descartar de imediato a culpa ou responsabilidade não acrescenta valor. Geralmente, não se procura um culpado mas sim uma solução.
Medo do refactoring
Por motivos de pressão superior e/ou medo de estragar alguma coisa, há muitos programadores que optam por “mexer o mínimo possível”. Quando é preciso uma alteração, acabam por (na gíria do software) “dar marteladas” ou fazer “copy/paste” de código, entre outras péssimas práticas. O código transforma-se então em “código-esparguete”, que já ninguém consegue manter. O programador deixa assim morrer o seu perfecionismo e o projeto perde a sua melhoria contínua.
Como em tudo na vida, deve haver um balanço. Não defendo que se deva estar sempre a mudar tudo, mas o bom código muda. Muda porque os requisitos mudam, as dependências (ex: S.O., browser) mudam, porque aparecem (ou se aprendem) novas técnicas, porque algo trará mais valor ao utilizador, etc.
Portanto é melhor aceitar a mudança que negá-la. É certo que há produtos com um término bem definido, mas mesmo esses entram em fase de manutenção e têm novas funcionalidades de tempo a tempo.
Para evitar criar o medo da mudança, deve-se reduzir o risco associado à mesma:
- O bom código fala por si: é simples, estruturado e elegante o suficiente para estar preparado ser modificado.
- Comentar o código todo é utópico; por isso, deve-se comentar pelo menos as operações destrutivas, as importantes e as diretamente ligadas ao negócio.
- Devem existir testes que permitam verificar que tudo continua bem após uma mudança (para tal, é bom conhecer o TDD).
- Deve-se considerar a preparação de ambientes de teste e de staging.
- Deve ser fácil voltar atrás caso algo negativo aconteça (inclui reverter código facilmente assim como realizar deploys rápidos).
- Todos os programadores devem tentar conhecer todo o código; para tal, o pair programming e o code reviewing podem ajudar.
- Todos os programadores devem conhecer muito bem a arquitetura do projeto (e do sistema onde ele se insere) antes de alterar código; isso pode mudar tudo. Para isso, bastam simples diagramas e páginas em wikis internas.
Recomendo também que conheça o Teste de Joel.
Deslumbramento pela tecnologia
«Vamos converter tudo para Swift»
É comum o programador sofrer de “entusiasmo pela tecnologia”. Como consequência, acaba por caprichar ou até forçar o uso de determinadas tecnologias, nem que isso implique mudar todo um projeto. Não tem mal ser um entusiasta. De facto, até pode ser importante. Não se deve é deixar de se fazer uma análise imparcial às várias tecnologias, antes de se optar por uma. Eis alguns falsos argumentos para a escolha de uma tecnologia:
- «Já usei isto em muitos projetos»
- «Ele já tem muita experiência; vamos usar»
- «Estou mesmo curioso em experimentar»
- «Sinto que é o ideal»
- «Li num blogue que é espetacular» ou «É o que o Google usa»
- «Toda a gente usa isto agora!» ou «É o que está a dar»
Não há soluções universais e a oferta tecnológica está em constante mudança, pelo que é provável que seja sempre necessário pôr as coisas em causa.
O bom programador, mesmo que entusiasta, sabe refrear os ânimos quando conhece uma tecnologia ou sai o “último grito” de uma framework. Sabe que o negócio está à frente da tecnologia e que quanto menos tecnologias um projeto tem, melhor. O mau programador enche um projeto com dezenas de bibliotecas e frameworks que o tornam “sensível” (em que não se pode mexer), com inúmeras dependências e potenciais pontos de falha.
Desvalorização de “desenhos”
«Desenhar no PC é muito melhor»
É fácil cair no erro de se achar que já se resolveu tudo na cabeça. Isto aplica-se tanto a um algoritmo, a uma interface, ou até a uma arquitetura de software.
Quem não se lembra do liceu, em que um simples desenho ajudava a resolver e acompanhava a solução de problemas de matemática, física e química? Poder visualizar algo complexo em imagens é determinante, na solução e no caminho para lá chegar.
Com “desenhos” refiro-me a simples protótipos de baixo nível (wireframes), fluxogramas e outros esquemas e esboços. Não me refiro a usar ferramentas do tipo Visio ou Photoshop, mas sim papel (ou quadro) e caneta/lápis. Passo aos exemplos, para melhor expressar esta ideia:
- Fluxogramas para expressar algoritmos, interações e outros fluxos.
- Protótipo de baixo nível não funcional (mockups ou throwaway prototypes) para representar interfaces gráficas (GUI).
- Diagramas de classes (e de outros tipos) para representar conceitos arquiteturais.
Este tipo de desenhos tem as seguintes vantagens:
Cativam a reflexão sobre o problema, colocando-o numa linguagem (tal como falar sobre um problema a alguém). Isto permite desde cedo abandonar ideias sem futuro e reforçar outras interessantes. Ter um modelo mental coeso da solução permite ser muito mais objetivo na hora de a pôr em prática.
Promovem a comunicação: é muito mais fácil apresentar uma ideia a alguém se ela for gráfica. Por outro lado, é mais fácil que 2 ou mais pessoas construam um modelo mental semelhante da solução, em vez de cada um ter o seu.
Como consequência, poupam-se custos denecessários. Um desenho que custou 20 minutos a fazer pode poupar muito mais tempo ao programador e à empresa, evitando muito refactoring desnecessário. Mesmo após esse refactoring, o código pode nem ficar com a qualidade que teria caso se tivesse uma ideia bem definida do problema desde cedo.
Desvalorização do pair programming
A técnica do pair programming é valiosa e devia ser mais aplicada. Implica que dois programadores estejam no mesmo computador. É desvalorizada exatamente por isso: porquê ter duas pessoas no mesmo local quando podiam estar ambas a programar sozinhas?
A questão é que um programador não é uma máquina; comete erros, distrai-se e não tem produtividade e motivação lineares. Ter alguém ao lado permite:
- Maior foco
- Menos erros
- Melhor conhecimento do código
- Maior partilha de conhecimento
Não é objetivo deste artigo explicar esta técnica pelo que recomendo que leia mais sobre o tema.
Zona de conforto
«Ele disse para fazer assim…»
Este talvez seja o tópico mais sensível, na medida em que pode afetar zonas de conforto e não é trivial colocar um superior em causa. Quando um programador recebe uma tarefa, não deve simplesmente executá-la. Deve fazer algumas perguntas básicas primeiro: “faz sentido?”, “será que é mesmo isto que o utilizador quer?”, “deve ser exatamente assim?”. Só depois de a tarefa passar neste teste inicial é que se deve avançar. Isto é ainda mais premente quando dizem não só o que fazer, mas como fazer. O programador deve, fazendo uso de argumentos lógicos, debater se essa é a melhor forma de resolver o problema.
Por outro lado, o bom programador sugere melhores formas de atuar e questiona as metodologias e tecnologias em uso.
O programador não é um computador
«Não te preocupes, eu trato disso»
Como lidamos com máquinas tão frequentemente, sucede o fenómeno de acharmos que também somos uma, especialmente em termos de memória. De certeza que já passou pela situação de dizer para si “não me posso esquecer disto”. É então que reserva um espaço de memória para o efeito. As tarefas e o stress da sua memorização vão acumulando e algumas vão sendo esquecidas.
Mesmo que haja um sistema de tracking (ex: JIRA), há tarefas muito pequenas que nem “merecem” lá entrar (microgestão). Por exemplo. pequenos detalhes que alguém sugere, coisas que nos lembramos “do nada” mas que não podemos implementar no momento ou subtarefas de uma tarefa.
Para isto, ter simples listagens (to do lists, checklists, etc.) pode ser muito produtivo. Um caderno, post its, ou um EcoBook sempre à mão é quase sempre suficiente. Contudo, se preferir uma versão eletrónica, pode usar o Google Keep ou o Trello (ou um utilitário semelhante). Ambos suportam listagens, sendo ágeis e colaborativos.
Há também um efeito psicológico benéfico: a vontade de completar uma listagem está sempre patente (provavelmente está ligada ao colecionismo). Sentimos motivação ao ver essa lista (principalmente se estiver sempre presente) encurtar à medida que a vamos completando.
Em suma, o que não fazer:
- Promover a cultura do medo da melhoria.
- Ser muito otimista nas estimativas: é melhor para o programador e gestor que o primeiro seja realista.
- Trabalhar em função da tecnologia: os sistemas de informação devem atender e servir as necessidades de negócio e utilizadores e não o contrário: as pessoas e as empresas não deveriam ter que se adaptar aos sistemas de informação.
- Não ter iniciativa para conhecer o negócio, o cliente e os utilizadores (e, pior ainda, culpar estes últimos).
- Desvalorizar técnicas aparentemente rudimentares (de papel e caneta) como a prototipagem em papel, o desenho de fluxos ou simples “to do lists”.
- Aceitar tarefas, tecnologias e metodologias sem nunca as questionar.
_____
Outros artigos do Luís Soares: