44
ORIENTAÇÃO A OBJETOS 17 e 19 de Abril [email protected] marcoafilho @marcoafilho

Object Oriented Programming

Embed Size (px)

DESCRIPTION

Second part of the Agile Development with Ruby on Rails course for the Computer's Science junior enterprise. It is shown

Citation preview

Page 1: Object Oriented Programming

ORIENTAÇÃO A OBJETOS

17 e 19 de Abril

[email protected]

marcoafilho

@marcoafilho

Page 2: Object Oriented Programming

LICENÇA

Page 3: Object Oriented Programming

MARCO ANTONIO FILHO

COORDENADOR DE TI INPACT.ME

Page 4: Object Oriented Programming

UM POUCO DE RUBY

Page 5: Object Oriented Programming

10 COISAS SOBRE RUBY #  1.  Tudo  eh  um  objeto  5.times  {  print  "Hello  World!"  }    #  2.  Blocos    sample_array.each  {  |element|  print  element  }    #  3.  Retorno  de  funcao  implicito    def  sum(a,b)      a  +  b  end    #  4.  Tudo  eh  aberto    class  Fixnum      def  previous          self  –  1      end  end  6.previous      #  5.  Operadores  unarios.  Nao  ha  ++,  -­‐-­‐;  Use  +=  

Page 6: Object Oriented Programming

10 COISAS SOBRE RUBY #  6.  Atribuicao  paralela  a,  b  =  b,  a    #  7.  Cada  string  é  um  objeto  print  "hello".object_id  print  "hello".object_id  #  Um  novo  objeto    #  8.  Verdadeiro  e  falso  em  Ruby  if  0      print  "Hello  World"  end    #  9.  Suporte  a  faixa  de  numeros  e  expressoes  regulares  de  forma  nativa  (1..10).each  {  print  "Hello  World"  }    #  10.  Indicadores  de  metodo  class  Woman      def  loves?(thing)          thing  ==  "chocolate"  ?  true  :  false      end  end  

Page 7: Object Oriented Programming

APLICAÇÃO SIMPLES puts  "Welcome!  What  do  you  want  to  be?"  #  Imprime  na  tela  choice  =  gets.strip  #  Lê  do  teclado  e  remove  \n    if  choice  ==  "Knight"  #  Comparacao  em  if      puts  "Then  a  princess  you  must  save"  elsif  choice  ==  "Wizard"  #  Else  if  com  condicao      puts  "Then  a  book  you  must  find"  else      puts  "Just  stay  at  home"  end    puts  "What  is  your  strength?"    choice  =  gets.to_i  #  Le  do  teclado  e  converte  para  int  damage  =  choice.times.collect  do  

 rand(6)  +  1  end.inject(:+)  puts  "You  did  #{damage}  damage"  #  String  com  interpolacao        

Page 8: Object Oriented Programming

EXERCÍCIO OBJETIVO

Criar o primeiro programa em Ruby: Calculadora de dano.

MÉTODO

§  Crie arquivo calculator.rb;

§  Leia do teclado a força e depois leia a armadura;

§  Para cada unidade de força jogue um dado de seis lados. A soma é o valor de ataque;

§  Para cada unidade de armadura jogue um dado de seis lados. A soma é o valor de defesa;

§  A subtração do ataque com a defesa é o dano total. Apresente este resultado;

§  Para executar o programa no terminal execute ruby calculator.rb

15 MIN

Page 9: Object Oriented Programming

UM POUCO DE ARQUITETURA

Page 10: Object Oriented Programming

MVC

MODELS - Representam os modelos do sistema CONTROLLERS - Representam as ações do sistema VIEWS - Interfaces resultantes de ações ASSETS - Arquivos auxiliares (images, js, css) BIN - Arquivo binários LIB - Módulos auxiliares

Page 11: Object Oriented Programming

INICIALIZAÇÃO #  bin/nome_da_aplicacao.rb  libs  =  [      File.expand_path('../../lib',  __FILE__),          File.expand_path('../../app',  __FILE__)  ]  $LOAD_PATH.unshift  *Dir.glob(libs)    require  "nome_da_aplicacao"  

#  lib/nome_da_aplicacao.rb  #  inicialmente  vazio  

$  ruby  bin/nome_da_aplicacao.rb  

Para executar faça uso do seguinte comando no terminal:

Page 12: Object Oriented Programming

EXERCÍCIO OBJETIVO

Construir a sua arquitetura

MÉTODO

§  A partir dos conceitos dados monte a sua arquitetura MVC;

§  Crie o arquivo de inicialização da aplicação;

