Object Oriented Programming

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

description

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

Transcript of Object Oriented Programming

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