Depois eu leio

Alias para rebase

Resolver conflitos durante um rebase é um processo que pode ser bastante repetitivo, por isso, normalmente utilizo estes dois alias no .gitconfig para ajudar:

[alias]
next = "!git add . && git rebase --continue"
conflict = "!f() { git ls-files --unmerged | cut -f2 | sort -u ; }; mate `f`"

O "mate" ali no final é para abrir os arquivos em conflito no TextMate, substitua pelo seu editor favorito. Então minha rotina de rebase fica assim:

1. Sincronizando o master
[rogerio] ~/projects/spikes/post_rebase (master)
$ git pull

2. Iniciando rebase
[rogerio] ~/projects/spikes/post_rebase (feature_xpto)
$ git rebase master

4. Conflitos: utilizar o alias para abrir simultaneamente todos os conflitos no seu editor favorito
[rogerio] ~/projects/spikes/post_rebase ((babd371...)|REBASE)
$ git conflict

4. Após resolver os conflitos, aplicar o patch e continuar
[rogerio] ~/projects/spikes/post_rebase ((babd371...)|REBASE)
$ git next

Também é possível configurar o Git para utilizar alguma ferramenta visual para resolução de conflitos, como o DiffMerge, Kdiff3 ou Meld, mas eu pessoalmente prefiro o jeito old school mesmo. Mais informações aqui.

No comments

Dica rápida: atualizando um arquivo a partir de outro branch ou revisão (GIT)

Para puxar um arquivo específico de algum outro branch ou versão, pode-se usar o seguinte comando:

git show [repositório]/[branch]:[path do arquivo] > [path para escrever no arquivo local]

Exemplos:

Puxando do branch onde o Zezinho já consertou o arquivo

Supondo que por algum motivo ele ainda não possa integrar ao master, você pode sincronizar apenas o arquivo que interessa direto do branch dele (lembre-se de fazer o git fetch antes):

git show origin/fix_js:public/javascripts/arquivo.js > public/javascripts/arquivo.js

Rollback para uma revisão específica

- git show HEAD~3:public/javascripts/arquivo.js > public/javascripts/arquivo.js

No comments

Software fora de empresas de tecnologia

Trabalhar com software numa empresa cujo core business "não" é software, é um grande desafio. Já até ouvi de um colega de área que respeito bastante, que são lugares tristes para um desenvolvedor trabalhar. Realmente, ser tratado como "recurso" ou fazer parte do departamento que é "apenas custo", demonstra que o ambiente ainda tem muito o que amadurecer até se tornar verdadeiramente produtivo.

Por outro lado, é uma grande oportunidade atuar no cenário de uma empresa alheia aos processos mágicos ou tecnologias fantásticas da vez, que estão sempre nas modinhas do mundo de TI. Desenvolver um sistema de qualidade e levar a equipe a um bom nível de maturidade depende apenas da sua bagagem. Não há imposições quanto a esta ou aquela plataforma, não há processos jurássicos no meio do caminho nem submundo de disputa política entre departamentos ou programadores estrela. Mas então porque será que apesar da liberdade de atuação, implantar Scrum num ambiente destes é uma missão surreal?

Com o foco todo dedicado ao core business, a competição pela atenção dos POs no dia-a-dia dos sprints é uma causa perdida: "PO sempre presente" é lenda, horários de reunião nunca são respeitados, backlog fraco, pedidos "pra ontem" quebrando o sprint... pior que isso só em fábricas de software.

Mas antes de continuar, vamos olhar a situação pelo ponto de vista de um empresário comum. Você está lá tocando a sua loja, organizando eventos ou cuidando de um laboratório e, de repente, brotam meia dúzia de computadores e uma gente esquisita que não cumpre horário comercial começa a pedir que você explique tudo do seu negócio. O primeiro resultado são bonequinhos de palito no quadro branco e post-its coloridos enfeitando a parede, por uma pequena fortuna mensal.

