Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Object Oriented Programming

275 views

Published on

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

It is shown

  • Be the first to comment

  • Be the first to like this

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

×