1up4developers logo

1up4developers

Nadando contra o Waterfall. tail -f /mind/realworld >> /blog

Usando Bundler Com Rails 2.3

| | Comments


Iniciando minha participação neste blog, vou apresentar uma solução rápida para um problema que eu tive e levei um certo tempo para encontrar uma resposta.

Caso você não conheça, Bundler é uma ferramenta criada para facilitar a instalação e atualização de aplicações e suas gems, resolvendo facilmente as dependências e criando ambientes homogêneos em máquinas diferentes. Em outras palavras, resolve de uma vez por todas aquele inferno que era ter que baixar gem por gem da sua aplicação e ainda assim correr o risco de encontrar alguma incompatibilidade.

O Rails 3 utiliza o Bundler por padrão, mas aplicações em Rails 2.x ainda dependem das gems declaradas no arquivo config/environment.rb, e ao copiar os arquivos para uma determinada máquina, você é obrigado a usar rake gems:install, que vai levar algum tempo rodando e não vai instalar tudo o que você precisa.

Ou pelo menos era assim que funcionava até você ler esse post.

Primeiro, considerando que você esteja no diretório raiz da sua aplicação, execute a sequência abaixo:

Antes de qualquer outra coisa, instale o Bundler na sua máquina executando o comando gem install bundler

No seu arquivo config/boot.rb, imediatamente antes da linha Rails.boot!, insira o bloco abaixo:

class Rails::Boot
  def run
    load_initializer

    Rails::Initializer.class_eval do
      def load_gems
        @bundler_loaded ||= Bundler.require :default, Rails.env
      end
    end

    Rails::Initializer.run(:set_load_path)
  end
end

Crie um arquivo config/preinitializer.rb. Esse arquivo não existe no Rails 2.x, então se você não criar, não vai funcionar. Adicione as linhas abaixo nesse arquivo:

begin
  require "rubygems"
  require "bundler"
rescue LoadError
  raise "Could not load the bundler gem. Install it with `gem install bundler`."
end

if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.24")
  raise RuntimeError, "Your bundler version is too old for Rails 2.3." +
   "Run `gem install bundler` to upgrade."
end

begin
  # Set up load paths for all bundled gems
  ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
  Bundler.setup
rescue Bundler::GemNotFound
  raise RuntimeError, "Bundler couldn't find some gems." +
    "Did you run `bundle install`?"
end

Crie um arquivo chamado Gemfile no raiz da sua aplicação. Entre em config/environment.rb, remova todas as instruções config.gem e as adicione no arquivo Gemfile conforme abaixo, sem o prefixo config. (ponto incluído).

Seu arquivo config/environment.rb era assim:

# Be sure to restart your server when you modify this file

# Specifies gem version of Rails to use when vendor/rails is not present
RAILS_GEM_VERSION = '2.3.10' unless defined? RAILS_GEM_VERSION

# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')

Rails::Initializer.run do |config|
  # Settings in config/environments/* take precedence over those specified here.
  # Application configuration should go into files in config/initializers
  # -- all .rb files in that directory are automatically loaded.

  # Add additional load paths for your own custom dirs
  # config.load_paths += %W( #{RAILS_ROOT}/extras )

  # Specify gems that this application depends on and have them installed with rake gems:install
  config.gem "bj"
  config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net"
  config.gem "sqlite3-ruby", :lib => "sqlite3"
  config.gem "aws-s3", :lib => "aws/s3"
  config.gem "authlogic", :version => "=2.1.6"
  config.gem "slim_scrooge", "=1.0.10"

  # Only load the plugins named here, in the order given (default is alphabetical).
  # :all can be used as a placeholder for all plugins not explicitly named
  # config.plugins = [ :exception_notification, :ssl_requirement, :all ]

  # Skip frameworks you're not going to use. To use Rails without a database,
  # you must remove the Active Record framework.
  # config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
end

E agora é assim:

# Be sure to restart your server when you modify this file

# Specifies gem version of Rails to use when vendor/rails is not present
RAILS_GEM_VERSION = '2.3.10' unless defined? RAILS_GEM_VERSION

# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')

