Categorias
Geral

NULL

foto do buraco negro Messier 87 que parece com um círculo de fogo desfocado sobre fundo preto

Quase todo desenvolvedor profissional vai ter que lidar com um banco de dados relacional ao longo de sua carreira. Os bancos de dados relacionais são uma daquelas ideias boas que a computação trouxe para o mundo.

Obviamente esses sistemas possuem limitações e essas limitações se dão tanto no nível conceitual como nas várias implementações de SGBD exitentes.

A limitação do modelo relacional existe porque não dá pra modelar o mundo que nos cerca usando conceitos tão “bidimensionais” como tabelas.

Ok, eu sei que dá pra modelar 3D, séries temporais, hierarquia, graphos, etc em bancos de dados relacionais, mas você vão concordar que as coisas começam a ter que ser ligeiramente “enjambradas” nas tabelas pra isso funcionar. E o funcionar ainda pode trazer algumas limitações.

Também tem as limitações de implementações do modelo. Os SGBDs ainda precisam saber se aquela coluna vai armazenar um texto ou um número e qual o tamanho esse dado vai ter.

Mas tem um negócio que é praticamente onipresente nos bancos de dados relacionais. O NULL.

O NULL serve para dizer que aquele dado, daquela coluna, naquela linha “não existe”. Não importa se essa célula de informação é um texto, uma data ou uma chave primária/estrangeira.

Ele também é um tipo de dado “complementar”, ou seja, você não diz que uma coluna da tabela é do tipo NULL. Você diz que aquela coluna é do tipo X e também pode guardar um NULL. Ou seja, o valor NULL não é um tipo mas também serve a todos os tipos.

O NULL também é usado para modelar as relações entre os objetos de duas tabelas. É ele que vem como resposta ou influencia o resultado dos famigerados LEFT|RIGHT|INNER|OUTER|... JOINs que tanto demoram pra entrar na cabeça dos desenvolvedores.

O NULL é tão esquisito que força os programadores, tão acostumados com a lógica binária, a pensar em uma lógica com três estados.

Esses problemas mencionados até aqui podem ser extendidos aos nil, None de várias linguagens de programação, portanto, a dica que eu vou dar pode se aplicar em outros contextos: se você puder evitar usar NULL, faça isso.

Um exemplo do tipo de discussão sobre NULL causa aconteceu na nossa equipe. A gente está trabalhando em um sistema que cadastra perfis de cavalos. Então teremos nesse cadastro o nome do cavalo, a cor dele, a árvore genealógica, gênero, etc. Algumas dessas informações podem mudar ao longo do tempo (ex. um cavalo pode nascer de uma cor e mudar de cor na vida adulta). Outro problema que temos que lidar é com a fragmentação e qualidade dos dados das nossas fontes (ex. algumas base de dados que temos não informam a cor do animal).

Considerando esses requisitos e limitações é bastante comum que programadores, por reflexo, saiam colocando várias dessas colunas como NULLABLE no banco de dados. Mas isso trás alguns problemas que eu pretendo demonstrar (provavelmente de forma incompleta) abaixo.

Perda de Otimizações

Alguns SGBD podem perder otimizações em cenários onde temos colunas NULLABLE. Esse artigo aqui (inglês) tem uma explicação mais detalhada de um desses problemas.

O tipo de problema de otimização causado por colunas NULLABLE variam de SGBD pra SGBD, então recomendo que você faça uma busca por “nullable optimization [seu banco de dados]” no seu buscador favorito para entender o impacto do NULL no seu SGBD.

Pobreza Semântica

Quando usamos NULL no lugar de um valor real sabemos apenas que não temos aquele valor. Mas o que isso significa de fato? Não dá pra saber.

Vou dar um exemplo bem simplificado para ilustrar melhor… Imagine que temos um site de e-commerce e na nossa tabela de produtos (ex. Product) a gente tenha uma coluna para guardar o diâmetro do produto (ex. diameter). Na sua loja virtual você tem produtos com essa característica (ex. parafusos, canos, etc) e produtos que não tem essa característica (ex. caixa decorativa, piso porcelanato, furadeira).

A gente pensaria: esse campo é NULLABLE porque ele não precisa ser preenchido para todos os produtos.

Mas o que o não-valor NULL significa de verdade nesse contexto? significa que eu “não sei o valor” porque ainda não medi o objeto que está cadastrado no meu banco de dados? Significa que o valor diâmetro não se aplica àquele produto porque ele é uma caixa? Significa que ele ainda está aguardando a informação porque ela é preenchida de forma assíncrona por outro serviço ou equipe?

Não existe uma solução específica para adicionar mais semântica para esses dados. Existe um conjunto de técnicas e práticas que podem ser usadas pra resolver esse problema.

No caso da cor do cavalo que comentei acima, temos uma Foreign Key (FK) para uma tabela de cores oficiais de cavalo (sim, isso existe), o ideal seria criar uma cor NOT_AVAILABLE na tabela de cores e referenciar ela quando não conseguirmos determinar a cor do animal. Mas a mesma solução não serviria para a data de nascimento dele.

Como temos diferentes tipos de informação que podem ou não estar disponíveis precisamos criar uma modelagem específica para lidar com isso.

Coalescing

Quando dizemos que uma coluna é de um tipo específico podemos fazer nossas queries e nosso código sempre assumindo que o dado retornado é daquele tipo.

Saber disso diminui a complexidade do nosso código porque não precisamos ficar lidando com um cenário excepcional onde o tipo do dado muda nem ficar convertendo esse dado de um formato para outro.

NULL é inevitável

Infelizmente nem sempre é possível evitar o uso de NULL. Eventualmente precisamos recorrer à ele ou preferir ele à outras opções.

Se eu tenho uma coluna birthdate e nem sempre eu terei essa informação para preencher no meu banco de dados é preferível usar NULL do que armazenar uma data inválida tipo 00/00/0000. Usar uma data inválida só vai servir pra mudar a complexidade de lugar (quando precisar calcular a idade da pessoa preciso excluir datas zeradas pra não ter alguém com 2020 anos).

No caso do diâmetro que eu mencionei acima, podemos usar um 0 pra sinalizar que o objeto não tem diâmetro. Mas fazer isso pode trazer problemas e complexidades para o sistema de shipping fazer o cálculo da volumetria do objeto pra calcular o frete. Nesse caso usar NULL pode fazer mais sentido (e usar uma segunda coluna pra adicionar semântica à esse NULL).

Conclusão

NULL não é inerentemente ruim e não estou desaconselhando ele. O objetivo desse artigo é só “desligar o automático” na cabeça dos desenvolvedores na hora de tornar uma coluna NULLABLE.

E quando estiver usando NULL é importante redobrar a atenção com seu código e com seus dados.

PS. NULL significa Zero em Alemão. Então eu abro exceção e tomo Coca-Cola Null Zucker (zero açucar) por aqui. 😉

Categorias
Geral

Ensinando Testes

Depois de algum tempo escrevendo código com testes automatizados eu comecei a considerar que cursos e livros sobre esse assunto fossem sempre um tipo de “falcatrua”. Achava que ensinar a fazer testes não fazia muito sentido.

Mas quando abri minha empresa de consultoria e treinamento eu recebia vários pedidos de clientes para ministrar um “Curso de TDD” para suas equipes. Então resolvi desenvolver esse curso.

Só uma observação: eu uso teste automatizado e não ao longo desse texto porque é importante saber que TDD é uma técnica de desenho e modelagem de código que usa testes automatizados mas tem muito software com testes automatizados que não foram criados com TDD.

Voltando para o curso…

O curso ficou bem legal e os slides estão disponíveis gratuitamente hoje em dia, já que não vendo mais ele e nem tenho mais a minha empresa.

Ter desenvolvido esse curso mudou a minha visão sobre ensinar testes com cursos e livros? Não mudou.

Prática vs. Perfeição

Eu continuo achando que só é possível aprender a escrever testes na prática. E durante o curso, como vocês podem ver nesse slide, eu menciono isso para não alimentar falsas expectativas de que cada aluno ali seria um “mestre dos testes” após concluir o meu treinamento.

Eu estabeleci um paralelo entre aprender escrever testes com aprender uma arte marcial. E usei a figura do Sr. Miyagi ensinando caratê pro Daniel San (ok, eu sei que sou velho mas me recuso a usar a figura do tira-casaco/coloca-casaco que ensinava Kung-Fu).

E, tal como nas artes marciais, você não aprende a escrever testes em livros e cursos.

Resolvi estabelecer uma proposta “ousada” para o curso: não ensinar a escrever testes.

No lugar disso o curso daria uma fundamentação sobre o que é teste, pra que servem, a importância deles, e desmistificaria algumas bobagens que dizem sobre eles (ex. cobertura de 100% é essencial, código com testes não tem bugs, etc). Depois a gente teria algumas atividades práticas controladas (as tão temidas “dinâmicas”).

Em uma dessas dinâmicas eu criava uma atividade parecida com a de um Coding Dojo com os alunos. O problema em todas as turmas era sempre o mesmo: converter números para algarismos romanos.

Essa dinâmica baseada em Coding Dojo servia muito bem no processo seletivo de uma outra empresa onde trabalhei mas isso é assunto para outro artigo.

