Página 8 de 10

Reflexões sobre o uso de frameworks

Construção Errada

Em meu último artigo, Porque eu odeio frameworks, traduzi uma parábola fictícia que critica a crescente complexidade dos frameworks. Se você não tem muita experiência com Design Patterns (Padrões de Projeto) e com diversificados frameworks, provavelmente não tenha entendido ou mesmo achado o texto pouco interessante.

Agora, sendo mais direto, irei analisar nos tópicos a seguir alguns dos problemas e dificuldades que devemos nos precaver quando usamos frameworks e bibliotecas. Escolhas erradas impactam todas as fases do desenvolvimento de um sistema!

Complexidade excessiva

Quando aprendemos sobre Design Patterns e princípios como coesão e desacoplamento, temos a tendência de considerar tudo isso como soluções mágicas para os problemas de complexidade do software. Alguns começam a aplicá-los indiscriminadamente de forma que, mesmo operações que antes eram simples, exigem agora diversas classes para implementação e conhecimentos de vários conceitos para o entendimento.

Quando ainda estamos nessa fase de “descoberta”, onde acreditamos cegamente nas “vantagens”, sem compreender as consequências de nossas decisões ou mesmo a correta aplicação dos padrões, podemos acabar com dezenas de frameworks pendurados em nossos sistemas e inúmeras classes adicionais mesmo para tarefas simples. Já ouviu a expressão “matar uma mosca com um canhão?”

Soluções “genéricas”

Bons frameworks e bibliotecas possuem aplicações bem definidas. Nenhum framework é tão bom e completo a ponto de ser usado em todo e qualquer projeto. Nem mesmo uma determinada arquitetura como o MVC, por exemplo, mas infelizmente não é sempre assim que aprendemos na teoria.

Por outro lado, nós, desenvolvedores, somos culpados muitas vezes de usar um framework ou biblioteca indiscriminadamente, simplesmente porque já temos algum conhecimento.

Comprometimento da Arquitetura

Muitos frameworks são intrusivos no que diz respeito à arquitetura do software. Isso quer dizer que eles nos obrigam a tomar certas decisões arquiteturais simplesmente para que eles funcionem.

Infelizmente, a realidade hoje é que a grande maioria dos sistemas existentes possuem suas regras de negócios codificadas conjuntamente com classes específicas de terceiros. Não sabemos, e talvez nem pensemos sobre isso, o quanto somos orientados a tecnologias. Para falar a verdade, eu reconheço que também sou culpado disso. Quando codificamos, na maior parte das vezes, estamos mais preocupados com questões técnicas do que em realmente atender aos requisitos. Ou pior, quantas vezes não queremos simplesmente concluir o trabalho e não nos preocupamos com a qualidade interna do código? Infelizmente, a “preguiça” do programador em codificar corretamente é um dos grandes fatores que fazem crescer o número de defeitos e o número de horas extra.

Conclusão

Infelizmente, é preciso queimar muitos neurônios para criar frameworks e bibliotecas que, sendo flexíveis, não sejam demasiadamente complexos e intrusivos nos sistemas. E o mesmo se aplica ao uso deles.  Bons programadores devem saber não apenas como configurar, instanciar e executar objetos de frameworks e bibliotecas, mas principalmente sua precisa escolha e aplicação.

Por fim, para divertimento dos nerds de plantão, selecionei um exemplo de um Hello World em Java que abusa um pouco da complexidade. Ele serve para ilustrar como é possível complicar algo tão trivial.

public interface MessageStrategy {
    public void sendMessage();
}

public abstract class AbstractStrategyFactory {
    public abstract MessageStrategy createStrategy(MessageBody mb);
}

public class MessageBody {
    Object payload;
    public Object getPayload() { return payload; }
    public void configure(Object obj) { payload = obj; }
    public void send(MessageStrategy ms) {
        ms.sendMessage();
    }
}

public class DefaultFactory extends AbstractStrategyFactory {
    private DefaultFactory() {}
    static DefaultFactory instance;
    public static AbstractStrategyFactory getInstance() {
        if (null==instance) instance = new DefaultFactory();
        return instance;
    }
    public MessageStrategy createStrategy(final MessageBody mb) {
        return new MessageStrategy() {
            MessageBody body = mb;
            public void sendMessage() {
                Object obj = body.getPayload();
                System.out.println(obj.toString());
            }
        };
    }
}

public class HelloWorld {
      public static void main(String[] args) {
            MessageBody mb = new MessageBody();
            mb.configure("Hello World!");
            AbstractStrategyFactory asf = DefaultFactory.getInstance();
            MessageStrategy strategy = asf.createStrategy(mb);
            mb.send(strategy);
      }
}

* Extraído de http://seenonslash.com/node/465

Porque eu odeio frameworks…

Decidi construir uma prateleira de temperos. Como já fiz pequenos projetos com madeira anteriormente, acredito ter uma boa ideia do que eu vou precisar: um pouco de madeira e algumas ferramentas básicas, como fita métrica, serra, nivelador e um martelo.

Vou até uma loja de ferramentas para comprar o que preciso e pergunto ao atendente onde encontro um martelo.

– Um martelo? – ele pergunta. Na verdade ninguém mais compra martelos. Eles estão meio fora de mora.

Surpreso com essa mudança, pergunto a ele o por quê.

– Bem, o problema com martelos é que existem muitos tipos diferentes: do tipo marreta, o tradicional (com as duas pontas para tirar pregos), o de cabeça arredondada, o de borracha e assim por diante. E se você comprar um tipo de martelo e depois perceber que precisava de outro tipo? Você teria de comprar outro martelo. Sendo assim, a maioria das pessoas queria apenas um único martelo que pudesse executar todos os tipos de marteladas que você possa conhecer em sua vida.

– Suponho que isso seja bom. Pode me mostrar onde encontro o “martelo universal”?

– Não, nós não vendemos ele mais. Estão obsoletos.

– Sério? Mas você acabou de me dizer que o “martelo universal” é a onda do futuro.

– Descobrimos que, se você faz um tipo de martelo capaz de fazer todos os tipos de tarefas de todos os tipos de martelos, ele na verdade não é tão bom em nenhuma tarefa. Pregar um prego com uma marreta não é muito eficiente. E, se você quer matar sua ex-namorada, não há melhor substituto do que o martelo com cabeça arredondada.

– Isso é verdade. Mas então, se ninguém compra mais “martelos universais” e você não vende mais os martelos tradicionais, que tipo de martelos você vende?

– Na verdade, nós não vendemos nenhum martelo.

– Então…

– Conforme nossas pesquisas, o que as pessoas realmente precisavam não era um “martelo universal”, no fim das contas. Sempre foi melhor ter o tipo de martelo adequado para o trabalho. Então nós começamos a vender fábricas de martelos capazes de produzir qualquer tipo de martelo que você possa se interessar em usar. Tudo o que você precisa fazer é preencher a fábrica de martelos com trabalhadores, ativar a maquinaria, comprar a matéria prima dos martelos, pagar as contas e, voilà, você terá exatamente o tipo de martelo que precisa na hora!

– Mas eu não queria comprar uma fábrica inteira de martelos.

– Isso é bom, porque nós também não as vendemos mais.

– Mas você acabou de dizer que…

– Nós descobrimos que a maioria das pessoas realmente não precisa de uma fábrica inteira de martelos. algumas pessoas, por exemplo, nunca precisarão de um martelo com cabeça arredondada (talvez porque não tenham uma ex-namorada ou já usaram um furador de gelo para matá-las). Então, não há razão para alguém comprar uma fábrica de martelos que pode produzir todo tipo de martelo existente debaixo do sol.