Depois de uma semana (sendo muito otimista), aparecem para lhe mostrar uma tela com meia dúzia de botões que você tem certeza que seu sobrinho que "também mexe com computador" conseguiria fazer por 3 jogos de PS2 comprados no camelô. Como conseguir a colaboração genuína de alguém que só quer que as coisas se resolvam, rapidamente e sem o menor esforço para entender o valor e o background do que está comprando?

Você quer ver a mágica sem aprender o truque

Falando a partir do meu senso comum, creio em três níveis de compromisso. No primeiro, você precisa de algo mas não dá a menor importância para entender como aquilo funciona. Por exemplo, eu quero que meu carro sempre funcione, então sigo as manutenções recomendadas. Mas se quebrar, eu só quero saber quanto custa pra arrumar e quando fica pronto, e meu critério pra escolher um mecânico vai ser na base do orçamento e indicação. Neste nível eu não estou nem aí pra qual era o problema, não gosto de mecânica e não quero entender nada disso - apesar de depender do veículo diariamente.

Você tem curiosidade de descobrir o truque

No segundo nível de compromisso, as pessoas têm algum interesse em ficar boas no assunto em questão. Geralmente é aí que estão os hobbys, o estudo em áreas fora do campo de trabalho ou a prática de esportes, por exemplo. Precisa gostar e treinar muito pra ficar bom de guitarra ou não espatifar um aeromodelo veloz, mas se você quer tocar como o Joe Satriani ou abrir uma loja de modelismo, então faz parte do próximo e último nível de compromisso.

Você quer ser o mágico

E neste último nível, só entra o que é realmente a sua praia, aquilo que você consegue manter o interesse pelo tempo necessário para ficar realmente bom e fazer disso o seu ganha pão. Há um estudo que chegou no número de dez mil horas pra ficar mestre em algo, mas mestre ou não, geralmente é nessa área que você se diverte e consegue usar seu melhor potencial criativo onde outros têm dificuldade.

Voltando ao problema

Quem não é geek gosta de computadores tanto quanto eu gosto de carros, ou seja, só quer ligar e sair usando. O problema é que software não é como um carro, onde você compra um dentre um número bem limitado de marcas e modelos disponíveis e todos resolvem o problema da locomoção de forma extremamente parecida. Pouquíssimos softwares têm o mérito de estar a esquerda do 80/20, e por isso mesmo podem ser comprados numa prateleira. Basicamente são jogos ou sistemas para o cotidiano de escritórios e usuários não geeks.

O próprio mercado explica porque isso acontece: apesar de cada área de negócios ter um padrão bem definido, cada empresa busca atuar no seu ramo de um jeito que a diferencie das outras. E é daí que brotam os departamentos de TI e consultorias de três letrinhas: especialistas em reinventar a roda diariamente, fazendo e refazendo sistemas que resolvem os problemas de uma determinada área do conhecimento, porém, sob a ótica de uma empresa específica e contrato de confidencialidade.

Isto (e mais tantos outros motivos) invalida qualquer tentativa de tratar software como linha de produção. Software é artesanal (até os de prateleira), e para que os artistas expressem em seu código e usabilidade o espírito da empresa para a qual venderam a alma, digo, para a qual estão trabalhando, o desafio para o time de TI "estranho no ninho" é trazer os empreendedores - ou POs (Product Owners) - do nível 1 de interesse para o nível 2.

Ciclos de entrega curtos são uma das chaves para garantir que o sistema está resolvendo satisfatoriamente as necessidades dos interessados. Por isso o artigo começou falando de Scrum, seus ciclos curtos, bom suporte para comunicação eficaz e simplicidade somados a ênfase em pessoas sobre processos (do manifesto) ajudam bastante a fazer as pontes para os POs participarem cada vez mais da ilha de TI. Mas o Scrum, por si só, não resolve nada e é aí que o artigo acabaria no "surreal" do segundo parágrafo.