Eu observava a dinâmica mas não trabalhava no problema. Eu tomava nota de algumas coisas da atividade e, no final, a gente discutia o que havia acontecido de errado, o que tinha dado certo e eu ia encaixando os tópicos de TDD para serem ilustrados pelo que eles experimentaram.

Depois disso a gente passava por mais alguns fundamentos e retornávamos para a prática.

A segunda atividade era escrever um encurtador de URLs completo na linguagem/framework que a empresa usava ou com o qual a maior parte da equipe estava mais familiarizada.

Nesse momento a gente aprendia como organizar melhor os testes, como usar as ferramentas de teste e até como fazer TDD. Essa atividades levava de 1 a 2 dias e eram feitas em duplas (pair programming) que eram trocadas a cada 2 horas (o critério de troca era misturar abordagens das diferentes duplas com programadores(as) diferentes).

Por fim eu indicava alguma literatura complementar (majoritariamente como referência) porque obviamente eles aumentam a sua compreensão sobre testes automatizados mesmo não sendo a fonte principal de aprendizado.

Uma curiosidade sobre a dinâmica do Coding Dojo com o problema dos algarísmos romanos: eu ministrei esse treinamento para 5 turmas diferentes. Das cinco turmas que trabalharam no problema, cada uma delas entregou solução completamente diferente umas das outras. Todas funcionavam e atenderiam tranquilamente requisitos de performance, uso de memória, etc. Engraçado notar como pessoas e times possuem perspectivas tão distintas sobre os problemas apresentados.

Não é fácil mas é possível

Infelizmente é impossível aprender a escrever testes sem praticar. Mas eu garanto que vale a pena tentar.

Vai ser frustrante e lento no início mas depois as coisas aceleram.

E entenda que o seu “caratê” vai ser bem ruim no começo e, talvez, no futuro, ele fique ótimo. Você pode até chegar à faixa preta mas atingir a perfeição é impossível.

Por conta dos seus testes serem ruins no começo eles vão gerar um grande esforço de manutenção. Aquele refactoring ou bugfix “trivial” vai te garantir horas de reescrita de testes. Desistir vai parecer uma ótima ideia nessas horas. E é aí que você vai precisar perseverar. Entenda que isso acontece porque seus testes ainda não estão muito bons (ou ainda que o seu código sendo testado precise de algumas melhorias).

E quando você não conseguir mais programar sem testes você vai ver que valeu a pena.

Categorias
Geral

Python Raiz

Logotipo antigo do Python onde se lê "Python Powered" com uma fonte pontilhada em branco com uma borda preta. Esse logotipo fica sobre uma elipse azul

Como todos sabem sou programador Python a quase duas décadas e boa parte da minha carreira foi construída em torno desta linguagem. E isso mostra como ela é excelente. Pra uma pessoa como eu, que adora aprender e estudar linguagens de programação, significa muito priorizar uma só linguagem por quase metade da vida.

Mas o que me motivou a escrever esse texto aqui foram as adições recentes (ou nem tão recentes) à linguagem. Coisas como suporte para desenvolvimento assíncrono (async, await, etc), anotações de tipos, f-strings, operador “walrus” (:=), e a mais recente delas (cuja PEP ainda está em “Draft”): Pattern Matching.

Python Nutella

O conceito de Pattern Matching já existe a bastante tempo (Prolog?) mas ficou mais popular com a recente adoção da excelente linguagem Elixir por muitos desenvolvedores.

O uso mais básico de Pattern Matching pode ser visto nas instruções switch/case presente em várias linguagens de programação estruturadas. Mas Pattern Matching não é “só” um switch/case. Nos tradicionais comandos de switch/case as linguagens avaliam uma expressão (switch expr) e dependendo do resultado da expressão ele busca um bloco de código que dê “match” com esse resultado (case constant-expr).

Mas em linguagens como Elixir (que é a que usarei como exemplo por conhecer melhor) esse “match” pode ser feito com regras muito mais elaboradas e usar estruturas de dados completas no lugar de apenas um valor constante, como nas linguagens que mencionei acima.

Abaixo vou colocar um exemplo de código pseudo-Python que demonstra como uma função pode ser implementada sem e com Pattern Matching:

Esse caso mostra como o conceito é poderoso e prático para resolver uma série de problemas. E a sintaxe parece razoavelmente natural. Mas parece que essa “naturalidade” some quando avançamos pelos exemplos da PEP e começamos a ver coisas como:

O que me assusta em tudo isso são as invenções de coisas que nunca estiveram no Python:

  • _ como caracter coringa: o caracter _ sempre foi usado, por convenção, como uma variável cujo valor pode ser descartado. Um exemplo disso seria fazer coisas como: name, url, *_ = 'name,url,extra,data'.split(','). Porque não usar a cláusula else: com o match?
  • Dotted-names: Os casos de Constant Value Patterns onde tiveram que inventar uma sintaxe nova com dotted-names é outra coisa que nunca vi no Python. Essa sintaxe foi descartada anteriormente para coisas muito mais simplórias como quando pediram algo parecido com with do Pascal.
  • | como operador de alternativa: | já existe em Python e ele faz as vezes de OR bit-a-bit. Também temos o or que faz as vezes de OR lógico. Me parece que, mesmo não sendo semanticamente a mesma coisa, o segundo OR lógico faz mais sentido do que o OR bit-a-bit. Uma opção aceitável, por familiaridade, seria o uso de || que também é usado como OR lógico em diversas linguagens.

Mas o que mais me desagrada nessas recentes adições à linguagem é a preocupação que tenho com “legibilidade natural da linguagem“. E não, essa legibilidade não tem relação direta com escrever código limpo e organizado para programadores Python. Tem relação com a capacidade de um código ser compreendido até mesmo por algum desenvolvedor que não conhece a linguagem.

Aprendendo Python

Python não foi minha primeira linguagem. Já conhecia outras antes dela. Essas linguagens eram majoritariamente estruturadas mas eu já tinha brincado um pouco com desenvolvimento orientado à objetos com Object Pascal do Turbo Pascal 6 e 7 (com Turbo Vision e tal).

Meu primeiro contato com Python se deu por volta do ano 2000 na extinta e saudosa Conectiva (aquela do Conectiva Linux que depois se juntou com a Mandrake pra formar a Mandriva que também sumiu… enfim… uma bagunça 🙂).

Eu estava trabalhando em um projeto de “compilador de configuração para interfaces gráficas”. Esse é o nome chique que dei agora… na época era só um programa escrito em C que geraria os arquivos texto de configuração para Gnome, KDE e WindowMaker à partir de um conjunto de configurações centralizadas.

Mas o importante para a discussão de agora é a parte do “escrito em C” e “arquivos texto”. Todos sabem que C e texto não se harmonizam muito bem, certo? Então… no final tudo daria certo. Só demoraria mais tempo pra ficar pronto.

Certo dia meu chefe me trouxe um artigo que ensinava Python. Ele havia traduzido o artigo original para o português e pediu pra que eu desse uma revisada (acho que a intenção dele era outra já nem sabia inglês direito). O artigo original não está mais no ar mas tenho uma cópia dele (a tradução se perdeu).

A versão do Python, naquela época, era 1.5.2 (o artigo foi atualizado depois que eu li para acrescentar coisas do Python 2). E lendo só esse artigo eu aprendi Python em 1, uma, UMA f*cking noite! Com um artigo de blog!

Eu aprendi Python em uma noite porque eu sou inteligente? Esperto? Super-humano? Não! Dêem uma olhada no post.

Eu espero.

Viram como a linguagem do artigo é simples? Ela é legível, as construções dela são intuitivas: v = 1 atribui valor 1 pra v, v == 2 compara valor v com 2, v[0] acessa o primeiro elemento de um array/lista, class Person: ... define uma classe, e assim se segue. Ou seja, para uma pessoa que programa minimamente em algo conseguia aprender a linguagem muito rápido.

Tinham pouca coisa estranha nessa linguagem que não existia em outras. Talvez o fato de usar indentação pra delimitar os blocos de código e aquele parâmetro self nos métodos de instância. Mas tirando isso é tudo bem normalzinho.

Agora imaginem uma pessoa aprendendo Python com coisas como:

Imagina esbarrar com um código desses logo de primeira? O cara volta pro Perl 🙂 Just kidding…

Eu sei que o código do artigo é praticamente o mesmo para rodar no Python de hoje (talvez só o uso de print() e input() tenha mudado com o Python 3).

Também sei que o artigo não ensina tudo sobre a linguagem (mesmo naquela versão da época). Ele é só uma introdução. E de fato, quando decidi me aprofundar mais no aprendizado da linguagem eu fui atrás de outros materiais. Li o The Python Tutorial que vem com a própria linguagem e na seqüencia importei um livro que realmente ensinava a linguagem toda: Learning Python da editora O’Reilly.

Naquela época eu comprei a primeira edição do livro que, hoje, já está na quinta edição que cobre até o Python 3.3.

Finalmente eu pude estudar tudo o que Python tinha. E até hoje eu recomendo esse livro. Mas vou falar uma curiosidade sobre ele: a 1ª edição tinha 384 páginas. A 5ª edição tem 1648 páginas! Mais de 4 vezes maior. E nem descrevem as (muitas) novidades do Python 3.4, 3.5, 3.6, 3.7, etc.

Ou seja, se você realmente pretende dominar tudo o que a linguagem oferece vai levar uma vida. Além do Learning Python eu ainda recomendo o Fluent Python (assim que a segunda edição sair eu atualizo o link) do meu querido amigo Luciano Ramalho.