– Sim, isso faz muito sentido.

– Então, ao invés disso, nós começamos a vender esquemas para fábricas de martelos, permitindo a nossos clientes construir suas próprias fábricas de martelos, personalizadas para fabricar apenas os tipos de martelos que eles iriam precisar.

– Deixe-me adivinhar: vocês não vendem isso mais…

– Não! Certamente não! Descobrimos que as pessoas não queriam construir uma fábrica inteira apenas para fabricar um ou dois martelos. Deixe a construção da fábrica para os especialistas em construção de fábricas, foi o que eu sempre disse!

– E eu tenho que concordar com você.

– Isso. Então nós paramos de vender os esquemas e começamos a vender fábricas de construção de fábricas de martelos. Cada fábrica de fábricas de martelos é construída para você pelos principais especialistas no ramo de fábrica de fábricas de martelos, então você não precisa se preocupar com nenhum detalhe em construir uma fábrica. E ainda assim você tem todos os benefícios de ter sua própria fábrica personalizada, produzindo seus martelos personalizadas rapidamente, de acordo suas próprias especificações de martelo.

– Bem, na verdade, isso não parece…

– Eu sei o que você vai dizer! Nós não vendemos mais isso também. Por alguma razão, poucas pessoas estavam comprando as fábricas de fábricas de martelos, então nós criamos outra solução para resolver o problema.

– Hu-ho!

– Nós analisamos a situação com calma e olhamos para toda a infraestrutura de ferramentas. Então entendemos que as pessoas estavam frustradas em ter que gerenciar e operar uma fábrica de fábricas de martelos, tanto quanto a fábrica de martelos que era produzida. Esse tipo de trabalho adicional pode ficar muito confuso quando você lida com um cenário provável de também ter que operar uma fábrica de fábricas de fitas métricas, uma fábrica de fábricas de serras e uma fábrica de fábrica de niveladores, sem mencionar o conglomerado de fabricação de chapas de madeira. Quando nós olhamos a situação com a devida atenção, vimos que era tudo muito complexo para alguém que quer apenas construir uma prateleira de temperos.

– Nem me diga!

– Então, nesta semana, nós estamos introduzindo no mercado a fábrica de fábricas de fábricas de ferramentas de propósito geral, de forma que todas suas diferentes fábricas de fábricas de ferramentas podem ser produzidas por uma única fábrica unificada. A fábrica de fábricas de fábricas não irá apenas produzir as fábricas de fábricas de ferramentas que você precisa, mas cada uma das fábricas de fábricas irão produzir fábricas únicas baseadas nas suas especificações personalizadas de ferramentas. O conjunto final de ferramentas que irão emergir desse processo serão as ferramentas ideias para o seu projeto em particular. Você terá exatamente o martelo e a fita métrica que precisa para sua tarefa, tudo com o simples pressionar de um botão (embora você tenha ainda que implantar alguns “arquivos de configuração” para fazer tudo isso funcionar de acordo com suas expectativas).

– Então, você não tem nenhum martelo? Nenhum mesmo?

– Não. Se você quer mesmo uma prateleira de temperos de alto padrão e de acordo com as especificações da indústria, você precisa urgentemente de algo mais avançado do que um simples martelo de uma lojinha de ferramentas.

– Isso é o que todos estão fazendo agora? Todo mundo está usando uma fábrica de fábricas de fábricas de ferramentas de propósito geral, sempre que precisam de um martelo?

– Exato!

– Tudo bem, Acho que vou querer uma dessas também. Se é assim que todos estão fazendo, acho melhor aprender dessa forma.

– Vai ser bom pra você.

– Vem com manual, né?


Trecho extraído de http://discuss.joelonsoftware.com/?joel.3.219431.12

Seja um especialista

Neste artigo, simplesmente farei a tradução de um pequeno trecho do livro The Passionate Programmer, de Chad Fowler, que me chamou muito a atenção.


homem-com-lupaInfelizmente, a indústria de software tem produzido em massa esses especialistas superficiais, que usam o termo especialista como uma desculpa para saber apenas uma coisa. Na indústria médica, um especialista é alguém com um entendimento profundo de alguma área específica. Médicos encaminham seus pacientes a especialistas porque, em circunstâncias específicas, o especialista pode cuidar melhor deles do que um clínico geral.

Então, o que deve ser um especialista na área de desenvolvimento de software? Eu vou lhe dizer o que estava procurando em cada esquina e beco naquela viagem de recrutamento. Eu estava buscando pessoas que entendessem profundamente o ambiente de programação e produção Java. Queria gente que pudesse dizer “já passei por isso, resolvi de tal jeito” em 80 por cento das situações que poderíamos encontrar, cuja profundidade de conhecimento pudesse fazer os 20 por cento restantes suportáveis. Eu queria alguém que, enquanto lidasse com abstrações de alto nível, entendesse os detalhes de baixo nível da implementação daquelas abstrações. Eu queria alguém que pudesse resolver qualquer problema em produção que pudéssemos encontrar ou pelo menos soubesse para quem pedir ajuda.

Esse é o tipo de especialista que sobreviverá às mudanças na indústria da computação. Se você é um especialista em .NET, isso não é uma desculpa para não saber nada além de .NET. Isso significa que se algo tem a ver com .NET, você é a autoridade. O Servidor IIS travou e precisa ser reiniciado? “Sem problemas.” Integração de código fonte com Visual Studio .NET? “Vou mostrar como se faz.” Clientes ameaçando cancelar o projeto por questões obscuras de desempenho? “Me dá 30 minutos.”

Se não é isso que ser um especialista  significa para você, então espero que você não diga que é um.


Texto original:

Unfortunately, the software industry has churned out a whole lot of these shallow specialists, who use the term specialist as an excuse for knowing only one thing. In the medical industry, a specialist is someone with a deep understanding of some specific area of the field. Doctors refer their patients to specialists, because in certain specific circumstances, the specialist can give them better care than a general practitioner.

So, what should a specialist be in the software field? I can tell you what I was searching for in every nook and cranny on that recruiting trip. I was searching for people who deeply understood the Java programming and deployment environment. I wanted folks who could say “been there, done that” in 80 percent of the situations we might encounter and whose depth of knowledge could make the remaining 20 percent more livable. I wanted someone who, when dealing with high-level abstractions, would understand the low-level details of what went into the implementation of those abstractions. I wanted someone who could solve any deployment issue we might encounter or would at least know who to call for help if they couldn’t.

This is the kind of specialist who will survive in the changing computer industry. If you’re a .NET specialist, it’s not just an excuse for not knowing anything except .NET. It means that if it has to do with .NET, you are the authority. IIS servers hanging and needing to be rebooted? “No problem.” Source control integration with Visual Studio .NET? “I’ll show you how.” Customers threatening to pull the plug because of obscure performance issues? “Give me thirty minutes.”

If this isn’t what specialist means to you, then I hope you don’t claim to be one.

Dependência Organizacional

Annex - Chaplin, Charlie (Modern Times)_01

Charles Chaplin, no filme Tempos Modernos, pinta um retrato cômico de um operário na era industrial. Seu trabalho é apertar um parafuso e provavelmente ele não tem ideia do que está ajudando a construir. Extrapolando toda a crítica social dessa obra, será que, como profissionais, podemos extrair uma lição prática para hoje? Acredito que sim!

Antes de falar sobre que tipo doença é essa tal de dependência organizacional ;-), deixarei o caro leitor com uma indagação: você é dependente da estrutura da sua empresa? Se trocar de emprego hoje, ainda que na mesma área, teria que praticamente recomeçar sua carreira?

