@danielvlopes @jeffrydegrande - static.eventials.com · rest ddd spike pair prog. continuous deploy...
TRANSCRIPT
...
@danielvlopes @jeffrydegrande
SOFTWARE DEVLOPMENTDA FORMA CERTA !!!
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☑
SH*T HAPPENS
FORA DE CONTROLE
COMPORTAMENTO DA EQUIPE
COMPORTAMENTO INDIVIDUAL
COMPORTAMENTO INDIVIDUAL
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
DISTRIBUTEDDRY & 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.updatable?
%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.updatable?
%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.updatable? } = 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? }
VIEW? DRY !
MANUTENÇÃO
CRIAÇÃO1º
2º
=== LANÇAMENTO ===
ADAPTAÇÃO
DESCOBERTA
EVOLUÇÃO
1º
2º
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
DISTRIBUTEDTDD & 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
endend
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
endend
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
AUTOMATED TESTS / BDD / TDD
Aprox. 25 min p/ rodar
testes dependentesfalsa confiançafalhas intermitentes
testando áreas desnecessárias
AUTOMATED TESTS / BDD / TDD
Aprox. 25 min p/ rodar
testes dependentesfalsa confiançafalhas intermitentes
testando áreas desnecessárias
O QUE EU DEVO TESTAR?
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
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
AUTOMATED TESTS
ACCEPTANCE TESTS
BABY STEPS
AUTOMATED TESTS
ACCEPTANCE TESTS
BABY STEPS
TESTE MANUAL
BIG STEPS + REWRITES PARCIAIS
AUTO. TEST APÓS RAILS 3
def new @thing = Thing.new(params_for_testing) respond_with @thingend
def params_for_testing if Rails.env.development? { name: "blaah" } else {} endend
TESTE MANUAL
EXCELENTES RESULTADOS
TDD BDD TAFT DRY
NOSQL
RUBY
FUNCTIONAL
OOP
MVC
REST DDD
SPIKE
PAIR PROG.
CONTINUOUS DEPLOY
CONTINUOUS DEPLOY
RAILS CONT. INTEGRATION
FAST TESTS PRESENTERS
DISTRIBUTEDPATTERNS & PRINCÍPIOS
LAW OF DEMETER
VISITORFACADE
OBSERVERPRESENTER
SINGLE RESPONSIBILITY
COMPOSITION
MVC
MOVE
MEDIATOR
PROXY
CHRISTOPHER ALEXANDER
Padrões e práticas atemporais derivadas de 2.000 anos de
arquitetura.
“ 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
COMPORTAMENTO DA EQUIPE
AgileTM
AgileTM
Time e cliente na mesma páginamantendo flexibilidade
Equipe
Cod. conduta
SUCESSO=
SPRINTS DE 2 SEMANAS .
5 PONTOS P/ PESSOA .
CONTINUOUS DELIVERY .
BURNDOWN CHART .
☑☑☑☑
Boas práticas
BACKLOG DETALHADO .☑
FAIL
Por que funciona para alguns mas não funciona para mim ?
DREYFUS MODEL
http://pragprog.com/book/ahptl/pragmatic-thinking-and-learning
visão do contexto
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 - EXPERTNão possui necessidade de regras, guidelines ou máximasEntende a situação como um todo intuitivamenteBaseando sua intuição vasta experiênciaTem visão do que é possívelConsegue transpor dificuldades em novos problemasAge quase como mágica
Ex. Médico
AGORA, SABEMOS AS RAZÕES
vamos refletir...
PRÁTICAS sem contexto
apropriado resultam em
DÓGMAS
DOGMAS são oriundos de equipes com pouca experiência.
DÓGMAS levam a falha técnica.
e com EGO inflado tudo
é feito CERTO DE PRIMEIRA
EM EQUIPES SEM EXPERIÊNCIA,
ITERAÇÃO
EVOLUÇÃOé diferente de
mas
RUÍDO c/ coisas
triviais esconde que
SOFTWARE É DIFÍCIL
e o
EVOLUÇÃOmas
tem custos !
TIME MULTI-DISCIPLINAR
EVOLUÇÃO+
IMPOSSÍVEL FALHA TÉCNICA
Já falhas como empreendimento já é outra história.
@danielvlopes @jeffrydegrande
MUITO OBRIGADO