Python para não-programadores

Todo mundo sabe que Python tem crescido muito na comunidade científica. Isso aconteceu muito graças à iniciativas como SciPy e de projetos que nasceram dentro dessa iniciativa e ganharam vida própria como o Jupyter, matplotlib, pandas, scikit-learn, etc.

Por outro lado Python também se tornou uma linguagem muito usada no ensino de programação de diversas escolas e universidades em todo o mundo. Usam ela para ensinar programação para todo mundo e não só para alunos dos cursos de computação e afins.

E essas duas coisas estão relacionadas. Se você ensina programação com Python para um aluno de biologia qual linguagem ele vai usar para escrever uma ferramenta que auxilia num trabalho de genética?

Porque essas escolas escolheram Python para ensinar programação Porque projetos como SciPy e Jupiter escolheram usar Python? Porque não escolheram outras linguagens?

Eu suspeito de que seja um conjunto de atributos da linguagem, entre eles:

  1. Educacional: Python nasceu de um projeto de linguagem educacional (ABC), mas também nasceu porque seu criador (Guido van Rossum) acreditava que linguagens educacionais não precisavam ser de brinquedo (toy languages) e que deveria ser possível usá-las no dia-a-dia.
  2. Multiplataforma: instalação, implementação e uso fácil nas principais plataformas disponíveis.
  3. Multipropósito: você consegue desenvolver software de linha de comando mas também consegue implementar uma interface gráfica ou um servidor Web.
  4. Multiparadigma: sabe programação estruturada? ok. Sabe modelagem OO? ok também. Sou craque em lambda functions? tá lá também um básico pra você usar.
  5. Facilidade de integração com bibliotecas em de outras linguagens como C, Fortran, etc. Vocês devem imaginar o imenso número de bibliotecas científicas implementadas em outras linguagens. Porque reescrever tudo?

Mas o que eu acho mais importante para essa escolha é a de que todos os cientistas que já programaram alguma coisa para seu trabalho conseguem ver um código Python e ter uma ideia, mesmo que superficial, do que aquilo faz. É a tal “legibilidade natural da linguagem” que já mencionei.

Multipropósito

Se você quer um carro que comporte toda a família, seja potente, veloz, econômico, tenha porta-malas grande, seja espaçoso, confortável, etc você provavelmente vai acabar com isso aqui:

Python nasceu pra ser fácil de aprender e usar. Ter uma sintaxe limpa, clara e familiar. Sem coisas esdrúxulas como símbolos em excesso ou coisas menos convencionais como a sintaxe object message do Smalltalk (que inspira a sintaxe do Ruby).

Python também nasceu sem tipos ou anotações de tipos. Tudo nela foi pensada para abstrair esse conceito “mundano” da computação. Isso facilita o aprendizado das pessoas.

Python nunca pretendeu ter uma performance absurda. Só a performance necessária para permitir o seu uso em problemas reais. Se você precisasse de performance absurda você provavelmente escreveria código em C ou Assembly e “colaria” ele com Python.

Python nunca foi pensada para concorrência ou paralelismo. Então não dá pra “competir” com linguagens como Go ou Elixir (Erlang) nesse quesito. Essas linguagens nasceram pra lidar com esse tipo de problema. Acrescentar um punhado de palavras reservadas e algumas bibliotecas não torna Python ideal para esse propósito.

Python não nasceu como linguagem funcional. Mesmo ela tendo ferramentas que te permitam expressar algumas ideias de modo funcional ela não é uma linguagem funcional de verdade. Python nasceu como linguagem majoritariamente orientada à objetos.

Colocar um map() aqui e um lambda acolá não torna a linguagem própria para resolver problemas que são mais facilmente solucionáveis com linguagens funcionais. Python tem objetos mutáveis. Python não tem suporte nativo à tail-recursion. Macros? O próprio Guido já disse que “nem morto” (não achei a referência, mas acredite, eu vi isso).

Guarda-Chuva

Python já não é mais uma linguagem de nicho ou underground. Python já é mainstream e centenas ou milhares de empresas de diversos portes já usam ela em seus negócios.

Como consequência disso o número de vagas de emprego e trabalhos com Python cresceu vertiginosamente nos últimos anos e por isso, inevitavelmente, programadores de outras linguagens acabam tendo que lidar com Python em algum momento de suas carreiras.

Por conta dessa situação eu tenho a sensação de que a necessidade de adicionar certas funcionalidades no Python vem do desejo desses programadores de usar parte favorita da outra linguagem também em Python porque eles não conseguem pensar “do jeito Python”.

Lembro bem quando Java estava na moda e todo programador Python criava getters/setters nas classes. Inventavam mil maluquices como Interfaces (no Zope), protocols, … para terem algo parecido com o que Java oferecia. Um baita esforço pra programar Java em Python.

Hoje em dia parece que tá todo mundo querendo programar Elixir em Python, JS/Node em Python, …

Sem Conclusão

Vocês devem estar imaginando que estou ficando desgostoso com a linguagem ou que vou abandoná-la. Não estou não. As coisas novas que não gosto de usar irei ignorar (ex. operador :=). Outras que me fizeram até torcer o nariz mas passei a gostar entraram pro meu repertório (ex. f-strings).

Tem aquelas funcionalidades que me fazem torcer o nariz, e quando dei uma chance pra elas descobri que podem ser úteis se forem usadas com muita moderação (ex. type annotation) serão usadas com moderação.

Enfim… Vou continuar a usar e a gostar de Python. Até porque ela tem tantas qualidades que me deixou preguiçoso para mudar. Mas pretendo continuar a programar Python em Python. Daquele jeito raiz. Daquele jeito moleque… aquela programação Python de várzea.

Update: corrigido um erro no operador “OR lógico” para or e adicionei uma sugestão de uso do ||.

Categorias
Geral

Mercado saturado: isso importa?

Como me envolvi em vários eventos voltados para empreendedores nos últimos anos recebo e-mails de várias pessoas que pretendem desenvolver seus próprios empreendimentos. O perfil dessas pessoas geralmente é formado por programadores ou freelancers que tiveram uma idéia e querem desenvolve-la até que ela se torne um negócio.

Recebo vários tipos de perguntas mas tem um tipo que me chama a atenção: “Você não acha que esse mercado está saturado?”.

Essa pergunta me chama a atenção porque, por trás dessa aparência inocente, ela tem várias subquestões importantes como: mercado “oceano azul” vs “oceano vermelho”, mercado global vs local, ineditismo vs copycat, etc.

Ineditismo

Dia desses um amigo chegou com uma ideia interessante e disse que ia começar a desenvolve-la. Algum tempo depois eu fui perguntar pra ele como estava o andamento do projeto e ele me respondeu: “Ih! Desisti da ideia. O Google implementou um produto ‘igualzinho’.”.

Eu achei a resposta interessante porque parece que as pessoas se esquecem que já existiam buscadores antes do Google 🙂 O que o Google fez para alcançar o domínio nas buscas foi criar um produto que funcionava melhor que os concorrentes.

Mesmo com esse ótimo produto eles tem os seus concorrentes em buscas específicas como busca de ofertas (ex. Buscapé no Brasil), busca de estabelecimentos locais, etc. Eles tem concorrência até mesmo para o produto principal: DuckDuckGo (a participação de mercado é menor mas mesmo assim a empresa já é lucrativa).

Quando uma grande empresa grande e poderosa resolve atacar no mesmo mercado e com um produto parecido com o seu significa que você, provavelmente, está com um bom projeto nas mãos! Essa concorrência deve ser encarada como uma validação positiva da sua idéia e não uma coisa para se lamentar. Eu sempre desconfio de empreendedores com idéias “que ninguém mais teve”.

Outro exemplo: nós, programadores, conhecemos os serviços de hosting de código Github e Bitbucket, certo? Eles são os mais famosos e o Github é o maior player nesse mercado. Quando o Github nasceu o Google já tinha o Google Code Hosting.

Mesmo assim colega resolveu criar um serviço desses e cobrar $9/mês para as pessoas usarem. Nasceu o Codeplane. O Codeplane nasceu porque ele tinha uma necessidade que não era atendida pelo Bitbucket/Github de forma satisfatória: ter dezenas de projetos pequenos para hospedar em repositórios privados.

O Github cobra por cada repositório privado, logo, o custo seria enorme. O Bitbucket, na época, limitava o número de repositórios privados em apenas 5 por usuário. No Codeplane não. Você poderia ter quantos repositórios privados precisasse. O único limite era o espaço de armazenamento total.

Ele criou um serviço útil para ele e para várias pessoas e ganhou dinheiro com isso. Independentemente dos “cachorros grandes” desse mercado.

Diferenciais

Uma coisa que é importante ter num mercado onde existe concorrência é o diferencial. O Google tinha como diferenciais a qualidade nos resultados das buscas e a velocidade com que elas eram feitas. O Codeplane tinha uma forma de cobrar diferente dos concorrentes. O DuckDuckGo também tem seus diferenciais.

O simples fato de ter um serviço adaptado para a realidade brasileira, por exemplo, pode criar um diferencial. Mas tenha em mente que esse diferencial pode ser pequeno demais para impedir seus concorrentes de atacarem seu mercado.

Copycats

Criar um produto similar à outro pré-existente e colocar alguns diferenciais nele é bacana. O “copycat” puro e simples não é.