§  Crie o arquivo de gerenciamento de dependências;

§  Para testar coloque um comando para escrita na tela no arquivo de dependências;

§  Execute;

§  Se funciona, apague a linha usada o comando de escrita na tela;

5 MIN

Page 13: Object Oriented Programming

BATALHA DE CONCEITOS

Page 14: Object Oriented Programming

CONCEITOS DE OO Classe

Atributos

Métodos

Character name str skill

attack() defend()

string int int

Character #2

name str skill

attack() defend()

James 3 2

Character #1 name str skill

attack() defend()

Marc 2 4

Character #3 name str skill

attack() defend()

Leon 1 3

INSTÂNCIAS

Page 15: Object Oriented Programming

CLASSES Classe

Atributos

Métodos

Dungeon name type

string string

Dungeon #2

name type

Garlia Prison

Dungeon #1 name type

Syrus Castle

INSTÂNCIAS

Page 16: Object Oriented Programming

CLASSES ESTÁTICAS Die

sides int

self.roll()

Não pode ser instanciada! Só há um dado no jogo

Page 17: Object Oriented Programming

MÓDULOS EM RUBY #  lib/save_the_princess/die.rb  class  Die      @@sides  =  6        #  Roll  the  die      #  You  can  change  the  amount  of  sides.  Default  is  6.      def  self.roll(sides  =  @@sides)          rand(6)  +  1      end  end  

#  lib/save_the_princess.rb  require  "save_the_princess/die.rb"  

Adicionar classe à lista de dependências

Page 18: Object Oriented Programming

INTERACTIVE RUBY

$  irb  -­‐Ibin  -­‐rsave_the_princess  >  Die.roll  =>  4  

Ambiente interativo para desenvolvimento e teste de comandos em Ruby

Page 19: Object Oriented Programming

CLASSES EM RUBY #  app/models/character.rb  class  Character      #  Character  profile  attributes      attr_accessor  :name      attr_accessor  :strength,  :skill,  :resistance,  :armor,  :fire_power            #  The  sum  of  the  amount  of  strength  die  rolls.      def  attack          strength.times.collect  do                Die.roll          end.inject(:+)      end        #  The  sum  of  the  amount  of  armor  die  rolls.      def  defend          armor.times.collect  do              Die.roll          end.inject(:+)      end  end  

LEMBRE-SE DE ADICIONAR A DEPENDÊNCIA!

Page 20: Object Oriented Programming

INTERACTIVE RUBY

$  irb  -­‐Ibin  -­‐rsave_the_princess  >  character  =  Character.new  >  character.name  =  "Marc"  >  character.name  =>  "Marc"  >  character.strength  =  3  >  character.attack  =>  15  >  character.defend  NoMethodError:  undefined  method  `times'  for  nil:NilClass  

#  lib/save_the_princess.rb  require  "save_the_princess/die.rb"  require  "models/character.rb"    

LEMBRETE

Page 21: Object Oriented Programming

EXERCÍCIO OBJETIVO

Escrever as classes Die e Character;

MÉTODO

§  Na classe Die deve existir o método self.roll representando um jogar de dados;

§  Na classe Character defina os seus atributos e os métodos attack e defend;

§  Execute no IRB;

§  Em Character adicione um método para calcular a vida do personagem:

§  O método calculate_health_points é baseado na resistência do usuário;

§  É necessário guardar a vida em um atributo chamado max_health_points;

30 MIN

Page 22: Object Oriented Programming

CONSTRUTORES class  Character        ...      attr_accessor  :max_health_points            #  Character  constructor.  Sets  the  attributes  default  values.      def  initialize(params  =  {})          @name              =  params[:name]  ||  ""          @strength      =  params[:strength]  ||  0          @skill            =  params[:skill]  ||  0          @resistance  =  params[:resistance]  ||  0          @armor            =  params[:armor]  ||  0          @fire_power  =  params[:fire_power]  ||  0                    calculate_max_health_points      end  end  

self.name  =  @name  =  ...  

Page 23: Object Oriented Programming

INTERACTIVE RUBY

$  irb  -­‐Ibin  -­‐rsave_the_princess  >  c  =  Character.new  name:  "Marc",  strength:  2,  skill:  4,  resistance:  2  =>  #<Character:0x007fcf2210f3d0  @name="Marc",  @strength=2,  @skill=4,  @resistance=2,  @armor=0,  @fire_power=0,  @max_health_points=12>  >  c.name  =>  "Marc"  >  c.max_health_points  =  200  >  c.max_health_points  200  

Page 24: Object Oriented Programming

HERANÇA Character

name str skill

attack() defend()

string int int

Knight

slash()

Priest

heal()

Archer

fire_arrow()

SUB-CLASSES

INSTÂNCIAS

Page 25: Object Oriented Programming

HERANÇA class  Knight  <  Character            #  Do  an  attack  with  a  bonus  of  3      def  slash          attack  +  3      end  end  

$  irb  -­‐Ibin  -­‐rsave_the_princess  >  k  =  Knight.new  name:  "Marc",  strength:  2,  skill:  4,  resistance:  2  =>  #<Knight:0x007ffcf280e750  @name="Marc",  @strength=2,  @skill=4,  @resistance=2,  @armor=0,  @fire_power=0,  @max_health_points=8>  >  k.slash  =>  9  >  c  =  Character.new  name:  "James",  strength:  3,  skill:  2,  resistance:  1  =>  #<Character:0x007f93a30f90e0  @name="James",  @strength=3,  @skill=2,  @resistance=1,  @armor=0,  @fire_power=0,  @max_health_points=3>  >  c.slash  NoMethodError:  undefined  method  `slash'  for  #<Character:0x007f93a30f90e0>  