Na verdade, nenhum processo é capaz de resolver o problema do nível de compromisso. Sozinhos, processos apenas tornam centros de custo toleráveis como um cunhado que pede dinheiro emprestado. É na cultura da empresa que devemos cativar o nível de compromisso e qualidade que buscamos, pois o próprio Scrum sem a cultura do manifesto ágil é tão fraco quanto qualquer outro processo e falha na mesma proporção.

A literatura clássica diria que é hora de mapear os stakeholders e fazer o planejamento da comunicação. Eu gosto da teoria sobre o mapa de poder, legitimidade e urgência, mas como não estamos falando de guerra fria, prefiro pensar que existem contadores de histórias adormecidos.

Poder, legitimidade e urgência - Mitchell, Agle, Wood (1997)

Mitchell, Agle, Wood (1997)

POs rebeldes não têm a obrigação de entender de sistemas, mas são os únicos capazes de explicar como as coisas funcionam de um jeito que nós de TI, conseguimos entender como elas poderiam ser mais simples. Perceber que estão substituindo n planilhas em excel, x formulários e y horas de ligações telefônicas diárias por um sistema que tornará vários de seus processos instantâneos, facilmente auditáveis e principalmente, mais simples, transforma os donos do negócio em verdadeiros "contadores de causo".

Com os POs no nível 2 de interesse, um gerente que fez a lição de casa sobre agile (idealmente o próprio PO) tem condições de planejar um bom backlog e proteger a equipe das quebras de ciclo. Agora sim a equipe passará a entregar o que interessa e as histórias irão refletir um alto nível de detalhamento no sprint corrente, diminuindo gradualmente até épicos conforme se afastam na linha do tempo.

No fim, é bem gratificante ver pessoas que apenas delegavam responsabilidade e culpa do alto de uma montanha descerem até o quadro branco pra fazer uns rabiscos na reunião de planejamento. Ter a consciência de ser tão responsável pelo sucesso ou fracasso do sistema quanto o desenvolvedor faz toda a diferença.

E se um dia aparecesse uma oficina mecânica no meu quintal, pode ter certeza que em poucos dias minhas mãos também iam ficar sujas de graxa.

No comments

Refatorando arquivos de configuração

Para reduzir a quantidade de linhas repetidas em arquivos yml, é possível reutilizar blocos. Por exemplo, este arquivo de configuração padrão...

development:
  adapter: mysql
  database: my_project_development
  username: root
  password: 123
 
test:
  adapter: mysql
  database: my_project_test
  username: root
  password: 123
 
production:
  adapter: mysql
  database: my_project_production
  username: root
  password: 123

...pode ser refatorado assim:

shared: &shared
  adapter: mysql
  username: root
  password: 123
 
development:
  <<: *shared
  database: my_project_development
 
test:
  <<: *shared
  database: my_project_test
 
production:
  <<: *shared
  database: my_project_production
 
No comments

Pesquisar e alterar um valor no Hash

Esses dias precisei procurar e alterar um valor específico num Hash, por exemplo:

 
my_hash = {:key1 => "value1", :key2 => "value2", [{:key3 => "target_value"}]}
 

Como a classe Hash não oferece busca recursiva por padrão, podemos abri-la e adicionar nosso próprio método.

 
class Hash
  def swap_value(target_value, new_value)
    self.each do |k, v|
      case v
        when String
          self[k] = new_value if v == target_value
        when Array
          v.each {|item| item.swap_value(target_value, new_value) }
        when Hash
          v.swap_value(target_value, new_value)
        end
    end
  end
end
 

É isso, agora a classe Hash tem um método para find and replace recursivo.

 
my_hash.swap_value("target_value", "my_new_value")
 
No comments

Rails Summit 2009

Nos dias 13 e 14 de outubro estive no Rails Summit 2009. Numa das palestras do dia 13 (se não me engano do Ilya Grigorik), o palestrante perguntou: quem aqui é programador .NET? Levantei a mão sozinho no meio do auditório, e pelo que o palestrante apontou, devia ter apenas mais um ou dois nas cadeiras do fundo.