O problema do copycat é que os seus clientes usarão o seu serviço até descobrirem o “original”. Se a empresa que fez o original for mais “poderosa”, provavelmente, terá condições de melhorar o produto deles num ritmo muito mais acelerado que o seu. Isso te deixaria para trás muito rápido na corrida pelo mercado.

Oceano Azul vs Oceano Vermelho

Existe um livro chamado “A Estratégia do Oceano Azul” (W. Chan Kim, Renee Mauborgne) que descreve o mercado como oceanos. Existe um oceano cheio de tubarões (concorrência) onde a briga entre eles é tão grande que tinge as águas de vermelho. E existem outros oceanos bem menos concorridos onde as águas ainda são azuis.

O objetivo de todos os empreendedores que estão começando deveria ser o de navegar por oceanos azuis. Com pouca concorrência. Para fazer isso o livro sugere que segmente o mercado de maneiras diferentes e ofereça valores também diferentes para esse mercado.

Analise os atributos de valor que os seus concorrentes oferecem para os clientes e tente realçar/eliminar alguns deles de modo a ter um produto único e diferente que sirva para pessoas que estão em mercados ainda inexplorados.

Global vs Local

Em vários artigos que falam sobre como começar um negócio você vai ler sobre “a necessidade de adaptar o produto para a realidade brasileira”. Não tem nada de errado com essa estratégia e ela pode até ser boa porque, inicialmente,  diminui os riscos do negócio.

Mas eu acho que devemos nos arriscar mais e parar com esse pensamento pequeno. Com a Internet e os negócios voltados para tecnologia o custo de iniciar certos serviços em escala nacional ou global é muito parecido. E, me perdoe pela obviedade, o mercado global é muito maior que o brasileiro.

Se a gente falar de um negócio que só adapta um que já existe em outro país a coisa fica ainda pior. Pode ser questão de (pouco) tempo para que a empresa global adapte o seu produto para a realidade brasileira e venha competir com você aqui no Brasil.

E aí será uma briga de uma empresa local contra uma empresa global. É bem mais difícil ganhar essa briga, não acham?

Categorias
Geral

Programador Freelancer

foto de um programador de costas trabalhando em seu notebook com um monitor externo. A foto está tratada para deixar toda a imagem exceto a tela do monitor externo em preto-e-branco.

Durante muito tempo da minha vida eu trabalhei como programador freelancer. Eu até tive empresa, sócio, etc. mas o fato é que eu era um freelancer como qualquer outro. Afinal eu vendia o serviço, elaborava proposta, negociava, executava o projeto, cobrava, emitia nota fiscal, e dava suporte. Durante esse tempo eu aprendi algumas coisas que gostaria de compartilhar.

Freelancing não escala

Trabalhar como freelancer é divertido e dificilmente enfrentamos problemas com a rotina quando trabalhamos desta forma. Não temos que lidar com a rotina porque cada projeto é único.

Essa variedade de projetos é legal mas tem algumas desvantagens. Como eles são razoavelmente diferentes fica difícil reaproveitar o conhecimento adquirido durante a execução de um deles.

Como o freelancer precisa aprender coisas novas em quase todos projeto perde-se boa parte do “ganho de escala” do negócio. E é o ganho de escala que permite reduzir custos que geram margens de ganho maiores ou preços menores para o cliente. Isso não é bom nem ruim. É uma característica inerente do trabalho do freelancer.

Se o freelancer opta por “crescer” o negócio e montar uma empresa com vários funcionários (ou freelancers) precisa observar que ele pode até ganhar escala mas esse ganho será praticamente linear: para fazer 1 projeto precisa de 1 pessoa e para fazer 2 projetos provavelmente precisará de 2 pessoas.

Você pode até mudar a inclinação do gráfico projetos x pessoas mas ele dificilmente se curvará.

Você vende horas? Cobre por horas

Uma armadilha bastante comum para freelancers iniciantes é a de negociar um contrato com um escopo fechado. A coisa piora se o escopo não estiver muito detalhado.

Essa armadilha é mortal porque na imensa maioria dos casos o contrato vincula o pagamento do serviço à entrega do escopo. E, acredite, os clientes vão expandir esse escopo ao ponto de tornar o projeto prejudicial para o freelancer.

Eu sei que é difícil negociar um contrato baseado em horas de trabalho mas você tem que negociar nesses termos. É melhor não pegar o projeto do que negociá-lo por escopo e/ou vincular o pagamento ao escopo.

Sei que isso é bem complicado porque as contas para pagar chegam todos os meses sem piedade e aquele contrato com escopo fechado oferece uma oportunidade de ter dinheiro para pagar essas contas. Mas no médio prazo você pode acabar se tornando um escravo do projeto e ficar trabalhando de graça nele (ou até pagando para trabalhar).

O melhor para você e para seu cliente é trabalhar com entregas parciais em intervalos curtos e rápidos. Isso nos leva ao próximo ponto…

Atualização: logo depois que enviei O Melhor da Internet o meu amigo Elvis enviou um link para um artigo que ele escreveu onde ele ressalta o fato de que um freelancer raramente consegue vender 100% das suas horas disponíveis.

Atualização 2: Depois que o artigo foi publicado me lembrei de uma outra dica importante relacionada à esse tópico. Quando você está elaborando a proposta e negociando o projeto é importante incluir o tempo usado nesse processo no valor final do projeto. Se você não fizer isso essas horas sairão “de graça” para seu cliente. Para isso funcionar direito as propostas também precisam ter um prazo de validade que permita uma revisão de valores nos casos onde a negociação demora muito.

Não cobre “50% no início e 50% na entrega”

É uma prática bem comum trabalhar dessa forma: o freelancer recebe 50% quando inicia o projeto e o restante quando entrega ele pronto.

Existem duas pegadinhas nesse modelo: uma é o conceito de pronto (veja o tópico anterior) e a outra tem relação com um negócio chamado fluxo de caixa.

Uma das coisas que certamente mata uma empresa é a má gestão do seu fluxo de caixa. E um freelancer é uma empresa de uma pessoa só. Precisa gerenciar seu fluxo de caixa com muita atenção.

Quando você fecha um negócio e recebe por ele 50%+50% fica mais difícil de gerenciar o fluxo de caixa da empresa porque a segunda metade do pagamento vira um alvo móvel. Quando você vai entregar o projeto? Quando ele estará “pronto”?

No lugar de negociar 50%+50% prefira receber parcelas em intervalos regulares (mensalmente? quinzenalmente?). Pode-se até vincular os pagamento às entregas parciais do projeto.

Receber pelo trabalho em intervalos regulares e vincular isso às entregas parciais é o cenário perfeito porque facilita a gestão do fluxo de caixa do freelancer e aumenta a segurança do cliente que pagará por algo que já recebeu.

“Produtize” seus serviços

No primeiro tópico eu falei sobre o problema de escala associado ao freelancing e aqui eu vou apresentar uma forma de amenizar esse problema.

É raro mas acontece: quando um freelancer está trabalhando no seu milésimo projeto ele percebe que certos padrões surgem em todos eles. Exemplo: quase todos os projetos tem um formulário de contato, ou uma página com um mapa mostrando a localização da loja do cliente, ou tem algum sistema de monitoramento, backup, etc.

Quando o freelancer detecta um padrão desses ele pode ter certeza que existe uma oportunidade de transformar essa parte do projeto em um produto que pode ser vendido para vários clientes. Se você fizer isso vai ter um ganho de escala ou até mesmo alguma receita recorrente.

Certos projetos também são genéricos ao ponto de poderem ser transformados em produtos (com a devida anuência do cliente contratante). Um exemplo? Um dos meus clientes solicitaram o desenvolvimento de um sistema de avaliação de funcionários para o RH da empresa.

O sistema usava uma metodologia conhecida como “Avaliação 360°” e gerava relatórios para o RH da empresa avaliar os seus funcionários. O sistema foi desenvolvido para um cliente específico mas, certamente, poderia ser útil para outras empresas. Não foi o caso mas esse projeto poderia ter se transformado em um produto.

Outros tipos de produtos que você pode criar estão na forma de conteúdo. Em meu caso, por exemplo, escrevi um livro e criei um video-curso de programação Python e Django para vender na Internet (que, por não manter mais, acabei disponibilizando gratuitamente).

Crie receitas recorrentes

Todo negócio tem seu risco e com o freelancing não poderia ser diferente. Quando o freelancer está trabalhando e vendendo suas horas de trabalho para alguém as coisas ficam bem. Mas quando, por algum problema, isso não acontece as coisas podem ficar bem complicadas.

Um freelancer pode adoecer, o mercado pode dar uma esfriada, pode acontecer uma entresafra de projetos (ex. o período de novembro a março costuma ser difícil para novos projetos).

Uma maneira de lidar com essas dificuldades é cuidar para poupar nos períodos fartos para ter algo nos períodos difíceis como na fábula da Cigarra e das Formigas. Outro modo de lidar com essa questão é criando formas de se obter receitas recorrentes.

Ofereça serviços de manutenção, suporte, apoio, etc para os clientes que desenvolveram projetos com você. Crie mecanismos (honestos) para continuar recebendo dinheiro deles mesmo depois que o projeto tenha terminado. Ou crie algum produto (tópico anterior) que seja vendido na modalidade de assinatura.

Recuse clientes ruins

