Object Oriented Programming

206 views
172 views

Published on

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

It is shown

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
206
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Object Oriented Programming

  1. 1. ORIENTAÇÃO AOBJETOS17 e 19 de Abrilmarcoafilho@gmail.commarcoafilho@marcoafilho
  2. 2. LICENÇA
  3. 3. MARCO ANTONIOFILHOCOORDENADOR DE TI INPACT.ME
  4. 4. UM POUCODE RUBY
  5. 5. 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  +=  
  6. 6. 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  
  7. 7. APLICAÇÃO SIMPLESputs  "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        
  8. 8. EXERCÍCIOOBJETIVOCriar 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.rb15 MIN
  9. 9. UM POUCODE ARQUITETURA
  10. 10. MVCMODELS- Representam os modelos do sistemaCONTROLLERS- Representam as ações do sistemaVIEWS- Interfaces resultantes de açõesASSETS- Arquivos auxiliares (images, js, css)BIN- Arquivo bináriosLIB- Módulos auxiliares
  11. 11. 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:
  12. 12. EXERCÍCIOOBJETIVOConstruir a sua arquiteturaMÉ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
  13. 13. BATALHADE CONCEITOS
  14. 14. CONCEITOS DE OOClasseAtributosMétodosCharacternamestrskillattack()defend()stringintintCharacter #2namestrskillattack()defend()James32Character #1namestrskillattack()defend()Marc24Character #3namestrskillattack()defend()Leon13INSTÂNCIAS
  15. 15. CLASSESClasseAtributosMétodosDungeonnametypestringstringDungeon #2nametypeGarliaPrisonDungeon #1nametypeSyrusCastleINSTÂNCIAS
  16. 16. CLASSES ESTÁTICASDiesides intself.roll()Não pode ser instanciada!Só há um dado no jogo
  17. 17. 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
  18. 18. INTERACTIVE RUBY$  irb  -­‐Ibin  -­‐rsave_the_princess  >  Die.roll  =>  4  Ambiente interativo para desenvolvimento e teste de comandos em Ruby
  19. 19. 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!
  20. 20. 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
  21. 21. EXERCÍCIOOBJETIVOEscrever 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
  22. 22. CONSTRUTORESclass  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  =  ...  
  23. 23. 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  
  24. 24. HERANÇACharacternamestrskillattack()defend()stringintintKnightslash()Priestheal()Archerfire_arrow()SUB-CLASSESINSTÂNCIAS
  25. 25. HERANÇAclass  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>  
  26. 26. EXERCÍCIOOBJETIVOEscrever 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 disponibilizarpara a aplicação, sem ter a necessidade de criar toda vez que é inicializada.50 MIN#  bin/save_the_princess.rb  @characters  =  [Character.new  ...,  ...]  
  27. 27. MODIFICADORES DE ACESSOclass  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  
  28. 28. QUE A BATALHACOMECE!!!
  29. 29. Battle...start()start_round()start_turn()COESÃO E ACOPLAMENTOfazendo mais do que deveria == baixa coesão
  30. 30. Battle...start()COESÃO E ACOPLAMENTOmuitas dependências == alto acoplamentoRound...start()Turn...start()
  31. 31. Battle...start()ALTA COESÃO E BAIXO ACOPLAMENTORound...start()Turn...start()Importante! Ruby não possui interfaces. É necessário implementar uma solução.OBJETIVOClasse deve fazer o que propõeClasse deve possuir o mínimo de relacionamento possível
  32. 32. A BATALHAREGRAS1. 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;
  33. 33. 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  
  34. 34. EXERCÍCIOOBJETIVOEscrever a classe Battle e todas as suas dependências;MÉTODO§  Desenvolva as classes Turn, Round e Battle nesta ordem;30 MIN
  35. 35. EXERCÍCIOOBJETIVOAdicionar 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
  36. 36. BOASPRÁTICAS
  37. 37. 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  
  38. 38. 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  
  39. 39. CharacterCONVENTION OVER CONFIGURATIONcharacter.rb charactersNome de arquivo Nome de classe Nome de tabela§  ClassesEmCamelCase;§  variaveis_e_funcoes_sempre_minusculas;§  CONSTANTES_SEMPRE_MAIUSUCLAS;
  40. 40. DOCUMENTERDOCDocumentar 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  
  41. 41. EXERCÍCIOOBJETIVORefatorar 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
  42. 42. EXERCÍCIOOBJETIVOClasse 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 uminimigo aleatório, assim como, o time desafiado (opponent) deve ter uma rodada para cadaintegrante 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  
  43. 43. DÚVIDAS?? ????????? ?
  44. 44. MUITO OBRIGADO!marcoafilho@gmail.commarcoafilho@marcoafilho

×