Passei o minuto seguinte contando quantas pessoas haviam no meu campo de visão – 60 – e outro minuto calculando o total do público naquela palestra – mais ou menos 220 pessoas. Enquanto isso, a pergunta seguinte foi “e quem aqui é programador Java?”. Metade do público levantou a mão.

Qual será o motivo dessa diferença? O preço do evento era bem acessível (R$199,00 mais barato que a compra antecipada do último TechEd, e R$399,00 do que a compra na última data), e o conteúdo, apesar do tema principal ser Ruby on Rails, contava com ícones do mundo do software falando sobre temas diversos. Rockstars, como brincou o Obie Fernandez no seu Keynote.

Meu palpite é que isso é reflexo do isolamento histórico que a comunidade .NET mantém com o resto do mundo. Por muito tempo, as únicas referências que os seus developers, developers, developers recebiam eram o incentivo ao drag-and-drop e a falsa impressão que a MS podia lhes dar tudo o que precisassem. Precisam de um ORM? Vamos fazer um novo ao invés de colaborar com o NHibernate. Querem usar ajax? Ok, toma aqui o nosso ajax toolkit e deixa a parte complicada com a gente.

A estratégia do drag-and-drop fazia muito sentido na era pré-internet, para o tipo de aplicações que linguagens como o VB, Delphi e Java se propunham a resolver. Qualquer coisa que exigisse um controle maior do código seria feito em C mesmo, então a bagunça que essa abstração criava embaixo do tapete não era lá muito problemática. Porém, quando as empresas deixaram de ser pequenas ilhas e começaram a provar que a internet podia ser melhor que o desktop para rodar aplicações, era hora de parar.

Mas não foi o que aconteceu. Quando a plataforma .NET foi lançada, havia uma legião de desenvolvedores viciados na facilidade de criar aplicações Windows arrastando buttons, labels e textbox no Visual Basic. Eles não podiam perder essa base de programadores, e como sua próxima meta era o desenvolvimento web, fazer a construção de sites ser parecida com o desenvolvimento windows era a melhor forma de incluir os programadores da geração anterior. Daí o famigerado ASP.NET, com seus viewstates, web controls, page life cycle e tudo mais dos infernos.

Apenas recentemente eles vêm deixando essa postura de lado, com iniciativas open-source, parcerias em soluções já consolidadas e dando mais autonomia para o desenvolvimento de código decente - que o digam o MVC.NET + JQuery. Sem falar que estão cada vez menos tímidos em revelar o quanto já abraçaram internamente a parceria Scrum + XP.

O fato é que enquanto os desenvolvedores .NET eram mimados com ferramentas, o resto ralava tendo que codificar interface na unha ou usando/desenvolvendo ferramentas Open Source. O que era pra ser a maldição destes "rebeldes" virou uma benção, pois, não ter uma empresa ditando como fazer nem o que usar fez essa turma adquirir mais o hábito de trocar informações, dividir código e boas práticas em geral. Surgem frameworks como o Hibernate e o Spring, IDEs diversas, e principalmente, uma grande base de desenvolvedores que sabem o que estão fazendo.

Outro problema pode ser relacionado a cultura das empresas que utilizam a plataforma. Tomara que eu esteja enganado e o que eu vi ao longo da carreira não seja a regra, mas normalmente empresas que adotam integramente um plano de soluções corporativas só estão preocupadas em ter alguém pra processar se fizerem burrada. Nesse tipo de lugar normalmente quem compra não é quem usa, as pessoas são recursos alocados e os processos têm níveis de maturidade. É a entropia fazendo a festa rumo ao colapso, e não existe a menor chance de alguém ser incentivado a olhar pro mundo lá fora quando sua experiência é baseada em lugares assim.

Alguém que não se importa de ser chamado de recurso alocado é incapaz de perceber o valor que existe nestes eventos. Não só nestes encontros, mas nas práticas ligadas a cultura de software em geral. As ferramentas e os processos tradicionais acabam dando a falsa impressão de que está tudo bem, e se o profissional não ficar atento acaba preso num ShouldWorkToLive(Person resource) recursivo.