O que é a Dependência Organizacional

Na área de TI, tenho notado que, em empresas de médio e grande porte, as quais contam com um ambiente complexo, o desenvolvedor tende a aprender uma forma muito específica de engenharia de sistemas. Ele simplesmente “pega o jeito” da empresa, isto é, aprende a usar ferramentas e processos específicos para criar um tipo específico de aplicação.

Também já vi currículos onde profissionais de desenvolvimento afirmam ter experiência com ferramentas ou frameworks criados dentro da empresa onde trabalham e usados exclusivamente por elas. Sinceramente, tal experiência é, no mínimo, irrelevante, exceto se conceitos de Engenharia de Software forem explícitos, o que dificilmente ocorre com ferramentas internas. Imagine alguém que passou anos criando software com o gerador de tabelas e formulários do Microsoft Access. Dificilmente isso agregará boas práticas sobre modelagem de banco de dados, programação e elaboração de interfaces que sirvam para outras plataformas.

Além disso, a área de TI está cada vez mais complexa. Novos processos, ferramentas, tecnologias e frameworks surgem com uma frequência alta. Se não nos esforçarmos constantemente em aprender, permanecendo numa zona de conforto, acabamos nos tornarndo “especialistas” limitados.

Enfim, a verdade é que muitos profissionais são completamente dependentes da estrutura de uma empresa. Eles ficam perdidos fora do ambiente de trabalho com o qual estão acostumados e dificilmente conseguem manter um diálogo com colegas de outras empresas. Infelizmente, a carreira deles se resume a fazer o que lhes é ordenado.

O ambiente de trabalho

O local de trabalho influencia, até certo ponto, no desenvolvimento do profissional. O trade-off que muitos encontram é algo dessa natureza:

  • Trabalhar em uma empresa de grande porte, com estabilidade e boa estrutura, mas ser apenas um operário com uma tarefa específica que nunca enxerga o todo.
  • Ou entrar numa empresa menor, talvez com um salário menor, um trabalho desafiador, mas que recompensará e impulsionará sua carreira.

Não é uma escolha fácil, quando há chance de escolha. Porém, independente da cultura da empresa na qual trabalhamos, devemos buscar nos desenvolver e amadurecer como profissionais.

Uma dica para desenvolvedores de software

Desenvolver-se como profissional de TI não se trata apenas de código e tecnologia, mas, falando especificamente aos desenvolvedores, gostaria que todos fossem full stack developers. O que é um full stack developer? Trata-se de alguém que domina diversos aspectos da arquitetura de sistemas.

Faça uma auto-avaliação sobre seu conhecimento. Todos querem ser o novo Zuckerberg, mas, sinceramente, ideias não valem nada. Você tem a capacidade de concretizá-las? Criar um sistema do zero, desde o banco de dados até a interface com o usuário?

Listarei abaixo alguns dos conhecimentos[1] que um desenvolvedor pode (e deve) ter:

Servidor, Rede e Hospedagem

  • Entender o funcionamento, onde e porque podem ocorrer falhas.
  • Usar apropriadamente sistemas de armazenamento, nuvem e recursos de rede.
  • Entender de redundância e disponibilidade de dados.
  • Compreender como a aplicação escala de acordo com o hardware.
  • Entender problemas de concorrência e multi-threading.
  • Prover mensagens de log coerentes, pois provavelmente outras pessoas irão analisá-las antes de você.

Modelagem de dados

  • Criar modelos consistentes pois, se o modelo de dados é ruim, as regras de negócio ou outras camadas mais altas da arquitetura começarão a ter gambiarras para contornar os casos que o modelo não consegue tratar.
  • Full stack developers devem saber como criar modelos de dados razoavelmente normalizados, usando adequadamente chaves estrangeiras, índices, visões e outros recursos disponíveis.

Regras de negócios

  • Ter conhecimentos sólidos sobre orientação a objetos é essencial para a implementação do “coração do sistema”.
  • Conhecer bibliotecas  e frameworks específicos é importante para não se reinventar a roda.

Controle da aplicação e integrações

  • Usar adequadamente frameworks é fundamental para a interação da aplicação com o “mundo externo”.
  • Full stack developers devem ter a habilidade de criar interfaces de integração simples, claras e consistentes.

Interface com o usuário

  • Entender como criar interfaces legíveis, além de reconhecer a importância da ajuda de designers. O visual é um fator chave de um sistema.
  • Dominar HTML e CSS. JavaScript também é de extrema importância. Quem não está acompanhando, pelo menos em parte, os imensos avanços desta linguagens em suas variadas aplicações está perdendo um grande recurso.

Experiência com o usuário

  • Full stack developers devem entender que os usuários querem um sistema que funcione.
  • Um bom sistema não deve provocar tendinite ou cansar a vista. Bons desenvolvedores devem ser capazes de analisar a aplicação como um todo e reduzir um processo que exige uma dúzia de cliques e três passos para apenas um clique.
  • Mensagens de erro devem ser claras. Se algo está errado, não saia colocando a culpa no usuário. Alguns programadores, mesmo sem querer, escrevem mensagens de erro que fazem as pessoas se sentirem estúpidas.

Entendimento das necessidades do cliente e do negócio

  • Este item já vai um pouco além do papel de desenvolvedor, mas é importante ter um entendimento ainda que básico do que acontece na área do cliente onde o software é usado.
  • Hoje, conhecer as regras de negócio é muito mais valioso do que saber 10 linguagens de programação.

E quem não é desenvolvedor?

Me perdoem os demais profissionais, mas o foco do artigo está nos desenvolvedores de software. Mesmo assim, estou certo de que os princípios apresentados são validos para as demais áreas.

Conheço muita gente que é razoável em desenvolvimento, mas simplesmente não está “no sangue”. Se você reconhece isso e aspira a gerente de projetos, analista de negócios ou qualquer outra área, esqueça o tópico anterior e busque um conhecimento estruturado em sua área. Não se assuste nem se iluda, galgar os degraus da carreira não é impossível, mas também não ocorre da noite para o dia.

Além disso, mesmo não sabendo programar uma linha de código, um bom profissional pode participar da próxima grande ideia bilionária se souber cumprir seu papel com excelência. Todos querem trabalhar com pessoas boas e com isso quero dizer pessoas que fazem as coisas acontecerem.

Dicas para vencer a Dependência Organizacional

Está parecendo um macaco apertando botões e preenchendo documentos que não entende? Converse com pessoas mais experientes e procure entender sobre o processo de desenvolvimento e sobre o negócio de sua empresa.

Você está acomodado em um mesmo projeto há muito tempo? Mude. Participe de projetos extra, com amigos ou open source. Em último caso, trocar de emprego pode ser necessário.

Faz tempo que não aprende nada novo? Estude. É importante estudar por conta. Ainda que você tenha alguém mais experiente para lhe dar direções gerais, não desgaste essa relação.

Diga-em com quem andas! Procure estar com pessoas que sabem mais do que você. Melhor, esteja perto de alguém que seja mais ou menos aquilo que você quer ser. O princípio de aprender por osmose pode não funcionar dormindo com a cabeça sobre um livro, mas garanto que funciona se acompanhar bons profissionais de perto.

Conclusões

Mesmo trabalhando num ambiente com poucas oportunidades de crescimento é possível agregar experiência e conhecimento que transcendam sua atual empresa se conseguir entender as razões da existência de ferramentas e processos, seu funcionamento e aplicar na prática esses conhecimentos de alguma forma. Entenda porque as coisas são como elas são!