Page 26: Object Oriented Programming

EXERCÍCIO OBJETIVO

Escrever a classe Dungeon e as classes filhas de Character;

MÉTODO

§  Com o que já aprendeu construa a classe Dungeon, com seu nome e tipo;

§  Combine com o colega ao lado quais classes filhas cada um vai escrever;

§  Escreva as classes e partilhe com o seu colega;

§  No arquivo de inicialização carregue um array de personagens e masmorras para disponibilizar para a aplicação, sem ter a necessidade de criar toda vez que é inicializada.

50 MIN

#  bin/save_the_princess.rb  @characters  =  [Character.new  ...,  ...]  

Page 27: Object Oriented Programming

MODIFICADORES DE ACESSO class  Character        ...      attr_reader  :max_health_points            private      #  Calculate  max  health  based  on  resistance.      def  calculate_max_health_points          ...      end  end  

>  c  =  Character.new  name:  "James",  strength:  3,  skill:  2,  resistance:  1  =>  #<Character>  >  c.max_health_points  =  1000  NoMethodError:  undefined  method  `max_health_points='  for  #<Character>  >  c.calculate_max_health_points  NoMethodError:  private  method  `calculate_max_health_points'  called  for  #<Character>  >  c.max_health_points  5  

Page 28: Object Oriented Programming

QUE A BATALHA COMECE!!!

Page 29: Object Oriented Programming

Battle

...

start() start_round() start_turn()

COESÃO E ACOPLAMENTO

fazendo mais do que deveria == baixa coesão

Page 30: Object Oriented Programming

Battle

...

start()

COESÃO E ACOPLAMENTO

muitas dependências == alto acoplamento

Round

...

start()

Turn

...

start()

Page 31: Object Oriented Programming

Battle

...

start()

ALTA COESÃO E BAIXO ACOPLAMENTO

Round

...

start() Turn

...

start()

Importante! Ruby não possui interfaces. É necessário implementar uma solução.

OBJETIVO Classe deve fazer o que propõe Classe deve possuir o mínimo de relacionamento possível

Page 32: Object Oriented Programming

A BATALHA

REGRAS

1. Iniciativa: Joga-se um dado. Aquele que obtiver maior valor ataca primeiro. Caso igual joga-se de novo;

2. Ataque: Caso seja um ataque normal, seguir para 3, senão fazer um teste de habilidade;

3. Dano: A soma resultante de lances de dados equivalente à força ou poder de fogo;

4. Defesa: A soma resultante de lances de dados equivalente à defesa. Valor do dano é subtraído;

5. Pontos de vida: O dano que ultrapassa a soma da Armadura é subtraído de seus pontos de vida;

6. Retaliação: Se ainda estiver vivo, o lutador que foi atacado revida e os passos 2 a 4 são repetidos;

Page 33: Object Oriented Programming

CLASSES DE COMBATE #  app/models/battle.rb  class  Battle      attr_accessor  :challenger,                                  :opponent        #  Armazena  os  combatentes      def  initialize(params  =  {})      end        #  Instancia  rodadas  até  que        #  os  pontos  de  vida  de  um        #  pesonagem  chegue  a  zero.        #  Recupera  os  combatentes.      def  start      end  end  