Sobre o evento em si nem pretendo falar muito, há diversos relatos internet afora e os vídeos podem ser encontrados no Vimeo. Para mim, superou as expectativas a ponto de motivar este recado aos que não costumam trocar figurinha com turmas de outras ruas: saiam da toca e participem dos encontros por aí, têm pra todos os perfis. Testes, agilidade, gestão, frameworks... Veja pelo menos uns dois ou três por ano, vai dar uma grande ajuda pra aprimorar sua visão profissional no período.

No comments

Código legado e débito técnico

Trabalhar num código legado, é como fazer uma viagem no tempo ou atravessar um dos portais Stargate. É ali que está a verdadeira história de uma empresa de tecnologia: a pressa em lançar antes do concorrente, a atenção (ou falta de) que se dá para um capacity planning, a qualidade da comunicação interna, o perfil das equipes de desenvolvimento, a clareza das regras de negócio, etc. Está tudo ali, pra quem souber traduzir os hieróglifos também conhecidos como débito técnico.

Ward Cunningham foi o primeiro a utilizar o termo “débito técnico”, para explicar que sempre que uma empresa de software opta por um design que visa resultados rápidos - abrindo mão da qualidade - ela insere no sistema uma complexidade que tornará seu custo maior no longo prazo. Para mais detalhes sobre a parte teórica, recomendo ir direto ao site do Mestre dos Magos.

No primeiro parágrafo eu misturei propositalmente os termos “legado” e “débito técnico”, mas será que são realmente a mesma coisa? Segundo este outro cara, legado é simplesmente qualquer código sem testes. Seguindo esta linha, sou levado a crer que débito técnico e legado são dois bichos diferentes.

Legado é aquele código caixa-preta, que ninguém sabe o que será afetado se mudar uma linha e ninguém se atreve nem a indentar (ou endentar, pro dicionário ficar feliz) o código. Normalmente, o sistema foi feito por pessoas que nunca ouviram falar do termo “débito técnico”, pois se soubessem o conceito, também saberiam como fazer um design que favorecesse sua manutenção futura.

Este é o resultado da mistura entre cowboys e gerentes caricatos. Eles acreditam estar fazendo um bom trabalho sendo pragmáticos ao extremo, mas, sem bons alicerces teóricos e um mínimo de estratégia é quase impossível fazer um sistema que não seja uma bomba-relógio - a chance de acerto é pura sorte.

Já em relação ao débito técnico legítimo, a equipe têm consciência de que para aproveitar uma oportunidade de mercado ou algo parecido em tempo hábil, não será capaz de implementar a arquitetura mais desejável a tempo. Porém, é perfeitamente capaz de trabalhar com foco no mínimo necessário e ao mesmo tempo se manter aderente a princípios de design que favoreçam a refatoração no momento adequado. E claro, o sistema obrigatoriamente terá alguma cobertura de testes, e ser testável é sinal de mais boas práticas no pacote.

Minha dica aos desenvolvedores que precisam dar manutenção a algum sistema legado: vistam o chapéu de Indiana Jones e divirtam-se. Arqueologia de sistemas é um ótimo exercício para refatoração e desenvolvimento da programação como arte. Afinal, como na arte, o sistema perfeito é o que atingiu a simplicidade onde não há mais nada a ser removido.

No comments

Visão panorâmica

O aumento da maturidade nos processos e tecnologias para desenvolvimento de software, têm refletido no mercado com viradas radicais nos critérios que definem um bom desenvolvedor.

Até há algum tempo, quanto maior a sequência de certificações na plataforma X no currículo, mais chances para o candidato. Havia, e ainda existe na cabeça de alguns gerentes, o mito de que quanto mais especializado e maior o tempo desenvolvendo na tecnologia X, mais “sênior” é o desenvolvedor. Na prática, existem muitos com alguma certificação e que mal sabem OO.

Hoje em dia, nas empresas em que vale a pena ficar antenado, dificilmente isso conta como um grande diferencial. O motivo é simples: elas sabem que bons desenvolvedores investem em princípios, não em frameworks.