Profissionais de outras áreas também podem aplicar os princípios apresentados aqui para quebrar a dependência organizacional. Gerentes de projeto devem refletir: eles são apenas “cobradores” e “preenchedores de planilhas” ou eles sabem realmente como fazer um projeto qualquer andar e obter a colaboração dos envolvidos? Arquitetos de sistemas sabem aplicar as boas práticas reconhecidas no mercado ou simplesmente perpetuam “o jeito que as coisas são feitas por aqui”? Administradores de bancos de dados conhecem mesmo sobre bancos de dados ou apenas seguem os padrões pré-estabelecidos pela organização?

Enfim, é normal haver, no início de qualquer carreira, um certo nível de dependência organizacional. Porém, devemos, dia após dia, nos esforçarmos para quebrar essa dependência e evoluirmos para sermos melhores do que o ambiente que nos cerca. Disciplina, estudo, auto-crítica, reflexão e auto-avaliação são fundamentais para esse processo de amadurecimento.


[1] A lista de conhecimentos e habilidades foi baseada no conteúdo deste artigo: http://www.laurencegellert.com/2012/08/what-is-a-full-stack-developer/

Construindo objetos de forma inteligente: Builder Pattern e Fluent Interfaces

building-with-legosA Orientação a Objetos é constantemente mal utilizada. Sem o devido treino, temos a tendência de raciocinar de forma estruturada.

Esse problema está tão enraizado que muitas vezes encontramos dificuldades nos pontos mais fundamentais da programação, tal como a construção de instâncias de objetos um tanto mais complexos que beans simples. Como consequência, nosso código fica difícil de manter e mais propenso a erros.

Portanto, todo desenvolvedor deve estudar Padrões de Projetos (Design Patterns), já que estes ajudam a resolver os problemas mais comumente enfrentados e nos dão o treino necessário para pensarmos sobre os problemas mais complexos. Além disso, existem outras técnicas, como as Interfaces Fluentes (Fluent Interfaces), que ajudam a criarmos código mais legível e, dessa forma, aumentam a produtividade e diminuem a propensão a erros.

Criando um objeto (the dummy way)

Suponha que precisamos criar um objeto com diversos atributos “opcionais”. Vamos usar uma pizza como exemplo (um dos exemplos clássicos para ilustrar padrões de projetos). Já vi muitos construtores de “pizza” por aí da seguinte forma:

public class Pizza {

	private int tamanho;
	private boolean queijo;
	private boolean tomate;
	private boolean bacon;

	Pizza(int tamanho) {
		this.tamanho = tamanho;
	}

	Pizza(int tamanho, boolean queijo) { 
		this(tamanho);
		this.queijo = queijo;
	}

	Pizza(int tamanho, boolean queijo, boolean tomate) {
		this(tamanho, queijo);
		this.tomate = tomate;
	}

	Pizza(int tamanho, boolean queijo, boolean tomate, boolean bacon) {
		this(tamanho, queijo, tomate);
		this.bacon = bacon;
	}

}

Diga a verdade, você já faz isso em algum momento? E pode ficar pior se acrescentarmos construtores com combinações e ordenação diferentes de parâmetros!

A sobrecarga é interessante quando temos algumas poucas variações de parâmetros e há poucas mudanças no conjunto de atributos. Porém, chega uma hora que nem sabemos mais o que está acontecendo. Quanto tempo você já perdeu inspecionando conteúdo de classes de terceiros para entender que valores deveria usar? Exemplo:

new Pizza(10, true, false, true, false, true, false, true, false...)

Que tipo de pizza é essa mesmo? 😯

Criando um objeto com Builder Pattern

Alerta: antes que alguém fique agitado porque este exemplo diverge do Builder Pattern originalmente publicado no GoF, leia o livro com atenção, pois os próprios autores propõem implementações alternativas dos padrões de projeto e afirmam categoricamente que estes devem ser adaptados de acordo com o contexto. É sério, está escrito lá, acredite ou não.

public class Pizza {

	private int tamanho;
	private boolean queijo;
	private boolean tomate;
	private boolean bacon;

	public static class Builder {

		// requerido
		private final int tamanho;

		// opcional
		private boolean queijo = false;
		private boolean tomate = false;
		private boolean bacon = false;

		public Builder(int tamanho) {
			this.tamanho = tamanho;
		}

		public Builder queijo() {
			queijo = true;
			return this;
		}

		public Builder tomate() {
			tomate = true;
			return this;
		}

		public Builder bacon() {
			bacon = true;
			return this;
		}

		public Pizza build() {
			return new Pizza(this);
		}

	}

	private Pizza(Builder builder) {
		tamanho = builder.tamanho;
		queijo = builder.queijo;
		tomate = builder.tomate;
		bacon = builder.bacon;
	}

}

Aplicando o padrão de projeto Builder, temos agora um objeto “construtor” para o objeto Pizza. A classe Pizza está um pouco mais complexa, mas confira como ficou elegante a forma de temperarmos:

Pizza pizza = new Pizza.Builder(10)
                       .queijo()
                       .tomate()
                       .bacon()
                       .build();

É muito mais fácil de codificar com essa API e entender o que está acontecendo.

O Builder Pattern é muito utilizado em boas bibliotecas que disponibilizam APIs intuitivas e fáceis de aprender, como construtores de XML e o Response do JAX-RS, por exemplo.

Composição de Objetos

Outro ponto onde temos dificuldades encontra-se na criação de objetos que são compostos por vários objetos. Como exemplo, vamos montar um pedido com alguns itens para um cliente:

public class Pedido {

	List<Item> itens;
	Cliente cliente;

	void adicionarItem(Item item) {
		itens.add(item);
	}

	void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}

	void fechar() {
		// ...
	}

}

O uso fica assim:

Pedido p = new Pedido();
p.setCliente(new Cliente("José"));
p.adicionarItem(new Item("Motocicleta", 1));
p.adicionarItem(new Item("Capacete", 2));
p.fechar();

Embora, neste exemplo, nosso código esteja relativamente simples, um objeto mais complexo dificultaria ao desenvolvedor entender o código. Mas, estou certo, podemos fazer muito melhor que isso!

Interface Fluente

A “mágica” das Interfaces Fluentes está em encadear métodos que retornam a instância do próprio objeto, evitando repetições desnecessárias no código “cliente”. Abaixo, o exemplo anterior foi ligeiramente modificado:

public class Pedido {

	List<Item> itens;
	Cliente cliente;

	Pedido com(int quantidade, String nome) {
		itens.add(new Item(nome, quantidade));
		return this;
	}

	Pedido para(String nome) {
		cliente = new Cliente(nome);
		return this;
	}

	void fechar() {
		// ...
	}

}

O uso fica assim:

new Pedido()
	.para("José")
	.com(1, "Motocicleta")
	.com(2, "Capacete")
	.fechar();

Muito mais limpo, com maior clareza e intuitivo, não é mesmo?

Classes Utilitárias

Temos ainda classes utilitárias com seus métodos estáticos, usadas nos mais diversos pontos da arquitetura de um sistema. Elas causam problemas quando mal planejadas, pois a tendência é acumularmos muitos métodos sobrecarregados com diferentes objetivos que infectam todo o código. Então, sem perceber, perdemos o controle, já que agora todo o sistema está acoplado a tais classes e alterações acabam impactando onde não esperamos.

Vejamos um exemplo de uma típica classe com rotinas de tratamento de datas:

public class Data {

