Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A retrospective of problematic projects (Rubyconf Brazil 2012)

A retrospective of problematic projects (Rubyconf Brazil 2012)

Palestra realizada na RubyConf Brasil 2012 e preparada em conjunto com Jeffry Degrande ( twitter @jeffrydegrande ). Fazemos uma análise em retrospectiva dos padrões de projetos problemáticos que tivemos oportunidade de trabalhar nos 25 anos de experiência em conjunto.

danielvlopes

August 30, 2012
Tweet

More Decks by danielvlopes

Other Decks in Programming

Transcript

  1. ...

  2. Move code into controller ☑ Rails BEST PRACTICES gem Move

    code into model ☑ Rep. ivars with local vars ☑ Not use time_ago_in_words ☑ Dry bundler in capistrano ☑ Hash Syntax ☑
  3. TDD BDD TAFT DRY NOSQL RUBY FUNCTIONAL OOP MVC REST

    DDD SPIKE PAIR PROG. CONTINUOUS DEPLOY CONTINUOUS DEPLOY RAILS CONT. INTEGRATION FAST TESTS PRESENTERS DISTRIBUTED
  4. TDD BDD TAFT DRY NOSQL RUBY FUNCTIONAL OOP MVC REST

    DDD SPIKE PAIR PROG. CONTINUOUS DEPLOY CONTINUOUS DEPLOY RAILS CONT. INTEGRATION FAST TESTS PRESENTERS DISTRIBUTED DRY & AUTOMAÇÃO
  5. <h2>Cadastrar nova pessoa</h2> <%= form_for @person, :remote => true do

    |f| %> <fieldset> <%= f.label :number, "Qual o número de registro?" %> <br/> <%= f.text_field :number, :autofocus => true, :size => 25 %> </fieldset> <fieldset> <%= f.label :created_at, "Data de cadastro:" %> <br/> <%= f.text_field :created_at, :disabled => true, :size => 10 %> </fieldset> <fieldset> <%= f.label :start_date, "Início:" %> <%= f.text_field :start_date, :size => 10 %> e <%= f.label :start_date, "Fim:" %> <%= f.text_field :created_at, :size => 10 %> </fieldset> <fieldset> <%= f.label "Informe nº do processo desta pessoa" %> <br/> <%= f.text_field :process_number, :size => 20, :maxlength => 20 %> </fieldset> <% end %>
  6. %h2 Cadastrar nova pessoa = form_for @person, :remote => true

    do |f| %fieldset = f.label :number, "Qual o número de registro?" %br = f.text_field :number, :autofocus => true, :size => 25 %fieldset = f.label :created_at, "Data de cadastro:" %br = f.text_field :created_at, :disabled => true, :size => 10 %fieldset = f.label :start_date, "Início:" = f.text_field :start_date, :size => 10 e = f.label :start_date, "Fim:" = f.text_field :created_at, :size => 10 %fieldset = f.label "Informe nº do processo desta pessoa" %br = f.text_field :process_number, :size => 20, :maxlength => 20
  7. %h2 - if resource.persisted? = t 'title.edit', :resource_name => resource_class.model_name.human

    - else = t 'title.new.male', :resource_name => resource_class.model_name.human = form_for @person, :remote => true do |f| %fieldset = f.label :number, "Qual o número de registro?" %br = f.text_field :number, :autofocus => true, :size => 25, , :disabled => !resource.updatab %fieldset = f.label :created_at, "Data de cadastro:" %br = f.text_field :created_at, :disabled => !resource.updatable?, :size => 10 %fieldset = f.label :start_date, "Início:" = f.text_field :start_date, :size => 10 e = f.label :start_date, "Fim:" = f.text_field :created_at, :size => 10 %fieldset = f.label "Informe nº do processo desta pessoa" %br = f.text_field :process_number, :size => 20, :maxlength => 20, :disabled => !resource.up
  8. %h2 - if resource.persisted? = t 'title.edit', :resource_name => resource_class.model_name.human

    - else = t 'title.new.male', :resource_name => resource_class.model_name.human = form_for @person, :remote => true do |f| %fieldset = f.label :number, "Qual o número de registro?" %br = f.text_field :number, :autofocus => true, :size => 25 %fieldset = f.label :created_at, "Data de cadastro:" %br = f.text_field :created_at, :disabled => true, :size => 10 %fieldset = f.label :start_date, "Início:" = f.text_field :start_date, :size => 10 e = f.label :start_date, "Fim:" = f.text_field :created_at, :size => 10 %fieldset = f.label "Informe nº do processo desta pessoa" %br = f.text_field :process_number, :size => 20, :maxlength => 20
  9. %h2 - if resource.persisted? = t 'title.edit', :resource_name => resource_class.model_name.human

    - else = t 'title.new.male', :resource_name => resource_class.model_name.human = semantic_form_for resource, :remote => true do |f| = f.inputs do = f.input :number, :input_html => { :autofocus => true, :size => 25, :maxlength => 20, :disabled => !resource. = f.input :created_at, :as => :string, :input_html => { :disabled => true, :size => 10, ... = f.input :start_date, :as => :string, :input_html => { :size => 10, :disabled => !resource.updatable? } = f.input :end_date, :as => :string, :input_html => { :size => 10, :disabled => !resource.updatable? } = f.input :number_process, :input_html => { :size => 20, :maxlength => 20, :disabled => !resource.updatable? }
  10. FAIL Automação e DRY excessiva sem uma visão holistica do

    projeto e em uma fase ainda nebulosa para se preocupar com padrões.
  11. TDD BDD TAFT DRY NOSQL RUBY FUNCTIONAL OOP MVC REST

    DDD SPIKE PAIR PROG. CONTINUOUS DEPLOY CONTINUOUS DEPLOY RAILS CONT. INTEGRATION FAST TESTS PRESENTERS DISTRIBUTED TDD & BDD
  12. describe "#release" do context "an occupied bed" do before do

    bed.status = :occupied end context 'when normal' do before do bed.extra = false end it "should make it available" do bed.release bed.should be_available end end context 'when extra' do before do bed.extra = true end it "should disable it" do bed.release bed.should_not be_enabled end end end end CONVENÇÕES
  13. describe "#release" do context "an occupied bed" do before do

    bed.status = :occupied end context 'when normal' do before do bed.extra = false end it "should make it available" do bed.release bed.should be_available end end context 'when extra' do before do bed.extra = true end it "should disable it" do bed.release bed.should_not be_enabled end end end end CONVENÇÕES
  14. describe "status of bed" do it "becomes available when releasing

    a normal bed" do bed.status = :occupied bed.extra = false bed.release bed.should be_available end it "is disabled when releasing an extra bed" do bed.status = :occupied bed.extra = true bed.release bed.should_not be_enabled end end
  15. describe "status of bed" do #### OCUPAÇÃO (availabe, occupied) it

    "becomes available when releasing a normal bed" do bed.status = :occupied bed.extra = false bed.release bed.should be_available end #### STATUS (enabled / disabled) it "is disabled when release an extra bed" do bed.status = :occupied bed.extra = true bed.release bed.should_not be_enabled end end
  16. it { should validate_presence_of :street} it { should validate_presence_of :number}

    it 'should validate presence of number complement if have complement and is not a house' do subject.should_not validate_presence_of :number_complement subject.complement = Complement::HOUSE subject.should_not validate_presence_of :number_complement subject.complement = Complement::APARTMENT subject.should validate_presence_of :number_complement end it 'to_s should be the street name, number and neighborhood name' do subject.street = Street.new(:name => "amazonas", :street_type => StreetType::AVENIDA) subject.street.neighborhood = Neighborhood.new(:name => "centro") subject.number = '100' subject.to_s.should == 'AVENIDA AMAZONAS, 100 - CENTRO' end it 'number should be greather than or equal 0' do subject.number = -100 subject.should have(1).errors_on(:number) subject.number = 100 subject.should have(:no).errors_on(:number) end
  17. it { should validate_presence_of :street} it { should validate_presence_of :number}

    it 'should validate presence of number complement if have complement and is not a house' do subject.should_not validate_presence_of :number_complement subject.complement = Complement::HOUSE subject.should_not validate_presence_of :number_complement subject.complement = Complement::APARTMENT subject.should validate_presence_of :number_complement end it 'to_s should be the street name, number and neighborhood name' do subject.street = Street.new(:name => "amazonas", :street_type => StreetType::AVENIDA) subject.street.neighborhood = Neighborhood.new(:name => "centro") subject.number = '100' subject.to_s.should == 'AVENIDA AMAZONAS, 100 - CENTRO' end it 'number should be greather than or equal 0' do subject.number = -100 subject.should have(1).errors_on(:number) subject.number = 100 subject.should have(:no).errors_on(:number) end T.A.T.F.T.
  18. AUTOMATED TESTS / BDD / TDD Aprox. 25 min p/

    rodar testes dependentes falsa confiança falhas intermitentes testando áreas desnecessárias
  19. AUTOMATED TESTS / BDD / TDD Aprox. 25 min p/

    rodar testes dependentes falsa confiança falhas intermitentes testando áreas desnecessárias
  20. Kent Beck “... my philosophy is to test as little

    as possible to reach a given level of confidence ... If I don’t typically make a kind of mistake, I don’t test for it ...”
  21. Outro cenário • 3 anos em desenvolvimento • App Rails

    2.3 • Várias apps C++ • Zero testes • Quantidade gigante de duplicação • Problemas graves de arquitetura • Performance caminhando para a morte
  22. def new @thing = Thing.new(params_for_testing) respond_with @thing end def params_for_testing

    if Rails.env.development? { name: "blaah" } else {} end end TESTE MANUAL
  23. TDD BDD TAFT DRY NOSQL RUBY FUNCTIONAL OOP MVC REST

    DDD SPIKE PAIR PROG. CONTINUOUS DEPLOY CONTINUOUS DEPLOY RAILS CONT. INTEGRATION FAST TESTS PRESENTERS DISTRIBUTED PATTERNS & PRINCÍPIOS
  24. “ The most disastrous thing about programming: extracting patterns from

    today's programming practices ennobles them in a way they don't deserve ” Alan Kay http://bit.ly/Mg6u3K
  25. SPRINTS DE 2 SEMANAS . 5 PONTOS P/ PESSOA .

    CONTINUOUS DELIVERY . BURNDOWN CHART . ☑ ☑ ☑ ☑ Boas práticas BACKLOG DETALHADO . ☑
  26. 1 - NOVICES * pouca experiência * sem interesse em

    aprender * preocupados objetivo imediato. * Não conseguem inferir os passos * Mas conseguem seguir uma lista Exemplo, um cozinheiro aprendiz, imposto de renda...
  27. 1 - NOVICES 2 - ADVANCED BEGINERS * alguma experiência,

    * infere alguns principios Mas * não quer o big picture * Problemas geram desespero. ex. CEO meeting w/ projections.
  28. 1 - NOVICES 2 - ADVANCED BEGINERS 3 - COMPETENT

    * infere padrões baseado em modelos anterirores * consegue enfretar problemas q nunca aconteceram. * consegue procurar e ouvir conselhos * noções de ações associadas a objetivos * mas ainda com dificuldade de identificar onde focar * e precisa de planejamento extensivo Normalmente descrito como o cara que tem inciativa na equipe.
  29. 1 - NOVICES 2 - ADVANCED BEGINERS 3 - COMPETENT

    4 - PROFICIENT * Precisa do big-picture * Pois tem uma visão holistica * Alta capacidade de focar por importância * Consegue aprender com situações dos outros * Mas adaptando ao contexto * Com grande capacidade de auto-correção
  30. 1 - NOVICES 2 - ADVANCED BEGINERS 3 - COMPETENT

    4 - PROFICIENT 5 - EXPERT Não possui necessidade de regras, guidelines ou máximas Entende a situação como um todo intuitivamente Baseando sua intuição vasta experiência Tem visão do que é possível Consegue transpor dificuldades em novos problemas Age quase como mágica Ex. Médico Podemos perceber claramente que pessoas em Dreyfus 2 e 3 precisam de regras mas práticas como Agile estão fortemente ligadas a adaptação.