Rails::Initializer.run do |config|
  # Settings in config/environments/* take precedence over those specified here.
  # Application configuration should go into files in config/initializers
  # -- all .rb files in that directory are automatically loaded.

  # Add additional load paths for your own custom dirs
  # config.load_paths += %W( #{RAILS_ROOT}/extras )

  # Only load the plugins named here, in the order given (default is alphabetical).
  # :all can be used as a placeholder for all plugins not explicitly named
  # config.plugins = [ :exception_notification, :ssl_requirement, :all ]

  # Skip frameworks you're not going to use. To use Rails without a database,
  # you must remove the Active Record framework.
  # config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
end

Bem mais limpo, não?

Já o seu recém criado arquivo Gemfile vai ficar assim:

source 'http://gemcutter.org'
gem "bj"
gem "hpricot", "~> 0.6"
gem "sqlite3-ruby", "~> 1.3.1", :require => "sqlite3"
gem "aws-s3", :lib => "aws/s3"
gem "rails", "= 2.3.10"
gem "authlogic", "~> 2.1.6"

group :development, :test do
  gem 'mongrel', :require => false
end

group :production do
  gem "slim_scrooge", "~> 1.0.10"
end

Note que eu criei dois grupos: um com :development, :test e um com :production. Significa que as gems do primeiro grupo somente serão utilizadas em desenvolvimento e em testes, e as do segundo grupo somente serão usadas no ambiente de produção. O que está fora dos grupos será usado em qualquer ambiente.

Agora, finalmente você digita bundle install, aguarda alguns instantes e pronto! A sua aplicação está com todas as gems instaladas e suas devidas dependências.

Para listar as gems utilizadas, execute bundle list.

Sugestões, correções e críticas são bem vindas nos comentários.

Para mais informações, leia a documentação no site do Bundle: http://gembundler.com/

Voltamos!

| | Comments


Caros leitores, depois de um período, digamos boring, estamos de volta e com novidades!

Durante o ano de 2010 estivemos trabalhando muito, por isso a baixa frequencia de posts. Porém tanto trabalho rendeu experiências únicas para todos nós, as quais pretendemos compartilhar com vocês em breve.

Novos rebeldes colaboradores

Rogério Ramos

Desenvolvedor, entusiasta, sonhador. Acredita que desenvolvedores e usuários devem trabalhar sempre a quatro mãos. Veterano com agile e Scrum, está iniciando sua jornada com com Ruby on Rails.

Plínio Balduino

Desenvolvedor, baixista musicólatra, test addicted, viciado em leitura, “pragmático, sarcástico, curioso” e pai do Gustavinho. Esperem posts ácidos sobre Scrum e dicas práticas de Rails.

Sejam bem vindos à guerrilha!

E não é só isso!

Estreiamos o novo tema, mais limpo e distribuído, facilitando a leitura dos códigos inline. O endereço do feed também mudou: atualizem seus leitores para o endereço http://feeds.feedburner.com/1up4developers. E quem ainda não assinou, assine d-já!

Fiquem a vontade para comentar (ou não). Sucesso!

Teste De Integração Com Rspec 1.x E Capybara Na Sua App Rails

| | Comments


Este não é daqueles posts que explicam o que é rspec, testes, diferenças entre teste funcional, integração e etc. Este post é só uma rapidinha, pra quem já conhece rspec e capybara.

A documentação do Capybara é boa, mas deixa a desejar nas instruções de como integrá-lo somente com rspec. Com a ajuda do George Guimarães da Plataforma, cheguei num passo a passo mega simples.

No config/environments/test.rb declare:

config.gem "rspec",            :version => "= 1.3.0", :lib => false
config.gem "rspec-rails",      :version => "= 1.3.2", :lib => false
config.gem "capybara",         :version => "= 0.3.9", :lib => false

No spec/spec_helper.rb coloque:

require 'capybara/rails'
[...]
Spec::Runner.configure do |config|

  [...]
  config.include(Capybara, :type => :integration)

end

Pronto! Isto é o suficiente para utilizar o Capybara nos testes de integração. Para finalizar, você pode montar um teste simples de validação. Por exemplo:

Crie spec/integration/site_spec.rb e coloque:

require 'spec_helper'

describe "Site sample" do

  context "root" do

    before do
      visit root_url
      save_and_open_page
    end

    it "should have Hello" do
      page.should have_content("Hello")
    end

  end

end

Para executar somente os testes de integração:

rake spec:integration

have_content e um hot tip que pode te salvar muitas horas !

Caso aconteça o erro:

undefined method `have_content' for #<ActionController::Integration::Session:0xb618ad10>

Graças a esta mensagem Can’t make matchers work with cucumber and rails 2.3.2, descobri que o have_content não funciona com o rails 2.3.2, eu resolvi o problema fazendo um upgrade para a última versão do rails. #ficaadica

Dúvidas, melhorias, sugestões e elogios são sempre bem vindos !

A Extinção Do Programador Sênior

| | Comments


Quando foi a última vez em que você viu um programador sênior? Eu tenho tido sérias dificuldades para encontrar algum. Acho que se estivesse procurando ararinhas azuis teria tido mais sucesso — será que alguma toparia programar? Desconfio que não. Consciente da causa ecológica, ela me diria: cada ararinha programando toma o lugar de um programador sênior, que é de uma espécie muito mais em risco do que eu. E bateria as asas em retirada.

É claro que, ao contrário da pobre arara, o programador sênior ainda existe, e em grandes quantidades. Mas algo deu errado na evolução da sua espécie que, ao invés de melhorar, foi substituída por uma variedade mais fácil de reproduzir, bem adaptada ao cativeiro, de comportamento dócil, capaz de passar anos fazendo a mesma coisa e com duas opções de cor: terno preto ou azul. E que, curiosamente, não consegue programar. Eu já vou batizando essa variedade de programador senhor.

Estou falando por experiência própria. A empresa em que eu trabalho está recrutando um “programador sênior” há alguns meses. Dada a indisponibilidade dos colegas no nosso networking (o que nos pouparia um grande tempo), resolvemos apelar e buscar no mercadão de trabalho (vulgo apinfo, catho, essas coisas). Nós filtramos dezenas de currículos, conduzimos entrevistas, aplicamos testes. Com isso, conseguimos achar diversos programadores senhores mas nenhum propriamente sênior. A maioria tinha 10+ anos de carreira, 30+ anos de idade e -1 noção para bolar respostas satisfatórias para questões como:

  1. Como dois programas podem se comunicar?

  2. O que são threads?

  3. Implemente o fizz buzz na linguagem que preferir.

E assim por diante. Nada muito específico: preferimos encontrar gente que tivesse convivido com certos problemas, independente da tecnologia adotada. Gente demonstrasse senioridade propriamente dita: maturidade, bom senso, raciocínio, segurança. E conhecimento suficiente para não achar que a chave de todos os problemas é uma consulta ao Google (houve quem confessasse isso). Não encontramos essa gente ainda, mas em compensação vimos muitas pessoas bem intencionadas, certamente esforçadas, mas com imensas dificuldades para concatenar opiniões a respeito de conceitos que julgamos básicos e, no nosso negócio, fundamentais.

Sequer exigimos que o candidato conheça tópicos como controle de versão, orientação a objetos, design patterns, agilidade e etcetera, que são sinais mais do que evidentes de maturidade. Já entendemos que tudo isso está além dos limites do habitat do programador senhor. São coisas tão exóticas quanto um programador sênior genuíno, que só deve existir em áreas de proteção ambiental, como este blog.

(Às araras azuis que estiverem interessadas no recrutamento: por ora concluímos o processo, mas não deixem de entrar em contato.)

Gerando Rotas Com Parâmetros Dinâmicos No Rails De Modo Fácil

| | Comments


A API de rotas do Rails simplifica consideravelmente o desenvolvimento fornecendo um padrão de geração e utilização de URLs para toda aplicação. Porém algumas necessidades especificas e relativamente simples podem gerar dores de cabeça se forem implementadas incorretamente.

Um caso bastante comum são URLs compostas que sempre apontam para um mesmo recurso. Por exemplo, um blog que possua rotas para seus posts no formato /posts/autor/categoria/permalink provavelmente terá uma rota mapeada como map.post "posts/:author/:category/:permalink" gerando automaticamente os helpers post_path e post_url.

Muito bom, porém para usufruirmos desta facilidade precisamos fornecer os valores dos parâmetros dinâmicos nos controllers e views:

post_path(:author => @post.author, :category => @post.category, :permalink => @post.permalink)

E mesmo que você forneça os parâmetros em um array, vai dar muito trabalho além de deixar muito código repetido pela aplicação.

Entendi! Mas como resolvo este problema?

Para este caso, apenas implementar o método [to_param](http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M001840) do model não vai servir. Uma solução seria reescrever o método post_path (que é gerado automaticamente) no respectivo helper (posts_helper.rb):

def post_path(post, options = {})
  super(post, :author => post.author, :category => post.category, :permalink => post.permalink)
end

Outra solução seria sobrescrever o método [default_url_options](http://api.rubyonrails.org/classes/ActionController/Base.html#M000467) no controller para retorna os parâmetros padrões da rota:

def default_url_options(options = {})
  options.merge!(:author => @post.author, :category => @post.category, :permalink => @post.permalink) if options[:action] == "show"
end

A má notícia é que você terá que fazer isto para todos seus controllers e respectivos models.

A terceira solução (e mais elegante) é padronizar a maneira com que os parâmetros opcionais da rota são obtidos a partir do controller e seu respectivo model. Basta adicionar os seguintes métodos no seu ApplicationController:

def default_url_options(options = {})
  if (model = controller_model(options))
    dynamic_route_params(options).each do |param|
      options[param] = model.send(param) if model.respond_to?(param)
    end
  end
  options
end

def controller_model(options = {})
  clazz = (options[:controller].singularize.camelize.constantize rescue ActiveRecord)
  options.select { |key, value| value.is_a?(clazz) }.first.second
rescue
  nil
end 

def dynamic_route_params(options = {})
  returning [] do |dynamic_params|
    matched_routes = ActionController::Routing::Routes.routes.select do |route|
      route.matches_controller_and_action?(options[:controller], options[:action])
    end
    dynamic_segments = matched_routes.map(&:segments).flatten.each do |segment|
      dynamic_params << segment.key if segment.is_a?(ActionController::Routing::DynamicSegment)
    end
  end
end

Assim, os valores defaults dos parâmetros da rota serão obtidos diretamente do model. Caso queiram contribuir, este código está disponível no github.

Referências Rails Routing from the Inside Out Rails Guides: Routing

Active Record Em: Como Adicionar Comportamento as Suas Associações

| | Comments


Qualquer um que comece a desenvolver com Active Record (AR), minha primeira recomendação é, para tudo e leia:  A Guide to Active Record Associations ou O Guia de Associações do Active Record. O guia é bem completo, e descreve muito bem os tipos de associações que estão disponíveis no AR.

Association Proxy, #wtf !

As associações:

  • belongs_to

  • has_one

  • has_many

  • has_and_belongs_to_many

Quando usadas, adicionam alguns métodos (veja Detailed Association Reference). Por exemplo, ao declarar uma associação belongs_to, o model “ganhará” os seguintes métodos:

  • association(force_reload = false)

  • association=(associate)

  • build_association(attributes = {})

  • create_association(attributes = {})

Onde association, será substituído pelo nome da associação. Exemplo retirado do guides:

class Order < ActiveRecord::Base
   belongs_to :customer
end

Cada instância de Order, conterá os métodos:

  • customer

  • customer=

  • build_customer

  • create_customer

O association proxy, é o objeto que faz a ligação do objeto que contém a associação, conhecido como owner, e o objeto associado, conhecido como target.

Legal e daí !?!

Graças ao association proxy, ao declarar uma associação, podemos extendê-la e adicionar comportamentos “customizados”. No guia, é citado como Association Extensions. O código de exemplo abaixo, está no github em random-samples.

Para exemplificar, vamos criar um modulo que adiciona o comportamento de uma galeria a qualquer coleção.

module GalleryColletion

  def current=(curr = nil)
    @current, @index = nil

    if curr.nil?
      @current = collection.first
      @index = 0
    else
      collection.each_with_index do |item, index|
        if item.id.to_i == curr.to_i
          @current = item
          @index = index
        end
      end
    end
    @current
  end

  def current
    @current
  end

  def position
    @index + 1
  end

  def previous?
    return false if @index.nil?
    !!(@index - 1 >= 0)
  end
  def previous
    collection[@index - 1] if previous?
  end

  def next?
    return false if @index.nil?
    !!(@index + 1 < collection.size)
  end
  def next
    collection[@index + 1] if next?
  end

  private

  def collection
    proxy_owner.send(proxy_reflection.name)
  end

end

Gallery Collection

Note que o modulo está na pasta lib, logo, a pasta tem que ser adicionada no path via config/environment.rb.

Para extender a associação, declare:

class Article < ActiveRecord::Base
  has_and_belongs_to_many :images, :extend => GalleryColletion
end

Article model, Image model aqui.

Agora para navegar entre as imagens, você pode usar:

a = Article.first
a.images.current = 1 #1 e o Image.id que deseja selecionar
a.images.current
a.images.position
a.images.next?
a.images.next
a.images.previous?
a.images.previous

Caso esteja com coragem, baixe o projeto e veja rodando.

Dúvidas, sugestões, algum “case” de sucesso, comente!

Teste Sua Aplicação De Linha De Comando Com Cucumber!

| | Comments


É engraçado como tudo é questão de treino e disciplina. Levei um tempo para me acostumar com TDD, Vim e não poderia ser diferente com testes funcionais, sendo mais especifico, Cucumber.

Até o momento, só tinha usado cucumber em projetos web. E quando voltei a desenvolver o rubygems_snapshot, senti falta de algo para testar funcionalmente. Baseado no pik, montei um esquema simples para validar qualquer aplicação de linha de comando.

Como instalar

Basicamente, será necessário (fontes via gist):

  • rake para executar o cucumber

  • env_terminal.rb

  • terminal_steps.rb

Dado que você tem cucumber instalado, com o esquema da pasta “features”.

  • Copie o cucumber.rake para a raiz.

  • Copie o env_terminal.rb para a pasta features.

  • Copie o terminal_steps.rb para a pasta features/step_definitions/terminal_steps.rb.

  • Edite o  env.rb incluindo (pode ser no começo):

    require “env_terminal”

  • Dentro do Rakefile, pode ser no final mesmo, adicione:

    load “cucumber.rake”

Como usar

Todas features:

rake cucumber

Features com a tag @wip, também conhecida como Work in Progress.

rake cucumber:wip

Informações Extras

Caso precise de mais informações, você tem a opção de ver a saída dos comandos, executando a rake assim:

rake cucumber show_output=true

ou

rake cucumber:wip show_output=true

No caso do snapshot, tive a necessidade de “modificar” o comando gem toda vez que era executado, ou melhor, passar um parâmetro para controlar o ambiente. Dentro do env_terminal.rb, existe o método gsub_command, nele você pode “redefinir” comandos, caso necessite.

Gostei, quero mais!

A solução acima, é bem “caseira”. Para projetos simples com funcionalidades simples, funciona bem.

Caso queira algo mais robusto, você tem a opção da gem Aruba.

Tem este post como introdução:

Aruba – Cucumber Goodness for the Command-Line

Rubygems Snapshot! Importando/Exportando Gems Com Velocidade!

| | Comments


Nova versão do Rubygems_Snapshot no ar!

Fico feliz em dizer que este é o meu primeiro projeto que passou dos dez “watchers” ! :D E que realmente ajudou alguns developers mundo afora.

A primeira versão foi muito focada no uso pessoal, como “quebra-galho” mesmo. Resolvi investir algum tempo e praticamente refaze-lá, pois ao usar no dia-a-dia percebi algumas falhas e dificuldades de uso.

Basicamente, nesta nova versão:

  • É possível trabalhar com mais de um formato. Yml e Tar, que é o padrão.

  • Ao exportar, os arquivos “.gem” serão exportados.

  • Ao importar, ocorre praticamente uma instalação “offlline”, muito mais rápido e livre de problemas com “sources” do rubygem !

  • Usar o Snapshot como API !

Como tive um trabalhão para deixar o Readme legal, não pretendo escrever mais que isso! :D

Marcos, valeu pelo incentivo! Cara, forka lá e manda bala!

Importando E Exportando Suas Gems Com Rubygems Snapshot

| | Comments


Final de ano está rendendo. O rubygems_snapshot nasceu da necessidade de “migrar” as gems instaladas de uma máquina para outra, aliado ao rvm (veja este post-guia-rápido), permite mudar e/ou criar diferentes ambientes em minutos. Assim você pode fugir do famoso “gem hell”.

Veja como é difícil usar:

Instalação:

sudo gem install rubygems_snapshot

Para exportar as gems instaladas:

gem snapshot export projeto-exemplo.yml

Supondo que esteja em outra máquina, para importar as gems, use:

[sudo] gem snapshot import projeto-exemplo.yml

Afinal, o que tem de legal nisso?

Vamos supor que você acaba de entrar numa nova equipe e tem que montar o ambiente de desenvolvimento (por sinal, um ambiente complicado de configurar). O gem snapshot aliada ao rvm, foi feito para facilitar isto, vamos a um exemplo rápido:

Com o rvm, você pode criar um “novo ambiente”:

rvm use 1.8.7%projeto_exemplo




gem list

Deve retornar vazio.

gem install rubygems_snapshot




gem snapshot import projeto-exemplo.yml

Instalará as gems necessárias para o projeto e pronto!

ToDo:

Esta é uma versão bem básica, onde o “import” somente lê as gem e version e manda instalar sem requerir dependências. Está previsto de colocar um aviso no final das gems que deram erro, geralmente devido a dependências de “build nativos”, mas por enquanto estamos usando aqui na equipe com sucesso.

Como faço para criar um rubygems plugin também?

Bom, logo de cara posso te garantir que não é difícil (apesar da pouca documentação na internet), mas deixarei os detalhes para um outro post. Por enquanto, a minha recomendação é: clone o projeto, analise os dois rb do projeto :D e crie o seu!

Caso algum corajoso for usar, estou a disposição para ajudar, é só deixar um comentário aê! Valeu e sucesso!

Agile Enterprise Edition

| | Comments


Para começar o post, segue esta história sobre gerenciamento que vi no blog do Gustavo Ribeiro:

Todos os dias, uma formiga chegava cedinho ao escritório e pegava duro no trabalho. A formiga era produtiva e feliz. O gerente marimbondo estranhou a formiga trabalhar sem supervisão. Se ela era produtiva sem supervisão, seria ainda mais se fosse supervisionada.

E colocou uma barata, que preparava belíssimos relatórios e tinha muita experiência, como supervisora. A primeira preocupação da barata foi a de padronizar o horário de entrada e saída da formiga.

Logo, a barata precisou de uma secretária para ajudar a preparar os relatórios e contratou também uma aranha para organizar os arquivos e controlar as ligações telefônicas.

O marimbondo ficou encantado com os relatórios da barata e pediu também gráficos com indicadores e análise das tendências que eram mostradas em reuniões.

A barata, então, contratou uma mosca, e comprou um computador com impressora colorida. Logo, a formiga produtiva e feliz, começou a se lamentar de toda aquela movimentação de papéis e reuniões! O marimbondo concluiu que era o momento de criar a função de gestor para a área onde a formiga produtiva e feliz, trabalhava. O cargo foi dado a uma cigarra, que mandou colocar carpete no seu escritório e comprar uma cadeira especial.

A nova gestora cigarra logo precisou de um computador e de uma assistente (sua assistente na empresa anterior) para ajudá-la a preparar um plano estratégico de melhorias e um controle do orçamento para a área onde trabalhava a formiga, que já não cantarolava mais e cada dia se tornava mais chateada.

A cigarra, então, convenceu o gerente marimbondo, que era preciso fazer um estudo de clima. Mas, o marimbondo, ao rever as cifras, se deu conta de que a unidade na qual a formiga trabalhava já não rendia como antes e contratou a coruja, uma prestigiada consultora, muito famosa, para que fizesse um diagnóstico da situação. A coruja permaneceu três meses nos escritórios e emitiu um volumoso relatório, com vários volumes que concluía: “Há muita gente nesta empresa!”

Então o marimbondo mandou demitir a formiga porque ela andava muito desmotivada e aborrecida.

Então lembrei de uma imagem que ilustra perfeitamente esta fábula e retrata fielmente a “organização” de alguma empresas:

Dividir para conquistar: você está fazendo isso errado!

Quando uma startup passa a vender mais e ter uma procura maior por seus produtos/serviços (o que é bom), uma reação comum da “cúpula” é aumentar o quadro de funcionários visando atender a demanda. Logo surgem os problemas com a organização do pessoal e/ou fluxo de trabalho. A solução mais simplista (e óbvia) é a especialização: fulano faz isso, ciclano faz aquilo, e beltrano gerencia. Logo controles são criados, fluxos validados, centros de custo, documentos, reuniões, atas, comitês, gestão de pessoas e relacionamento, terceirização, cargos, departamentos… e nasce o monstro da burocracia, aka “enterprise”.

Com essa especialização, cada “módulo” (também conhecido como departamento) começa a perder o foco no GRANDE objetivo da empresa e passa a defender apenas seus interesses – a famosa MISSÃO da empresa passa a ser coadjuvante. O resultado? A empresa dobra ou triplica seu quadro de funcionários e na maioria dos casos, seu lucro bruto. Porém agora tem mais despesas com pessoal e gastos extras para manter esse novo modelo “enterprise”. Trocando em miúdos, continua na mesma!

Onde está o erro? Mais uma vez o FOCO está na solução ao invés de PROBLEMA. Se você ler meus posts anteriores vai ver que este é um tema recorrente. Então por que as empresas continuam fazendo as coisas erradas e cometendo os mesmos erros?

Idéias criativas surgem das pessoas diretamente relacionadas com os problemas e não de diretores, contadores, gestores, etc. Esse modelo “enterprise” é um overhead organizacional que só gera ruído e desperdício!

A solução é adotar agile!

SOLUÇÃO!? Mas qual era o PROBLEMA mesmo!? Sim, mais uma vez o foco é a solução ao invés do problema.

Como eu disse nos posts anteriores, acreditar que uma mudança drástica do processo pode mudar a cultura da empresa e pincipalmente as pessoas é o maior erro na adoção de metodologias ágeis. Mudam o processo mas não mudam as pessoas.

De uma forma simples e direta, agile resume-se a quatro valores:

Individuals and interactions over processes and tools Working software over comprehensive documentation Customer collaboration over contract negotiation Responding to change over following a plan

Ou seja, pessoas, software, colaboração e feedback. Simples assim!

O manifesto ágil não cita nada sobre “enterprise”, sobre a implementação. Este é o grande desafio em sua adoção. Como seguir estes valores sem burocratizar e engessar o processo? Como criar uma relação de colaboração com os clientes? Como responder rapidamente a mudanças? Como eliminar o esforço que não agrega valor ao produto e/ou empresa? Como evitar politicagem?

Mantenha-se pequeno!

Otimize! Busque soluções para os problemas que impedem de produzir mais e com mais qualidade. Faça MAIS com MENOS. Foque no O QUE ao invés do COMO. Escale as pessoas verticalmente!

Inove! Não espere conseguir resultados diferentes fazendo sempre a mesma coisa. Busque novidades, opniões, experiências. Ouça seus funcionários, seus clientes. Estude, pesquise, arrisque, erre, acerte… continuamente.

Mantenha o foco! Tenha um GRANDE e único objetivo e certifique-se que todos acreditem nesta filosofia. É importante que todos comprem a idéia e o modus operandis.

Finalizando, este é apenas meu ponto de vista, baseado na minha experiência em diversas empresas grandes e pequenas, vivenciando problemas, errando muito e principalmente aprendendo com os erros dos outros. Agilidade pode funcionar bem em grandes corporações, desde que haja foco e que todos comprem a idéia. Você pode concordar ou não.