	public static Date converteTextoParaData(String dataStr) {
		try {
			return new SimpleDateFormat("dd/MM/yyyy").parse(dataStr);
		} catch (ParseException e) {
			return null;
		}
	}

	public static String converteDataParaTexto(Date data) {
		return new SimpleDateFormat("dd/MM/yyyy").format(data);
	}

	public static Date avancarDiasCorridos(Date dataInicial, int dias) {
		Calendar c = Calendar.getInstance();
		c.setTime(dataInicial);
		c.add(Calendar.DATE, dias);
		return c.getTime();
	}

}

Eis como ficaria uma manipulação simples de data usando essa classe:

String inputDateStr = "28/02/2013";
Date inputDate = Data.converteTextoParaData(inputDateStr);
Date resultDate = Data.avancarDiasCorridos(inputDate, 30);
String resultDateStr = Data.converteDataParaTexto(resultDate);

Entediante. Vamos refatorar a classe com o conceito de Interface Fluente:

public class Data {

	private Date data;
	public Data(String dataStr) {
		try {
			data = new SimpleDateFormat("dd/MM/yyyy").parse(dataStr);
		} catch (ParseException e) {
			throw new IllegalArgumentException(e);
		}
	}

	public String toString() {
		return new SimpleDateFormat("dd/MM/yyyy").format(data);
	}

	public Data avancarDiasCorridos(int dias) {
		Calendar c = Calendar.getInstance();
		c.setTime(data);
		c.add(Calendar.DATE, dias);
		data = c.getTime();
		return this;
	}

}

E o uso fica assim:

String resultDateStr = new Data("28/02/2013").avancarDiasCorridos(30).toString();

Simples, não?

Nota: considere este como um exemplo de estudo. O uso do new para instanciar objetos é discutível, assim como o uso da classe java.util.Date.

Conclusões

Simplificar o código não é luxo. Trata-se de uma necessidade na luta contra a crescente complexidade dos sistemas de software.

A utilização de padrões de projetos como o Builder Pattern e técnicas como a Fluent Language nos auxiliam nessa empreitada, além de tornar a codificação mais simples e agradável.

Outro ponto positivo é que, ao utilizar objetos específicos para tratar problemas comuns, como no exemplo de Fluent Language, fica mais fácil manter o foco da responsabilidade das classes. Com métodos estáticos, a tendência é acrescentar novos métodos indiscriminadamente, enquanto com um objeto “inteligente” temos uma melhor percepção dos limites.

Leitura Obrigatória

Para ler mais sobre Fluent Interfaces, acesse http://martinfowler.com/bliki/FluentInterface.html.

Além disso, todo desenvolvedor deve ler o livro Design Patterns: Elements of Reusable Object-Oriented Software. Infelizmente, o livro é um tanto antigo e os exemplos podem ser um pouco “chatos” para desenvolvedores web, pois muitos aplicam-se à construção de GUI de aplicativos desktop.

Especificamente para quem está iniciando em Java, uma leitura mais leve é o Head First Design Patterns. É mais fácil de entender, porém incompleto. Não espere encontrar todos os padrões em detalhes. Muitos deles só constam no final como uma espécie de resumo.

Você é um desenvolvedor consciente?

Nossa jornada como profissionais de TI é uma grande curva de aprendizado. Entretanto, desenvolvedores recém-formados raramente compreendem isto. Alguns acham que já sabem tudo o que precisam porque conhecem uma ou duas linguagens de programação. Falo com conhecimento de causa, pois alguns anos atrás eu mesmo acreditava ser suficiente aprender tudo sobre uma linguagem para tornar-se um desenvolvedor experiente.

Mas não é apenas importante estudar constantemente, como todos já afirmam, mas também desenvolver o caráter e personalidade como um todo. Alguns de nós têm um certo prazer nerd em estudar apenas tecnologia. Gastamos nossos dias “escovando bits” no porão da empresa, deixando a barba crescer e ficando sem tomar banho.

É claro que estou exagerando, mas infelizmente isso não está tão longe da realidade. Tenho amigos que são excelentes técnicos, mas por falta de saber trabalhar em equipe e comunicar seu conhecimento, acabam isolados e não se desenvolvem como profissionais. Vencer a timidez, o comodismo, a procrastinação não é algo que ocorre da noite para o dia, mas é possível.

Pessoas são complexas. Entretanto, para fins de ilustração, classifiquemos três níveis de maturidade que caracterizam nossa jornada profissional:

1. O Lobo Solitário

lobo

Também conhecido como prima donna (ver Modern usage outside opera) por ter o ego inflado e se achar a estrela principal e indispensável do espetáculo. Em geral possui a síndrome chamada not invented here, isto é, prefere “reinventar a roda” ao reaproveitar o trabalho de alguém. Ele despreza o processo e segue apenas suas próprias regras.

A vantagem de um profissional desse nível é que ele não necessita de muito treinamento e trabalha bem em ambientes com poucos desenvolvedores que conduzem pequenos projetos sozinhos. Porém, ele causa muitos problemas quando uma equipe de verdade é necessária.

Não importa quantos anos de trabalho ou quanto conhecimento um desenvolvedor de software tenha. Enquanto orgulho, ego inflado e superioridade forem suas características, ele nunca será um profissional maduro.

O principal passo para vencer essa fase é reconhecer a importância do trabalho dos outros, de cooperar com os colegas e das regras estabelecidas na organização.

2. O Senhor dos Processos

agent-smithO desenvolvedor aprende sobre alguns processos, metodologias, normas ou padrões. Ele adota uma metodologia, um par de padrões e tenta seguir tudo à risca, acredita que toda regra estabelecida é importante e todos os que não acompanham nesse pensamento estão errados, não entendendo como essas pessoas podem ser tão tolas.

Em geral, o desenvolvedor adota uma abordagem única, a qual ele acredita ser a melhor para todos os cenários. Ele pode ter sucesso em alguns empreendimentos semelhantes, mas quando surgir um projeto diferente ele estará em maus lençóis.

Para vencer esse nível,  é preciso aumentar o leque de conhecimentos, estudar outras abordagens e compreender os diferentes contextos de cada projeto de software.

3. O Desenvolvedor Consciente

desenvolvedor-experienteO desenvolvedor consciente trabalha com base em princípios. Ele utiliza esses princípios para selecionar a melhor abordagem para cada situação, extraindo regras de metodologias existentes, mas aplicando-as com sabedoria quando elas devem ser aplicadas.

A maior dificuldade desse nível é a necessidade de grande investimento em educação para que o desenvolvedor entenda os princípios do desenvolvimento de software efetivo. Porém, uma vez que o desenvolvedor está treinado conforme esses princípios, ele estará equipado com todas as ferramentas necessárias para enfrentar uma grande variedade de projetos.

Nesse nível, o profissional não é apenas um programador, mas um Engenheiro de Software. Deste ponto em diante, sua própria experiência e sabedoria o guiarão no seu aperfeiçoamento contínuo.

* Este artigo foi parcialmente baseado em Raising Your Software Consciousness, de Steve McConnell.

9 pecados capitais do planejamento de projetos

MorteEm seu artigo Nine Deadly Sins of Project Planning, Steve McConnell nos apresenta uma forma bem interessante de reconhecermos um projeto mal planejado. O autor baseou-se em sua experiência para identificar os “pecados capitais” que frequentemente levam os projetos ao fracasso. Francamente, suspeito que ele andou visitando algumas empresas que eu conheço!

O que se segue abaixo é uma tradução um tanto informal do artigo, isto é, não muito ao pé da letra. Eis os nove pecados capitais do planejamento de projetos:

#1 → Não planejar nada

Um dos erros mais comuns. Não é necessário ser um especialista para planejar. Pessoas pouco experientes já o fizeram com sucesso simplesmente porque tiveram o cuidado de atentar para os requisitos do projeto.

Se tiver de escolher entre um especialista em planejamento que não pensa cuidadosamente sobre o plano e um iniciante na carreira, mas que analisa criteriosamente as necessidades do projeto, é melhor ficar com o último.

#2 → Não planejar todas as atividades necessárias

O pecado número 1 é não planejar, o número 2 é não planejar o suficiente.

Alguns planos de projeto simplesmente assumem que ninguém ficará doente, participará de treinamentos, sairá de férias ou deixará a empresa. Tais planos preparam o projeto para um desastre. Há inúmeras variações neste linha. Por exemplo, não incluir atividades auxiliares tais como criar instalação do software, conversão de dados de versões anteriores e outros tipos de tarefas por vezes irritantes que levam mais tempo do que gostamos de admitir.

Em alguns projetos que estão com o cronograma atrasado, tenta-se recuperar o prazo diminuindo o tempo que foi originalmente planejado para os testes. A justificativa é que provavelmente não haverá tantos erros como a princípio se pensava. Fica como exercício para o leitor imaginar por que então o tempo de testes já não foi menor desde o início.  😉

#3 → Não planejar considerando os riscos

Henry Petroski argumenta que os maiores desastres na construção de pontes ocorrem após períodos de sucesso que dão margem à autoconfiança. Os projetistas tornam-se complacentes e simplesmente copiam os atributos de uma ponte para outra sem atentar-se para os riscos em potencial da nova construção.

Em muitos projetos, a palavra “risco” não é mencionada a menos que estejamos com sérios problemas. Em projetos de software, se não estamos usando essa palavra cotidianamente e incorporando-a em nossos planos, não estamos fazendo bem nosso trabalho. Como disse Tom Gilb: “se você não atacar ativamente os riscos, eles irão atacar ativamente você”.

#4 → Usar o mesmo planejamento em todos os projetos

Algumas organizações familiarizam-se com uma abordagem para executar projetos. Ela é mais conhecida como “o jeito que nós fazemos as coisas por aqui”. As coisas costumam ir bem quando os novos projetos são bem parecidos com os anteriores. Mas, se aparecer algo diferente, essa abordagem vai causar mais problemas do que ajudar.

Um bom planejamento visa necessidades específicas do projeto para o qual ele foi criado. Muitos elementos podem ser reusados, mas deve-se considerar cuidadosamente se os elementos antigos se aplicam ao novo contexto.

#5 → Aplicar modelos de planejamento indiscriminadamente

Um planejamento que alguém realizou chega na forma de um livro ou metodologia e parece funcionar muito bem do jeito que está. Então usa-se este plano genérico indiscriminadamente sem pensamento crítico ou consideração pelas particularidades do projeto.

Exemplos conhecidos são o RUP (Rational Unified Process), o XP (Extreme Programming) e, até certo ponto, meu próprio “Guia de Sobrevivência a Projetos de Software” (Software Project Survival Guide). Esses planos “pré-fabricados” podem ajudar a evitar os pecados #1 e #2, mas não substituem nossa análise das demandas únicas do projeto.

Nenhum especialista externo pode entender as necessidades específicos de um projeto como as pessoas envolvidas diretamente nele. O plano de um especialista deve ser adaptado para as circunstâncias específicas. Felizmente, existem gerentes que estão atentos para esses problemas e usam o senso comum para selecionar as partes dos livros de Engenharia de Software que atendem suas demandas.

#6 → Permitir que o planejamento esteja divergente da realidade

Uma abordagem comum ao planejamento é criar o plano no início do projeto e depois abandoná-lo numa gaveta, juntando poeira até o fim projeto. Quando as condições mudam, o planejamento torna-se irrelevante e, no meio do caminho, o projeto anda sem rumo. Não há mais relação do planejamento com a realidade do projeto.

Isso pode estar relacionado ao pecado #5, pois quando alguém abraça uma metodologia pré-fabricadas algumas vezes torna-se relutante em mudar quando ela não funciona. Eles pensam que o problema está na aplicação, quando, na verdade, está no planejamento.

Um bom planejamento deve ocorrer e ser revisado incrementalmente em todo o projeto.

#7 → Planejar muito detalhadamente logo de início

Alguns gerentes bem intencionados tentam mapear todas as atividades do projeto logo no início. Mas um software consiste num constante desdobramento de decisões, cada fase gera novas pendências para decisões futuras. Como não temos uma bola de cristal, tentar planejar atividades distantes em detalhes é um exercício burocrático tão ruim quanto não planejar nada.