Bons desenvolvedores são curiosos demais pra manter fidelidade a uma plataforma. Eles querem saber de tudo, Java/C#, Ruby, Lisp, F#, Erlang, Python, Rest, bancos de dados orientados a documentos… Eles sabem que não dá pra expadir a mente o suficiente só estudando patterns da GoF e modelando tabelinhas normais, muito menos decorando peculiaridades específicas de uma plataforma.

Isso é a média. O cara fora da curva não restringe seu campo de atuação a uma plataforma, ele adora programar, adora participar de projetos com pessoas brilhantes, e principalmente, vivenciar desafios legítimos. Java + Oracle, C# + SQL, SOAP… Boooring. Isso é o que o Paul Graham chama de “daily work”. A gente faz isso durante o dia, mas a paixão mesmo, está no fim do expediente quando o músico vai tocar no bar. Ou quando o nerd vai programar em Lua, por exemplo.

Restringir-se a uma tecnologia limita a carreira. Ao invés de decorar as receitas de bolo de uma marca e enfiar seus frameworks goela abaixo em tudo que é projeto, vale mais a pena entender a fundo os tipos de problemas que eles se propõem a resolver, porque e como eles acontecem, e quais as possíveis formas de resolvê-los de pontos de vista distintos.

Ao sair do mundo corporativo padrão, vêm a liberdade de comparar soluções open source  com empresas comerciais, linguagens de paradigmas opostos, técnicas de integração completamente diferentes, e principalmente, pensar como resolver os problemas utilizando a melhor ferramenta para cada caso. Saber “como fazer”, sem antes entender “porquê fazer” é puramente mecânico, é a média do mercado. Qualquer um estuda algumas horas e passa numa prova. Mas saber os porquês traz um ganho muito maior: enriquece a “cultura de software”.

Não abro mão de ter uma “linguagem oficial”, lógico que é necessário ser ninja de verdade em uma coisa pelo menos. Mas as pessoas com as quais convivo atualmente, me demonstram na prática que cultura de software e comunicação eficaz, são as maiores riquezas que você pode encontrar num desenvolvedor. Qualquer um no APInfo pode quebrar o galho num projeto convencional, mas se você realmente quer fazer um sistema direito, procure um nerd de verdade.

Aquele que responde no StackOverflow sobre DDD num dia, e no outro resume 700 linhas de código OO em 70 com um algoritmo maluco em liguagem funcional (porque era para tornar o processamento paralelo), que questiona se o design pattern escolhido não é um sinal da equipe não ter entendido direito a regra de negócio, que aprende sobre DSL programando extensões para o WoW, que sabe que Atores não são apenas pessoas que interpretam no teatro, etc. E isso ainda nem é cultura de software, talvez eu fale sobre isso num outro momento.

O ponto é que a visão de um especialista muito especializado, tem horizontes muito curtos para ajudar a escolher os caminhos num nível mais abrangente. Esse cara pode te entregar no prazo, pode entregar o que você quer, mas não vai ser o que você ou o seu cliente realmente precisava.

É possível encontrar profissionais que seguiram a fundo no “daily work”, com carreira de certificação, e ainda assim são verdadeiros nerds. Até tive o prazer de conhecer alguns. O problema é que existem poucos por aí, e dos casos que conheço, eles nem ligam pros certificados e muito menos ficam presos as soluções da plataforma em questão. Exceto um que é PMP, esse tem vergonha mesmo e prefere quem nem comentem.

Edit

Dois posts que complementam esse blablabla com alguma coisa mais concreta:

http://www.techfounder.net/2009/07/22/what-makes-a-good-programmer/
http://www.inter-sections.net/2007/11/13/how-to-recognise-a-good-programmer/

No comments

Parallel, F# e no fim, de volta ao básico

Recentemente, reescrevemos aqui na empresa onde trabalho um serviço de instalações. O fluxo era mais ou menos o seguinte (ligeiramente simplificado):