Essa é uma das coisas mais difíceis de colocar em prática porque, a menos que alguém nos avise, é quase impossível saber se um cliente novo é bom ou ruim. Mas alguns indícios podem ser observados:

  • Cliente que questiona demais os preços – pode ser uma preocupação legítima mas geralmente não é. Mostra que é um cliente mais preocupado com preços do que com qualidade. Ele vai apertar os seus ganhos e vai te trocar por outro mais barato na primeira oportunidade.
  • Cliente que não sabe o que quer e não te ouve – existem muitos clientes que não sabem exatamente o que querem e isso isoladamente não é um problema. Mas se você tentar ajudá-lo a descobrir e ele recusar a sua ajuda isso pode virar um problema.
  • Cliente que descumpre o combinado – você estabelece com o cliente que ele te pagará mensalmente e no dia do pagamento você tem que ficar lembrando e cobrando. Ou cliente que simplesmente te dá um calote. Eu costumava fazer um teste: eu “esquecia” de cobrar os meus clientes algumas vezes. É engraçado mas os meus melhores clientes sempre me enviavam e-mail avisando sobre meu “esquecimento”.
  • Cliente que oferece uma “oportunidade única” de trabalhar para ele – tem muito cliente que pede um precinho camarada em um primeiro projeto com a promessa de valores maiores em projetos futuros. Não caia nessa armadilha porque esse cliente não é fiel à você. Ele é fiel ao teu preço baixo. E não se engane… tem muita empresa grande e famosa que usa o próprio nome para obter essas vantagens. Se usarem o discurso do “você vai colocar a nossa empresa no teu portifólio!” respondam de forma sarcástica: “eu já gastei a minha verba de marketing para esse ano”.

Para clientes pré-existentes é sempre importante gastar algumas horas do mês para reavaliar a sua carteira de clientes e projetos. Cliente bom é aquele que cumpre com suas obrigações, gera bons projetos, indica você para novos clientes e te dá um bom lucro.

Automatize as tarefas chatas

Coisas chatas que freelancers precisam fazer e precisam ser automatizadas o mais rápido possível:

Responder e-mails de sondagem

Eu recebia muitos e-mails assim: “Oi, Meu nome é Fulano e gostaria de saber quanto você cobraria por um projeto assim e assado”. Você tem que responder à esses e-mails mas 80% deles são de aventureiros. Pessoas que não tem dinheiro para te contratar, não sabem o que querem e não vão fechar negócio contigo.

O problema é que não dá pra você diferenciar as boas oportunidades daquelas que vão fazer você perder tempo.

Um das coisas que funcionou razoavelmente bem comigo foi colocar informações detalhadas sobre o tipo de projeto que eu desenvolvia e um valor aproximado para minha hora de trabalho no site da empresa. Colocava destaque na informação: “Esses valores são negociáveis”.

Com essas informações a pessoa já consegue ter uma idéia se ele consegue contratar o seu serviço. A outra informação (valores negociáveis) filtrava os aventureiros daqueles que realmente queriam realizar o projeto.

O cara pode até não ter o dinheiro para te contratar mas se ele quiser muito realizar o projeto ele vai entrar em contato contigo para tentar negociar o prazo de pagamento, os valores, o escopo, etc. E isso, por si só, mostra que ele pode ser um bom cliente e gerar negócios.

Algumas pessoas (por medo ou desconhecimento) acreditam que essas informações no site afugentam clientes. Pode ser que sim. Mas pergunte-se: “Que tipo de cliente eu estou afastando?”.

Produzir e enviar propostas

Depois que você entende melhor o projeto é o momento de enviar uma proposta para seu cliente.

Se você ainda estiver negociando projetos com escopo fechado fica impossível automatizar essa etapa porque cada proposta será única e precisará ser bem detalhada, mas se você negociar em termos de horas a proposta fica bem mais simples. Você precisa apenas preencher os milestones do projeto (entrego X na data Y, …) e fazer uma multiplicação de horas pelo teu valor/hora.

Eu tinha um template no meu editor de textos onde eu só alterava os dados, gerava um PDF, e enviava para o cliente. Se o cliente já era antigo, muitas vezes, eu só mandava um e-mail: “imagino que dê pra gente trabalhar nisso em uma semana por R$X”. E o cliente respondia: “Ok, pode fazer”. Esse é o tipo de relação de confiança que você precisa construir com seus clientes.

Cobrança e NFe.

Cobrar o cliente e ver se ele pagou é uma daquelas coisas que nunca consegui automatizar 100% mas cheguei à um ponto onde isso não atrapalhava o resto das atividades.

Eu criei uma conta de cobrança sem registro na conta da empresa no banco (dica: não misture sua conta pessoal com a conta usada para seu trabalho) e emitia boletos para meus clientes pagarem. Cerca de 5 dias depois da emissão dos boletos eu puxava um extrato e conciliava os pagamentos na mão. No site da prefeitura eu emitia as NFe daqueles que haviam pagado o boleto.

Comecei com um software que só emitia os boletos e depois migrei para outro que emitia os boletos e a NFe.

Seja parceiro dos bons clientes

É provável que você não consiga resolver todos os problemas de seus clientes e, nestes casos, você deve ajudá-lo a encontrar as soluções para esses problemas. Mesmo que para isso você tenha que encaminhá-lo para um outro prestador de serviços (freelancer, empresa, etc).

Se você fizer isso o cliente criará um modelo mental muito positivo sobre você: “quando eu tenho um problema é só eu entrar em contato com esse cara que ele resolve ou me ajuda a resolver”. Esse modelo mental é poderosíssimo para gerar novos negócios.

Cumpra combinados e faça com qualidade

Deveria ser o primeiro item mas resolvi deixá-lo para o final para que fique mais fresco na sua memória.

É da mais absoluta importância para um profissional que ele cumpra aquilo que foi combinado com o cliente. E mais do que isso… é importante que tudo seja feito com a maior qualidade.

Cumprir com o combinado manterá o seu cliente fiel à você. Fazer isso com qualidade transformará ele num canal de vendas.

Categorias
Geral

Trabalho Remoto

O programador, empresário e investidor Paul Graham publicou um artigo afirmando que as leis de imigração americanas impedem que talentos de outros países possam trabalhar nos EUA. Em resposta à esse artigo alguns programadores e empresários conhecidos sugeriram à ele que o trabalho remoto seria uma solução melhor para esse problema. Outros reforçaram a opinião do Paul Graham e começou aí a discussão.

Já faz quase 2 anos que trabalho remotamente para uma empresa de São Paulo a partir de Curitiba. Eu fui o segundo funcionário da empresa a ser contratado para trabalhar desse jeito. Hoje já temos 7 profissionais trabalhando assim.

Não vou mentir pra vocês: no começo foi bem complicado. Erramos de todas as formas e falhamos miseravelmente várias vezes até conseguirmos fazer as coisas funcionarem bem. Ainda está longe da perfeição mas a empresa, as equipes e os remotos estão se esforçando muito para melhorar.

Entre o caos e a situação em que estamos hoje houve um “turning point”. Um momento em que decidimos fazer a coisa funcionar.

Primeiro resolvemos estudar o assunto. Eu comprei livros e mais livros, assisti palestras e mais palestras, busquei referências em artigos, e refleti muito sobre nossos problemas.

O problema principal era a interação deficitária da equipe. Mesmo sendo uma equipe ágil que pratica SCRUM existiam muitos vícios na forma como os membros da equipe interagia. Era uma interação “olho-no-olho”, extremamente verbal (offline) e síncrona.

Essas três características são péssimas:

  • “Olho-no-Olho”: as reuniões diárias eram feitas com todos de pé (standup meeting) com todos os integrantes no escritório. Não preciso dizer que isso não rola para equipes remotas, certo?
  • Comunicação Verbal Offline: para uma equipe remota toda comunicação verbal já é deficitária (precisa de headset, conexão, ajustar o áudio, etc). A comunicação verbal “offline” é ainda pior. Eles decidiam coisas lá em SP e a gente nem ficava sabendo.
  • Comunicação Síncrona é aquela em que os intelocutores precisam estar “conectados” simultaneamente para transmitir a mensagem. Mesmo para trabalho local ela é ruim porque é uma comunicação que interrompe as pessoas. Exige a atenção delas. É o “cutucão no ombro”, o chamar no Skype, a “reuniãozinha rápida”, etc.

Enquanto ia refletindo sobre isso eu me lembrei sobre como foi trabalhar na Conectiva. A Conectiva foi o lugar onde trabalhei onde a comunicação da empresa era um exemplo de eficiência. Toda a comunicação da empresa funcionava pelos meios eletrônicos de forma extremamente eficaz:

  • Listas de Discussão (mailman com histórico online): toda a comunicação “séria” da empresa era feita por email em listas. Todos policiavam o bom uso do email e davam puxões de orelha em quem não usava do jeito certo. Existia uma hierarquia de listas (toda a empresa, equipe técnica, desenvolvimento, etc) e listas para coisas informais (off-topic). O email era para comunicação assíncrona e gerava longas threads muito bem escritas e organizadas onde se discutia quase tudo. Não era para preguiçosos porque exigia bastante esmero dos participantes.
  • IRC: a empresa tinha um servidor interno de IRC com salas organizadas também de forma hierárquica. Era usado majoritariamente pela equipe técnica (a parte administrativa da empresa usava ICQ… lembrem-se que era 2000). Aqui rolava a comunicação síncrona e a coordenação do trabalho.