Quanto mais trabalho é despendido em criar planos prematuros, maiores são as chances do plano ser engavetado (pecado número #6). Mas ninguém gosta de jogar seu precioso trabalho fora, então o gerente algumas vezes tentará forçar a realidade do projeto para se encaixar em seus detalhados planos, ao invés de revisar o plano prematuramente detalhado.

Eu penso num bom planejamento de projeto como dirigir a noite com os faróis do carro ligados. Eu posso ter um mapa que me diga como ir da cidade A para a cidade B, mas a distância que posso ver com os faróis é limitada. Em um projeto médio ou grande, um macro planejamento pode mapear todo o projeto. Então micro planejamentos detalhados conduzem o projeto apenas algumas semanas por vez.

#8 → Planejar para correr atrás do tempo perdido

Em projetos que começam a atrasar, um erro comum é planejar para se recuperar depois, correndo para “alcançar” o cronograma. A racionalização típica é: “a equipe passou pela curva de aprendizado no início do projeto, nós aprendemos várias lições duras, mas agora que entendemos o que estamos fazendo devemos conseguir concluir o projeto rapidamente”. Resposta errada!

Uma pesquisa de 1991 em mais de 300 projetos descobriu que dificilmente projetos recuperam-se, pelo contrário, a tendências é atrasar ainda mais. O erro desse raciocínio é que a equipe de desenvolvimento toma decisões importantes no início do projeto, enquanto ainda está aprendendo sobre as aspectos tecnológicos, de negócio, e sobre as metodologias. Nas fases posteriores do projeto, o passo não irá acelerar, mas diminuir na medida em que são colhidas consequências de decisões iniciais erradas e então é necessário investir tempo corrigindo esses erros.

#9 → Não aprender com os “pecados” cometidos anteriormente

O pecado mais mortal de todos é não aprender com os pecados já cometidos. Projetos de software podem levar muito tempo e a memória das pessoas pode ficar enevoada pelo ego e pelo tempo. No fim de um projeto longo, pode ser difícil lembrar todas as decisões iniciais que afetaram sua conclusão.

Uma forma fácil de contornar essa tendência e prevenir-se de pecados futuros é conduzir uma autópsia estruturada do projeto. Uma revisão não vai apagar os pecados passados, mas pode certamente evitar mais erros futuros.

Integração com Web Sevices usando Axis e inspecionando o conteúdo da mensagem SOAP

É comum realizarmos integrações entre sistemas através de Web Services tradicionais. Na minha empresa, em particular, usamos o Apache Axis, uma implementação Java do protocolo SOAP (Simple Access Object Protocol).

Observação: tratando-se de prover serviços de integração, eu, particularmente, escolheria o protocolo REST, mas quando acessamos serviços de terceiros não temos muita escolha, não é?

Irei descrever, em alto nível, os passos que geralmente realizamos para implementar a integração.

Requisitos

Antes de mais nada precisamos do arquivo WSDL (Web Servcie Definition Language), o qual define todos os serviços disponíveis, parâmetros e tipos de dados utilizados.

Algumas vezes recebemos a URL do end point, isto é, o endereço do Web Service. Por exemplo:

http://servidor:8080/app/webservices

Neste caso, obtemos o arquivo WSDL acresentando um parâmetro ao endereço, assim:

http://servidor:8080/app/webservices?wsdl

Gerando o client

O primeiro passo de implementação é gerar as classes de domínio e as interfaces stub usando o plugin do Eclipse WTP. (Siga os links para maiores detalhes)

Os objetos client são gerados com base no WSDL e assim o acesso ao Web Service se dá como uma chamada de método local, usando objetos locais, via RPC (Remote Procedure Call). A conversão dos objetos de e para XML no formato SOAP, além do transporte na rede é feito de forma transparente para o desenvolvedor.

Testando

O testes de integração com serviços de terceiros, pelo menos no nosso caso, não é algo viável de automatizar, pois não termos controle sobre o ambiente, nem acesso direto.

Para verificarmos se o serviços estão sendo acessados corretamente, criamos uma classe de teste com valores fictícios. O modelo do código ficou mais ou menos assim:

ServiceFactory serviceFactory = ServiceFactory.newInstance();
Service service = serviceFactory.createService(
        new ServicoServiceLocator().getServiceName()
    );
ServicoSoapStub stub = new ServicoSoapStub(
        new java.net.URL("http://site.com.br/app/ws"), 
        service
    );
ClasseRetorno retorno = stub.executarServico(
        new ParametroServico(...)
    );

Este link contém mais alguns que você pode usar como modelo para o seu Web Service.

Analisando o conteúdo da mensagem SOAP

Num caso específico, o cliente enviou exemplos de mensagens XML no protocolo SOAP e quisemos verificar se as mensagens geradas pelo Axis a partir do nosso código eram equivalentes em conteúdo.

Para inspecionar o Axis e ver o conteúdo da mensagem, adicionei os jars do log4j, commons-logging e commons-discovery. Também acrescentei na configuração do log (log4j.properties) a seguinte linha:

log4j.logger.httpclient.wire.content=DEBUG

Dessa forma, foram adicionadas mensagens no LOG com todo o conteúdo enviado pelo Axis.

Processos feitos para o fracasso

imagesO universo da tecnologia da informação é repleto de processos. Temos processos para desenvolvimento de software, prestação de serviços, gerenciamento de projetos (específicos ou não de software), garantia de qualidade e até para preparar o cafezinho da cozinha.

Note que não estou me referindo exatamente a modelos de processos como waterfall (cascata), iterativo, incremental, evolucionário, espiral e de prototipação, nem de metodologias ou frameworks de processos como Scrum, XP, RUP, ITIL, COBIT, CMMI ou MPS.BR. Todos estes possuem seu valor e nos dão uma base para definir o processo que adotamos no dia-a-dia nos mais diversos aspectos, incluindo artefatos, atividades e boas práticas fundamentais.

O foco deste artigo é no processo implementado em nosso ambiente de trabalho, o qual somos (algumas vezes) obrigados a seguir. 

Em conversas com colegas de trabalho, ao pronunciar a palavra mágica “processo”, geralmente ocorrem duas reações: uma gargalhada ou uma cara feia. No primeiro caso, o riso é acompanhando de desdém, tipo: ” se pelo menos tivéssemos um processo de verdade…”. Do outro lado, estão os que ficam quase irados: “não entendo porque nos fazem perder tempo com esses processos que não servem pra nada!”

Mas e aí? Você se encaixa em um desses grupos? O processo é um obstáculo no seu trabalho? Ou talvez você esteja do outro lado, criando processos para sua equipe ou empresa e acredita que certas atividades são de grande importância, mas não consegue se fazer entender. Vamos analisar alguns desses aspectos nos tópicos a seguir.

Quando realmente sofremos com o absurdo

angry-computer-large

Para ilustrar o sofrimento que alguns desenvolvedores tem de aturar, irei descrever exemplos de alguns dos piores casos de processos, ou de motivos para a definição deles, que já testemunhei:

Ditadura
Alguém da diretoria quer “controlar melhor” as atividades, culminando em algo excessivo e desnecessário. Houve um caso onde o chefe queria relatórios de atividades dos funcionários com detalhes em minutos! Por quê? Vai saber…

Labirinto
Processo confuso e redundante. Além de mandar e-mail, preencher documentos e incluir informações no sistema de controle, ainda é necessário imprimir e assinar um documento. Nesse tipo de processo, o desenvolvedor sempre é “culpado” por esquecer algum dos passos “essenciais” do processo.

Surpresa
Tudo está normal, de repente, você dá de cara com o processo.

Certa vez, ao  solicitar o envio de um script de correção urgente ao cliente, responderam-me:
– “Onde está o documento de envio?”
– “Que documento?”, repliquei.
E então, a surpresa:
– “Houve uma reunião com a diretoria hoje e recebemos ordens de, a partir de agora, não enviar nada ao cliente que não esteja acompanhados do respectivo documento de envio.”
Bem, restou-me correr atrás de alguém que pudesse me dizer do que isso se tratava… ordens são ordens, não é?

Morto-vivo
Às vezes o processo é essencial, outras nem tanto. Você leu o tópico anterior? Algum tempo depois disseram que o tal documento não era mais necessário. Isso mudou intermitentemente algumas vezes. Já aconteceu de você ficar perdido em como sua empresa funciona?

“Garantia” de Qualidade
Neste ponto alguém pode até argumentar em contrário, devido às boas práticas que alguns processos agregam. Porém, já presenciei casos onde um determinado processo foi adotado para tentar diminuir o número de defeitos num sistema! Primeiro, de forma geral, a burocracia apenas deixa o programador mais nervoso. Além disso, os desenvolvedores eram pouco experientes, então seria melhor investir em treinamento ou incluir pessoas mais maduras no projeto.
Em outra situação, um funcionário que recebeu a incumbência de uma atividade simples estava errando repetidamente, semana após semana. Ele simplesmente devia copiar alguns valores de uma planilha e fazer a inclusão no banco de dados, mas frequentemente os valores do sistema ficavam errados. Seu superior não sabia o que fazer. Seria de propósito? Seria uma total falta de inabilidade? Seria falta de comprometimento? O gerente tentou resolver a situação com um “processo” onde o funcionário problemático teria que “prestar contas” de suas ações. Obviamente isso não resolveu.

Marketing
Determinados certificados relacionados a processos (como CMMI e MPS.BR) colaboram para o status das empresas. Logo algumas investem tempo e dinheiro em práticas e documentações inúteis a fim de aumentar sua credibilidade para com clientes em potencial, sem se preocupar efetivamente com a qualidade de seus produtos ou com a queda de produtividade. Resta aos funcionários ficar até mais tarde para cumprir as exigências adicionais.

Processos servem para alguma coisa, afinal?

O processo é uma ferramenta. Como tal, ele deve ser usado para que os envolvidos e a organização como um todo alcancem seus objetivos. Estes objetivos devem estar alinhados às metas da organização, aos requisitos dos clientes e com as exigências dos órgãos regulatórios.

Um grande problema é que os requisitos e exigências são por vezes conflitantes. Por exemplo, para o cliente, as entregas de correções devem ser imediatas. Entretanto, do ponto de vista de qualidade, é necessário haver revisão e testes, que oneram razoavelmente o tempo necessário para entregar algo. Nos ambientes mais desorganizados, o desenvolvedor pode executar um script diretamente em produção. Por outro lado, em algumas empresas os usuários estão acostumados a ficar dias parados porque as correções não podem ser aplicadas sem uma série de aprovações de diferentes setores.

O processo pelo processo

Um dos maiores erros na engenharia de software é adotar um processo sem um motivo concreto, porque é “legal”, a última moda. Pior, alguns acreditam que determinado processo é a solução para as dificuldades do dia-a-dia. Ainda há aqueles que ficam tão impressionados com um determinado processo que tentam adotá-lo integralmente, com toda sua carga de artefatos e atividades.

Muitos gerentes e diretores acreditam que podem resolver os problemas de gerenciamento simplesmente adotando uma nova abordagem de processos. Eles não conseguem entender porque seus subordinados são tão avessos e resistem tão intensamento a mudanças. Por que será?

É uma questão de mentalidade

Por que resistimos aos processos e reclamamos deles? Por que alguns relatam um “renascimento” ao adotar processos ágeis? Por que os gerentes estão sempre impondo novos processos?

Existem conflitos de expectativas e entendimento. Considerando que não haja absurdos no processo, os desenvolvedores reclamam porque não entendem a necessidade da diretoria. Por que parece que quando um programador é promovido a gerente ele se “converte ao lado negro da força”? Na verdade ele simplesmente amadureceu e percebeu a importância de um gerenciamento adequado. Nós, desenvolvedores, devemos procurar amadurecer e compreender os desafios de nossos superiores, pois assim poderemos contribuir de forma mais efetiva em nosso trabalho e, quem sabe, os gerentes não sentirão a necessidade de criar processos rígidos para resolver seus problemas.

Por outro lado, os gerentes devem entender que processos não resolvem os problemas por si mesmos. Analogamente ao nosso governo, criar leis duras e colocar o exército nas ruas não irá mudar a mentalidade do povo, embora a opressão possa dar a impressão de maior organização e controle. Fazer “a coisa certa” é um desafio gigante, mas conseguir a sincera colaboração e motivação dos envolvidos é algo que não tem preço.

E os processo ágeis? Os “agilistas” relatam que métodos ágeis podem aumentar em diversas vezes a produtividade da equipe, a qualidade, deixar o cliente mais satisfeito e os desenvolvedores mais felizes e realizados. Será que realmente não seria o caso de existir um processo “bala de prata”, isto é, que garantisse o sucesso?

Se você observar a literatura dos “agilistas”, perceberá que antes de alcançar qualquer nível de sucesso, houve uma mudança de mentalidade geral dos envolvidos. Mas, quando o processo ágil falha, logo dizem que ele não foi seguido corretamente. Há uma certa verdade nisso, pois sempre que falhamos é porque não fizemos as coisas como deveriam ser feitas. Porém isto também se aplica a todos os processos.

Conclusões

Enquanto, em nosso trabalho, não pararmos de correr desenfreadamente em qualquer direção, pensando apenas em entregar código e se livrar do fardo que os superiores nos colocam, nunca iremos amadurecer, crescer profissionalmente e ter o prazer de entregar software bem feito.

Devemos rever nossos conceitos e despertar para a realidade do que estamos fazendo, não apenas continuar a repetir indefinidamente e irrefletidamente o que já praticamos vez após vez.

Devemos usar o processo como um aliado para nossos objetivos, que deve intervir em caso de necessidade e não como lei primordial. A chave para o sucesso do projeto (e do processo também), consiste em:

  • Transparência: o desenvolvedor merece saber e deve entender a razão do processo;
  • Confiança: o processo não deve ser feito baseado na desconfiança entre as partes ou resultará em um mal-estar geral;
  • Equilíbrio: embora virtualmente fosse bom controlar tudo o que ocorre na empresa, o processo deve ser apenas bom o suficiente para cumprir seus objetivos.

Lembre-se: o processo pode tanto contribuir como obstruir o desenvolvimento de software.

Para refletir: como saber se seu processo foi feito para o fracasso?

Pense nas atividades que devem ser executadas. Se o sentimento que lhe vier à mente for equivalente a quando você precisa fazer uma ligação de cancelamento de serviços (TV a cabo, celular, …), então provavelmente as pessoas farão tudo ao seu alcance para evitá-lo!

Se você está nessa situação (e é fã de Star Trek) vai entender que “resistir é inútil!”

Does good developers write complex code?

Did you ever see a developer boasting of himself because he created a hard-to-understand code? Perhaps you ever fancied yourself doing something like this:

void Run( const std::string& v, int tgt, int start ) { for( ; tgt >= 2 * start + 1; ++start ) Run( v + ' ' + boost::lexical_cast( start ), tgt - start, start + 1 ); std::cout << v << ' ' << tgt << std::endl;} int main() { Run( std::string(), 10, 1 ); getchar();}

(Source: http://www.cplusplus.com/forum/lounge/13042/)

Complex code is bad code

spaghetti-code A good developer knows complexity is his enemy. When we work with real software we have to fight it. Complexity hides errors, makes software obscure, and is a hindrance to maintenance. If all that doesn’t bother you, think in your own wallet, mainly if you’re a consultant, a freelancer, or own a company.

Did you ever work with code written by yourself a long time ago and had a hard time? How could you write such a hideous thing? If you were more careful, perhaps it would keep you or a colleague from future nightmares, isn’t? Of course it would! And hope shines if you are now able to see that!

Complex code is bad code. Maintenance will require too much refactoring and testing. Did you ever see a messed program you prefer rewrite it thoroughly instead of just make the changes required?

“Oh, but we have comments, don’t we?”, you can argue. Not so fast! Many will oppose to you. To begin with, processes like XP (eXtreme Programming) states that the code should be clear and self-explaining. Comments often are our enemies too. They can indeed fool us stating something the code doesn’t actually does. In excess, they pollute the code visually and make our sources longer.

Be simple

One approach to escape complexity is the principle known as KISS: “Keep It Simple, Stupid!“. Let’s outline a few steps from this “rehabilitation program for bad developers”:

  • Be humble, don’t think of yourself as a genius.
  • Break down your tasks in sub tasks: don’t work more than a few hours in the same code.
  • Study seriously about cohesion, coupling, class and method responsibility, SOLID principles.
  • Solve the problem first, then code the solution.
  • Don’t be afraid of throw code away.

An experienced software engineer should know how to use the available tools to produce the desired result with the minimum complexity and effort.

On the other hand, developers love to reinvent the wheel. In my first years as a developer, I thought to my myself: “I have no reason to learn framework XYZ if I can write my own framework!”. Yes, I’m guilty. I wrote a lot of small frameworks. Did it help me? Of course! I tested my own limits, learned the internals of these little monsters and then realized the importance of the work of other developers. I threw much code away and now I’m happy using frameworks and tools knowing exactly how they work and why they do what they do.

Simplicity example

Watch this video as if the guy at right was you in college and the guy at left you with years of experience.

Conclusion

Who cares if the program takes a bit less time to run or how much “pretty” the code is? Are we talking about the developer’s ego?

A mature IT professional should strive to improve his communication abilities. Whatever is your specialization, all artifacts in the development process should fulfill its purpose in communicating the information as effectively as possible.

Furthermore, it’s better keep our artistic skills for things like the International Obfuscated C Code Contest:

#define _ -F<00||--F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_
}

Página 8 de 10

Creative Commons O blog State of the Art de Luiz Ricardo é licenciado sob uma Licença Creative Commons. Copie, compartihe e modifique, apenas cite a fonte.