Share
Embed
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
Transcript
74 slides
-
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 ☑ -
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 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 -
<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 %> -
%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 -
%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 -
%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 -
%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? } -
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. -
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 -
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 -
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 -
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 -
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 -
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 -
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. -
AUTOMATED TESTS / BDD / TDD Aprox. 25 min p/
rodar testes dependentes falsa confiança falhas intermitentes testando áreas desnecessárias -
AUTOMATED TESTS / BDD / TDD Aprox. 25 min p/
rodar testes dependentes falsa confiança falhas intermitentes testando áreas desnecessárias -
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 ...” -
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 -
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 -
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 -
LAW OF DEMETER VISITOR FACADE OBSERVER PRESENTER SINGLE RESPONSIBILITY COMPOSITION
MVC MOVE MEDIATOR PROXY -
“ 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 -
SPRINTS DE 2 SEMANAS . 5 PONTOS P/ PESSOA .
CONTINUOUS DELIVERY . BURNDOWN CHART . ☑ ☑ ☑ ☑ Boas práticas BACKLOG DETALHADO . ☑ -
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... -
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. -
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. -
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 -
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. -
e com EGO inflado tudo é feito CERTO DE PRIMEIRA
EM EQUIPES SEM EXPERIÊNCIA,