Observem que não tinha nada de mais nas ferramentas. Mas elas eram usadas de forma correta e havia um policiamento por parte de todos para que isso não fosse desvirtuado.

Olhando pra isso é possível enxergar que a gente trabalhava “remotamente” no mesmo escritório. Não fazia diferença o local onde a gente estava. O trabalho aconteceria de qualquer forma porque tudo era comunicado o tempo todo pelos meios eletrônicos (salvo raras exceções e brincadeiras entre os integrantes da equipe).

Percebi que “tinha algo ali” mas guardei isso comigo.

Em 2013 a empresa onde trabalho mandou um ônibus para Brasília onde participaríamos da PythonBrasil[9]. Em Brasília tudo é “longe” e esse ônibus virou um transporte extra-oficial dos participantes do evento. Um dos convidados do ônibus foi o Sidnei da Silva e na época o Sidnei trabalhava remotamente para a Canonical. Uma grande oportunidade de aprender algo.

Entre as várias dicas que ele nos passou teve uma que me chamou a atenção: “a equipe tem que saber trabalhar remotamente mesmo que esteja no mesmo local”. Bingo!

Meu gerente (que também pesquisava o assunto) estava do meu lado quando o Sidnei disse isso e também percebeu a importância dessas palavras. Voltamos para o trabalho decididos a implantar esse sistema.

Não foi fácil mas conseguimos. Fizemos o seguinte:

  • “Forçamos” o uso de um headset para todos os integrantes da equipe (inclusive quem está no escritório);
  • As Dailys (usamos SCRUM) seriam feitas online (usamos o Mumble em um servidor próprio);
  • Movemos a maioria das conversas e discussões para os meios eletrônicos (isso diminuiu as interrupções causadas pelo “cutucão no ombro”);
  • Migramos todos os nossos whiteboards e post-its para o mundo virtual (usamos Scrumdo mas estamos avaliando alternativas melhores);
  • Usamos Slack e estamos adorando. Avaliamos e usamos outras (IRC próprio, Grove.io, Hipchat) mas o Slack detona;
  • Pareamos com tmate (temos um servidor pra isso) ou Teamviewer mas como a “fauna” de editores de texto e IDEs na empresa é abundante estamos sempre procurando algo melhor. E o Google Hangout é uma bosta. Nem adianta recomendar ele pra gente 😀 (Floobits?);
  • Já usávamos Github mas passamos a aproveitar melhor o sistema.

Tudo isso foi legal e bacana mas o que realmente foi importante nessa mudança foi o compromisso de cada um para que o trabalho desse certo. Começamos a nos policiar e “brigar” para que as coisas funcionassem do jeito certo.

Daily Meeting acontecendo no escritório

Foi importante mostrar para a equipe de SP que, se isso desse certo, eles também poderiam se beneficiar. Poderiam escolher entre ficar em casa ou encarar o trânsito de SP, por exemplo. Alguns poderiam até trabalhar mochilando!

Para a empresa? Só sucesso… ela consegue contratar os melhores funcionários mesmo que eles não queiram morar em SP. Conseguem economizar com infra-estrutura e com folha de pagamento (um salário bom em SP é excelente no interior de SC).

Quando eu era empresário sonhava em ter um escritório bacana cheio de gente foda trabalhando comigo. Hoje sou um defensor ferrenho do trabalho remoto. Acho que os governos deveriam incentivar essa forma de trabalho até mesmo como forma de melhorar o trânsito das grandes cidades.

Categorias
Geral

Livros para programadores

Episódio 1

foto com uma estante lotada de livros não identificáveis
Foto: Yinghai

Os amigos que me conhecem sabem que adoro livros. Para o desespero da minha mulher e das finanças da casa tenho o mal hábito de comprar muito mais livros do que consigo ler.

Recentemente isso ficou pior porque comprei um leitor eletrônico que permite comprar coisas com um toque na tela. Pelo menos o problema com o espaço para os livros foi resolvido.

Programo computadores desde muito cedo mas nunca tive muito estudo formal sobre o assunto (não sou graduado) então sempre dependi dos amigos mais inteligentes e dos livros para aprender as coisas. Alguns foram bem importantes pra mim e esses eu vou listar aqui.

Os meus caminhos de aprendizado sempre foram tortuosos e fragmentados então a lista não tem nenhuma sequência que precise ser seguida. Estão na ordem como fui lembrando deles.

Os livros com links são os que ainda podem ser adquiridos pela internet e que eu ainda recomendo a aquisição por não estarem defasados.

Se você tem sugestões de livros que foram importantes para você, escreva nos comentários.

Revistas de Eletrônica

Ok, não são livros mas foram importantes para mim. Antes de programar eu brincava de montar circuitos eletrônicos. Como eu era muito novo (uns 9 anos) não me lembro de muitos detalhes de todas as revistas mas algumas foram especiais:

  • Experiências e Brincadeiras com Eletrônica Júnior – gostava tanto dela que ganhei uma assinatura do meu pai. Era publicada pela editora Saber e tinha projetos mais simples e menos “sérios”. Adequado para crianças.
  • Be-a-Bá da Eletrônica – Era formatada como mini-cursos e cada edição abordava um tópico específico. Trazia uma placa de circuito impresso para fazer a montagem do circuito principal.

Infelizmente nenhuma das duas é publicada mais. Acho que a revista que chega mais próximo delas é a Eletrônica Total da Editora Saber.

Aprendizado Inicial

Quando eu comecei a aprender a programar as únicas fontes de informação que eu tinha eram os 2 livros que acompanhavam meu computador e a revista Micro Sistemas. Numa segunda fase, também de aprendizado inicial, passei a estudar mais a fundo o universo dos IBM PCs e do MS-DOS.

Livros

manuais-msx
  • Basic MSX – da editora Aleph e editado pelo famoso Prof. Pier (Pierluigi Piazzi). Era uma referência com os comandos e funções da linguagem Basic que acompanhava meu computador.
  • Dominando o Expert – também da editora Aleph e editado pelo Prof. Pier. Era um curso introdutório de informática usando Basic. Foi com esse livro que digitei meus primeiros comandos num computador.
  • Clipper Summer’87 Cartão de Referência (Rubens Prates) – não é bem um livro mas aprendi o básico de Clipper.
  • Clipper Summer’87 vol. 1 e 2 (Antonio Geraldo da Rocha Vidal) – com esses livros aprendi a desenvolver aplicativos comerciais e, a partir desse ponto, passei a trabalhar com programação. Tinha 12 anos.
  • Algoritmos e Estrutura de Dados (Niklaus Wirth) – apesar do livro não usar Pascal nos exemplos de código eu conseguia facilmente adaptar o código para Pascal (do Turbo Pascal 4 até o Turbo Pascal 7). Foi quando aprendi a programar em Pascal. Na minha opinião, hoje, existem livros melhores sobre estruturas de dados e algorítmos.
  • C Completo e Total (Herbert Schildt) – eu aprendi a programar em C “sozinho” mas sonhava em comprar esse livro. Como não tinha dinheiro eu lembro de ir até a livraria para ler ele. Só depois de velho consegui verba pra comprar uma cópia dele pra mim.
  • MS-DOS Avançado (Ray Duncan) – livro que ensinava desenvolvimento de software para DOS em Assembly e C.

Como vocês notaram o meu aprendizado era focado mais em novas linguagens de programação e em programação “baixo nível” (única exceção foi o Clipper que usava para “pagar as contas”).

Revistas

microsistemas
  • Micro Sistemas – “A primeira revista brasileira de microcomputadores” era o subtítulo dessa revista. Ela vinha com reportagens e listagens de programas enviados pelos leitores (publicaram um artigo meu).
  • CPU MSX – Comprava algumas edições dessa revista também. Também tinha artigos interessantes sobre jogos e programação mais avançada (muito tempo digitando as listagens com códigos hexadecimais dos programas em linguagem de máquina).
  • INPUT – Coloquei em Revistas porque ela vinha em fascículos mas, depois de encadernadas, produziam 5 volumes enciclopédicos. Essa coleção, até hoje, é uma referência para questões didáticas. Sempre que preciso explicar alguma coisa para alguém recorro à essa coleção para ver qual a abordagem que eles usaram.
  • Microcomputador Curso Básico – 2 volumes da editora Globo (ou Rio Gráfica). Folheava tanto esses livros que eles acabaram gastos. Gostava da seção Raio X onde eles tiravam fotos de vários computadores abertos e apresentavam a ficha técnica deles. Ficava imaginando o dia que poderia ganhar alguns deles 🙂

Fase Unix/Linux

Eu me divertia horrores programando para essas máquinas com “tela preta”. Vocês não imaginam a minha tristeza quando todo mundo começou a usar interfaces gráficas (Windows).

A coisa legal é que, bem nessa época, eu fui até uma feira em São Paulo (Fenasoft) onde vi um troço chamado Unix. Era uma estação da Silicon Graphics no estande da Globo. Ela tinha interface gráfica mas você ainda tinha que digitar comandos num terminal texto para operá-la. Provavelmente era um Irix.

Como eu tinha um PC/Intel em casa eu não conseguiria rodar esses Unix que vi na feira e comprar uma máquina daquelas… fora de cogitação. Fiquei com aquilo martelando na minha cabeça até começar o meu estágio e operar um 386 com SCO Unix (e um outro com Xenix).