1 – Identificar se o pedido foi aprovado
2 – Obter a lista de serviços inclusos no pedido
3 – Chamar o WS de instalação correspondente para cada serviço
4 – Logar todo o processo para gerar estatísticas e identificar erros de instalação

As instalações devem ser processadas ininterruptamente e o volume diário é imenso. Após um spike sobre o projeto, resolvemos utilizar o Parallels na camada de infra-estrutura para simplificar o processamento simultâneo por pacotes de serviços e escalar melhor aproveitando os múltiplos cores do servidor.

O desenvolvimento foi tranquilo, o projeto foi pro ar e observamos uma melhora significativa no ciclo de instalações. Agora a parte boa, cadê o problema? Monitorando o negócio depois de uns dias no ar, percebemos que as chamadas para os Web Services externos viraram o freio-de-mão puxado da aplicação.

“Mas como, isso é tão básico!” – pois é, tão sem graça que resolvemos variar e implementar em F# para fazer as chamadas assíncronas, saiu algo mais ou menos assim:

   1: /// Executa um POST para a url especificada.
   2: let AsyncPost (url:string, httpMethod:PostType, contentType:string, postData:string) =
   3:     Async.Run(AsyncHttpPost(url, httpMethod, contentType, postData))
   4:
   5: /// Immplementação para o método AsyncPost.
   6: let private AsyncHttpPost(url:string, httpMethod:PostType, contentType:string, postData:string) =
   7:         async {
   8:             let asyncRequest = WebRequest.Create(url)
   9:             asyncRequest.Method <- httpMethod.ToString()
  10:
  11:             do
  12:                 match httpMethod with
  13:                 |PostType.POST | PostType.PUT   ->
  14:                     asyncRequest.ContentType <- contentType
  15:                     use writeStream = asyncRequest.GetRequestStream()
  16:                     let encoding = new UTF8Encoding()
  17:                     let bytes = encoding.GetBytes(postData)
  18:                     writeStream.Write(bytes, 0, bytes.Length)
  19:                  |_ -> null
  20:
  21:             use! response = asyncRequest.AsyncGetResponse()
  22:
  23:             use stream = response.GetResponseStream()
  24:             use reader = new StreamReader(stream)
  25:
  26:             return! reader.AsyncReadToEnd()
  27:         }
  28:
  29: /// Verbos aceitos para atualizações HTTP
  30: type PostType =
  31: |    POST = 1
  32: |    PUT = 2
  33: |    DELETE = 3

Teoricamente não havia motivos para as chamadas http se tornarem o gargalo do fluxo, então decidimos rever do básico como as aplicações .Net processam chamadas http.

Depois de perder um tempo no MSDN, o Google me fez parar neste e neste post. Ambos têm a resposta que eu procurava, mas no primeiro ainda têm uma mega aula de debug e o segundo dá várias outras dicas importantes. Enfim, a solução principal estava no atributo do app.config:

<add address="*" maxconnection="20" />

Onde 20 é o número máximo de conexões simultâneas permitidas por url.

A configuração padrão no Framework permite apenas duas conexões simultâneas por endereço, e aí não têm sistema mega-blaster-multi-thread que resolva – quando chegar nas chamadas http vai enfileirar tudo neste limite.

Como o autor do segundo post explica, esse limite é uma cautela para proteger endereços de ataques DoS não intencionais e para seguir a RFC 2616, que diz que “um cliente não deve manter mais de duas conexões abertas para o mesmo servidor ou proxy”.

Ok… mas precisava uma engenheira de escalabilidade com poderes de debug sobrenaturais – da própria Microsoft, e mais um monte de gente passar pela mesma saga de “caça ao gargalo” pra chegar nessa informação? O MSDN melhorou muito nos últimos anos, mas ainda está longe de ser o ideal.

No comments

I18N + datetime_select = erro “can’t convert Symbol into String”

Não acontece se especificar a ordem:

<%= f.datetime_select :date_of_birth, :o rder => [:year, :month, :day] %>

No comments

Next Page »