#  app/models/battle.rb  class  Battle::Round      attr_accessor  :challenger,                                  :opponent        #  Armazena  os  combatentes      def  initialize(params  =  {})      end        #  Verifica  quem  terá  a        #  iniciativa  e  istancia        #  turnos.        def  start      end  end  

#  app/models/battle.rb  class  Battle::Round::Turn      attr_accessor  :attacker,                                  :defender        #  Armazena  os  combatentes      def  initialize(params  =  {})      end        #  Calcula  o  dano  feito  em        #  combate.      def  start      end  end  

Page 34: Object Oriented Programming

EXERCÍCIO OBJETIVO

Escrever a classe Battle e todas as suas dependências;

MÉTODO

§  Desenvolva as classes Turn, Round e Battle nesta ordem;

30 MIN

Page 35: Object Oriented Programming

EXERCÍCIO OBJETIVO

Adicionar class Team. Uma dungeon pode ter vários times;

MÉTODO §  Desenvolver uma classe Team que tem um nome e um vetor de Characters;

§  Adicione ao método initialize da Dungeon para receber times de oponentes como parâmetro;

§  Crie um método visit para Team que receba uma Dungeon como parâmetro;

§  Nesse método os oponentes presentes naquela dungeon devem ser enfrentados;

§  O vencedor será a batalha entre o primeiro do time 1 luta contra o primeiro do time 2;

2 HORAS

Page 36: Object Oriented Programming

BOAS PRÁTICAS

Page 37: Object Oriented Programming

DON’T REPEAT YOURSELF (DRY) #  app/models/character.rb  class  Character      ...            #  The  sum  of  the  amount  of  strength  die  rolls.      def  attack          [strength,  fire_power].max.times.collect  do                Die.roll          end.inject(:+)      end        #  The  sum  of  the  amount  of  armor  die  rolls.      def  defend          armor.times.collect  do              Die.roll          end.inject(:+)      end  end  

Page 38: Object Oriented Programming

DON’T REPEAT YOURSELF (DRY) #  app/models/character.rb  class  Character      ...            #  The  sum  of  the  amount  of  strength  die  rolls.      def  attack          roll_die_for  [strength,  fire_power].max      end        #  The  sum  of  the  amount  of  armor  die  rolls.      def  defend          roll_die_for  armor      end        protected      def  roll_die_for(attribute)          attribute.times.map{  Die.roll  }.inject(:+)      end  end  

Page 39: Object Oriented Programming

Character

CONVENTION OVER CONFIGURATION character.rb characters

Nome de arquivo Nome de classe Nome de tabela

§  ClassesEmCamelCase; §  variaveis_e_funcoes_sempre_minusculas; §  CONSTANTES_SEMPRE_MAIUSUCLAS;

Page 40: Object Oriented Programming

DOCUMENTE RDOC

Documentar a aplicação em Ruby é simples:

$  rdoc  -­‐-­‐all  Parsing  sources...  100%  [12/12]    UTF-­‐8                                                                                                                            Generating  Darkfish  format  into  /Users/marco/Projects/Rails/save-­‐the-­‐princess/doc...  Files:            12  Classes:        10  (10  undocumented)  Modules:          1  (  1  undocumented)  Constants:      1  (  1  undocumented)  Attributes:  21  (20  undocumented)  Methods:        38  (33  undocumented)  Total:            71  (65  undocumented)      8.45%  documented  Elapsed:  0.8s  

Page 41: Object Oriented Programming

EXERCÍCIO OBJETIVO

Refatorar a classe Battle e seus sub-módulos;

MÉTODO §  Simplificar as funções das classes criando classes mais específicas;

§  Garantir que a classe funciona da mesma forma;

§  Gere a documentação do seu projeto com RDoc;

1 HORA

Page 42: Object Oriented Programming

EXERCÍCIO OBJETIVO

Classe Battle deve prover batalhas entre times;

MÉTODO §  Alterar a classe Battle para receber dois times (ao invés de characters);

§  Para cada personagem no time desafiante (challenger) deve ser feita uma rodada escolhendo um inimigo aleatório, assim como, o time desafiado (opponent) deve ter uma rodada para cada integrante escolhendo um adversário aleatório;

§  Tente fazer o mínimo de alterações nas classes Turn e Round;

4 HORAS

#  Dica  @challengers.each  do  |challenger|      Round.new  challenger:  challenger,  opponent:  @opponents.shuffle[0]  end  

Page 43: Object Oriented Programming

DÚVIDAS

? ? ?

?

?

? ?

? ?

?

? ?

Page 44: Object Oriented Programming

MUITO OBRIGADO!

[email protected]

marcoafilho

@marcoafilho