Vi que existiam Unix para PC/Intel mas todos eram caríssimos (não rolava piratear porque não davam acesso aos disquetes originais para um reles estagiário).

Quando reclamei sobre isso com um amigo que estudava computação no Ibilce ele mencionou um tal de Linux. Pedi para um “cara” na cidade que tinha internet rápida e um gravador de CDs gravar um CD com Linux pra mim e assim ele o fez. Era um Slackware.

Decidi aprender a usar aquilo e, para isso, precisava instalar mais um SO no meu computador que já tinha MS-DOS, Novell DOS 7, OS/2 (usado na minha BBS) e Windows 95/98.

Me dediquei com afinco (precisou porque apanhei muito) até aprender bem a usar aquilo.

Mas a coisa ficou séria mesmo quando, por uma dessas pegadinhas do destino, eu comecei a trabalhar na equipe de desenvolvimento do Conectiva Linux em Curitiba.

Quem me ajudou mesmo foram os colegas de trabalho… Mas alguns livros que li na Conectiva e, posteriormente, nos diversos outros lugares em que trabalhei ajudaram muito também.

Livros

  • Aprenda em 24 Horas Unix (Dave Taylor) – sério. Muita gente tem preconceito contra esse tipo de livro mas para um cara que já conhece várias coisas e precisa aprender a “se virar” com uma tecnologia nova eles são ótimos. É um livro para iniciar e te dar referências para aprofundar os estudos.
  • Maximum RPM (Edward C Bailey) – não é um livro sobre programação (fala sobre fazer pacotes RPM para RedHat) mas foi um divisor de águas. Nem é um livro bom mas aprendi a fazer build de vários software (e entender o ./configure; make; make install). Além disso ele é em inglês e, digamos, eu não lia nada em inglês na época. Precisava aprender a fazer pacotes RPM se quisesse garantir meu emprego na Conectiva. E garanti.
  • Expressões Regulares Uma abordagem divertida (Aurélio Jargas) – o Aurélio era meu colega de trabalho e aprendi Expressões Regulares com ele pessoalmente e não com o livro. Mas tudo que ele me ensinou está no livro também, logo, vou colocar ele nessa listagem. É impressionante a didática dele para ensinar um assunto tão complicado.
  • Shell Script Profissional (Aurélio Jargas) – o mesmo caso aqui. Eu não li o livro mas boa parte do que sei sobre programação shell eu aprendi com o Aurélio. O conteúdo que ele me passou está todo aí.
  • Instant Python (Magnus Lie Hetland) – ok, é só um artigo sobre Python e não um livro. Mas esse artigo (traduzido pelo meu chefe) me apresentou a linguagem Python e, desde então, essa tem sido a minha principal ferramenta de trabalho. Mesmo tendo aprendido novas linguagens e trabalhado com outras sempre volto a trabalhar com Python. Dá pra acreditar que aprendi Python com esse artigo?

Fase OOP – Object Oriented  Programming

Depois que saí da Conectiva tive um breve período como sysadmin em uma empresa e desenvolvia mais scripts do que aplicações “de verdade”.

Mas depois desse emprego circulei por diversos outros onde, de fato, voltei a programar computadores mais seriamente.

Como a maioria desses trabalhos usavam linguagens com paradigma orientado a objetos acabei focando em livros que tratem esse tipo de assunto.

  • Fundamentos do Desenho Orientado a Objetos com UML (Meilir Page-Jones) – esse livro foi responsável pela minha “iluminação” com relação ao desenho orientado a objetos. Até então eu só tinha feito código procedural (mesmo em Python!) porque não entendia muito sobre o OOP. O livro usa UML para ilustrar os assuntos mas ele usa UML como deve ser usada: apenas para ilustrar algum conceito. Nada do pedantismo da UML e seus vários tipos de gráficos. Infelizmente a versão traduzida desse livro saiu de circulação mas ainda é possível encontrar o original em inglês.
  • Padrões de Projeto ou Design Patterns (GoF) – a primeira parte desse livro é importante e tem várias idéias importantes para qualquer programador que queira usar OOP. A segunda parte é mais para referência mas tem alguns patterns bacanas.
  •  eXtreme Programming Explained (Kent Beck) – livro que me apresentou o conceito de programação “ágil”, testes automatizados, refatoração, etc. Não tem código mas os conceitos são extremamente poderosos. E o Kent Beck é um excelente autor. Tem uma capacidade invejável de explicar qualquer coisa de forma simples. Esse livro teve uma tradução muito boa mas parece ter saído de circulação.
  • Refactoring (Martin Fowler) – livro elabora melhor a idéia de refatoração citada no livro de XP do Kent Beck. O capítulo sobre “Bad Smells” (Mal cheiros) foi escrito pelo Kent Beck e é uma das melhores partes do livro. Esse livro teve uma tradução muito boa mas parece ter saído de circulação.
  • Pragmatic Programmer (David Thomas & Andrew Hunt) – ganhei esse livro de um amigo e, pra mim, ele é fundamental. Todo programador deveria ler. Fala sobre um monte de coisas. De ética à teste automatizado. De técnicas de depuração à linguagens de programação.
  • Code Complete 2nd ed. (Steve McConnell) – esse livro fala sobre assuntos muito similares aos que você encontrará no Pragmatic Programmer. A diferença é que neste livro ele usa uma abordagem menos “pragmática/ágil” e se aprofunda mais nos assuntos. É um livro bem mais denso. Li a versão original mas já existe tradução.
  • Test-Driven Development by Example (Kent Beck) – eu já tinha lido sobre TDD no livro de XP do Kent Beck mas não tinha a menor idéia do que ele estava falando. Já nesse livro aqui eu consegui compreender a mecânica da coisa. O Kent Beck tem o dom de escrever as coisas de forma simples e objetiva. Vale a pena. Li a versão em inglês mas já existe uma tradução.
  • Advanced Programming in the UNIX Environment (Richard Stevens) – esse livro não era meu e nem cheguei a ler ele inteiro. Para ser honesto eu li uns 2 ou 3 capítulos apenas. Mesmo assim tudo o que eu sei sobre sockets e sobre chamadas como fork/exec do Unix eu aprendi nesse livro. Esse tipo de conhecimento é superimportante para programadores e existem diversos livros que tratam dele. Esse do Stevens é o que mais me ajudou.
  • Introduction to Algorithms (Cormen, Leiserson, Rivest, Stein) – obviamente não li esse livro inteiro. Mas foi o livro que me ensinou o significado da notação big-O para eficiência de algoritmos. Ele ensina a calcular mas confesso que foi além da minha capacidade intelectual. O restante do livro pode ser lido mas me parece mais adequado para consulta e referência. Ele lista diversos tipos de algoritmos. Existe tradução.

Conclusão

Depois desses livros eu comecei a me interessar por outros assuntos voltados ao empreendedorismo que também foram muito importantes. Mas vou deixar isso para outro artigo.

Categorias
Geral

Negócios na “internet fechada”

placa na fachada de uma loja com os dizeres "internet open"
Foto: Blaise Alleyne

Já faz algum tempo que acompanho o desenvolvimento de novos negócios de tecnologia ao redor no mundo. Por conta disso participei e participo de vários eventos dessa área no Brasil. Eventos onde empreendedores apresentam suas idéias, fazem seus pitches, demonstram seus produtos e buscam melhorar o seu relacionamento com outros empresários, investidores e até mesmo com seus clientes.

Nessas apresentações eu já vi todo tipo de negócio na área de tecnologia. Negócios que funcionam nos mais diversos tipos de plataformas. As plataformas mais comuns são a Web e a Mobile.

Quando um empreendedor começa a desenhar o seu modelo de negócio ele precisa pensar em diversas coisas e nesse processo ele eventualmente se coloca em uma armadilha que dei o nome de “internet fechada”. Já explico o que isso significa.

Todo mundo sabe que a internet é uma rede aberta, com padrões e protocolos abertos. Essa abertura da internet permite que você faça o que bem entender com ela (desde que não seja ilegal) sem se preocupar com nada. Na internet aberta ninguém tem poder de te censurar sem motivo razoável.

Mas existem plataformas dentro da própria Web onde existem regras mais rígidas que mudam frequentemente.

Se o empreendedor baseia toda a sua estratégia de negócio e desenvolve uma aplicação Web para o Facebook, por exemplo, ele fica sujeito às regras do Facebook. E no Facebook eles mudam essas regras o tempo todo.

O risco do Facebook inviabilizar o negócio desse empreendedor é muito alto. O empresário está lá trabalhando para aumentar a sua empresa e num dia de manhã, quando abre a sua Inbox, dá de cara com uma “Alteração nos Termos de Serviço”. Nessa alteração o Facebook proíbe ele de fazer algo essencial para atender os seus clientes.

O impacto dessa mudança nos Termos de Serviço pode até não ser fatal mas certamente vai dificultar muito as coisas para esse empresário.

Outra característica das plataformas fechadas é a de que os clientes nunca serão 100% do empresário em questão. Os clientes são da tal plataforma. Ou você acha que o Facebook vai te entregar os usuários deles?

Quando eu conversava sobre esse assunto com um amigo que desenvolve Apps para celular ele me perguntou se o mesmo não acontece nas lojas de aplicativos? Ele citou dois problemas principais: as regras mudarem de forma a impedir que sua App seja vendida na loja e o caso onde a fabricante da plataforma (ex. Android ou iOS) fornece uma App parecida com a sua integrada no aparelho.

No primeiro caso o problema é bem parecido com o da internet fechada. O segundo não.

A Apple é bem conhecida por suas mudanças de regras que levam empresas inteiras a passarem por dificuldades. Apps que promoviam outras Apps sofreram muitas restrições de funcionamento. Outras que vendiam livros, música, filmes, etc… sofreram barbaridade com a proibição de vendas a partir da App.

Pense nos empresários que investiram alto para criar esses produtos e acordaram um dia sem nada. Se a App estiver disponível para Android a coisa fica menos pior mas o impacto vai ser grande mesmo assim. No mundo do Google/Android a coisa é um pouco mais tranquila mas o risco está lá.

O segundo caso, quando uma a fabricante lança uma App similar já integrada com o SO, é diferente porque ela não proíbe você de negociar sua App.

Para resolver esse problema é só o empresário fazer a App dele ser preferida pelos seus clientes. A Apple tem o iMessage nem por isso o WhatsApp sofreu. As coisas ficam mais difíceis mas não impossíveis.

Portanto, a dica que fica para os futuros empreendedores é: não amarre o seu “core business” à internet fechada.

Integre sua aplicação com o Facebook, Twitter, etc. sem problemas. Mas faça isso de um modo onde seja possível trabalhar também de forma desacoplada: na internet aberta.

Categorias
Geral

“Ondas” tecnológicas

foto monocromática verde-preto de uma onda no mar

Já é de conhecimento de todos que trabalho com computação já faz muito tempo. Vi muitas ondas passarem.

Quando comecei com BASIC em máquinas de 8bits vi a primeira onda chegar… eram as linguagens estruturadas. Linguagens “procedurais”… código sem GOTO, etc. Quem programava só em BASIC e não conhecia esse “novo paradigma” (aspas propositais) estava fadado ao fracasso e ao ostracismo. Não mereceriam ser chamados de programadores.

Parti para a luta e fui aprender Pascal, C e/ou Clipper.

Ondas tecnológicas

Assim que dominei esse “novo paradigma” avistei outra “nova onda”: Programação Orientada a Objetos.

Essa foi uma das primeiras grandes ondas que contaram com apoio de Marketing de grandes empresas. Lembro-me de ler sobre “orientação a objetos” até em jornais de bairro (hipérbole detectada!). E mais uma vez fui convencido de que se não dominasse esse “novo paradigma” eu estaria fadado ao esquecimento.

Então comecei a estudar o assunto e no meu entendimento inicial (e duradouro) uma “classe” nada mais era do que um “struct” (ou RECORD) com esteróides. Ainda existem registros da minha primeira incursão nesse novo mundo. Eu só fui entender melhor OOP recentemente.

Outra onda que “bombou” mais ou menos na mesma época era a dos bancos de dados relacionais (SQL e afins). Mas eu não tinha muito contato com esse mundo que era restrito às “elite$”.

E com OOP e SQL essas empresas de marketing que, eventualmente, produziam software começaram a ganhar rios de dinheiro vendendo “gelo para esquimó”.

A tecnologia dos computadores surgiu para empresários em mensagens como: “Se sua empresa não usar OOP ou SQL você (perderá dinheiro|será devorado pela concorrência|será feio e bobo).” — (IBM|Gartner|Oracle)

Os empresários eram completamente ignorantes sobre esses assuntos e, num ato de fé, acreditavam em tudo o que as “IBMs” diziam. Afinal elas ficaram grandes e ricas por lidar com tecnologia, certo? Conseguem detectar a falha primordial nesse raciocínio?

Esse tipo de mensagem juntamente com a outra que dizia: “ninguém é demitido por ter escolhido IBM” fez muito bem para o lucro dessas empresas.

Naquela época isso fazia sentido, afinal, os computadores não faziam parte da vida de todo mundo. Tecnologia e mágica eram sinônimos. Mas hoje isso não deveria mais ser assim. A fábrica de “hypes” continua funcionando e os empresários e profissionais da área continuam investindo em tecnologias “da moda” apenas por estarem na moda.

Outras “ondas” movimentaram e ainda movimentam o mercado e com certeza não lembrei de todas: OpenSource, Java (J2EE), XML, NoSQL, Cloud, metodologias de desenvolvimento (ágeis ou não), Big Data, Internet of Things, Frontend/Backend engineering, etc.

Para cada uma delas temos defensores (não é uma onda! é realidade! olha só isso aqui!) e detratores (isso é hype! isso não funciona!). Ambos estão certos e errados.

Meus amigos devem estar pensando: “Mas ele é o cara que mais compra esses hypes! Andava com uma camiseta ‘você ainda usa banco de dados?’!”.

Eu, de fato, acompanho todas essas ondas. Cada uma delas acrescenta algo na minha caixa de ferramentas. Sempre que vejo uma delas chegando já vou logo dando uma chance pra elas se provarem úteis. Mas isso não significa que vou adotá-las em tudo o que farei e que as coisas antigas são lixo.

É o velho clichê: existem ferramentas certas para resolver cada tipo de problema.

Resolvi escrever isso pra que vocês possam refletir sobre a adoção racional de tecnologias. Usar critérios técnicos para a escolha e não ficar pegando jacaré em qualquer onda que aparece.

Outra coisa importante é não parecer bobo falando que você faz “Big Data” pra um cara que já processava toneladas de dados antes mesmo de terem cunhado essa expressão. Ou falar que usa NoSQL pra um cara que já usava Caché (kind of OODBMS), LDAP (hierárquico), ou Isis (schemaless).

Como vivi todas essas ondas eu saco logo que esses caras são mais “gogó” do que outra coisa.

Mantenham o foco em criar coisas boas que resolvam problemas importantes e escolham tecnologia usando critérios técnicos.

Ser proficiente numa linguagem é um critério muito importante mas ele deve ser considerado em conjunto com outros critérios (robustes, disponibilidade de recursos, etc).

Dia desses vi um anúncio procurando programador Clipper e pensei: esse contratante deve ter um excelente software. Deve ser um software tão bom e deve resolver problemas tão importantes que ele resistiu à várias ondas e não virou areia.

Categorias
Geral

Code Review e a Teoria das Janelas Quebradas

foto de uma janela bem antiga e degradada com um vidro quebrado por uma pedra do lado esquerdo inferior da janela.
Foto: Jeffrey Pott

Na empresa onde trabalho temos o (bom) hábito de fazer Code Review no código dos projetos que desenvolvemos. A prática não é obrigatória mas todos os desenvolvedores gostam de ter seu código revisado.

Eu adoro revisar código alheio tanto quanto gosto de ver meu código revisado e, por isso, me esforço para dar pitaco em quase todos os projetos da empresa. Até em projetos de outras equipes.

Eventualmente eu entro em longas discussões com os outros programadores para que eles renomeiem variáveis ou até mesmo para que coloquem/retirem espaços em branco que violam o Coding Style da empresa. Como usamos Python nos nossos projetos, adotamos a PEP-8 com apenas uma ressalva relativa ao número de colunas por linha que acaba estabelecida apenas pelo bom senso de cada programador.

E eu sou muito chato com isso. Eu realmente implico com qualquer coisa que não me pareça certa. Não importam se são problemas críticos ou triviais: recebem a mesma atenção.

Existe uma teoria que afirma que as janelas quebradas de edifícios em uma região da cidade tem relação direta com a criminalidade nesta mesma região.

Eu acredito nessa teoria e, por isso, sou exigente nas minhas revisões. Faço isso porque acredito que um mero relaxo numa linha em branco dentro do arquivo pode evoluir para um desenho ruim de um módulo inteiro da aplicação.

Ok, admito, isso pode parecer exagero mas… e se não for? E se a teoria das janelas quebradas se aplica também no contexto do código fonte de uma aplicação?

Esse tipo de cuidado é ainda mais importante quando trabalhamos com linguagens de programação com tipagens dinâmica ou fraca, pois certas convenções de nomenclatura podem dizer muito sobre os tipos envolvidos em uma operação. Exemplo?

Uma função chamada get_user() retorna que tipo de objeto? Eu presumo que seja uma instância de um objeto representando um usuário (ex. User). Mas só consigo presumir isso pelo nome da função (ou me dando ao trabalho de ler e entender a sua implementação).

E a função get_users(), o que retorna? Presumo que seja uma coleção (collection) de objetos representando usuários, certo? Se o desenvolvedor descuidar dessas e de outras convenções o trabalho ficará bem mais complicado para os outros membros da equipe.

Certa vez eu encontrei um código que fazia algo parecido com isso:

user = self._get_user_from_credentials(request)

Conseguem perceber o que está errado? O método diz que retorna um usuário a partir de suas credenciais (ex. username, senha, …) e enviamos para ele um objeto do tipo Request? Pedi para corrigir o problema de uma das duas formas:

  1. passando as credenciais do usuário para o método ou;
  2. renomeando o método.

Optaram por renomear o método e o código ficou assim:

user = self._get_user_from_request(request)

Note que é um método protegido (em Python o prefixo ‘_’ é usado para informar que o método em questão não deve ser chamado externamente) e, por isso, não seria um problema muito grave manter o nome antigo. Mas mantendo como estava deixariamos uma janela quebrada em nosso código.