Lab5 Marcus Edson

aluno: Nome do Aluno
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 06/08/2008 (2)

Introdução

Nessa prática foi criado um programa que implementa um bolão virtual. Recebemos o programa parcialmente feito e tivemos que realizar algumas melhorias bem como desenvolvemos o servidor para esta aplicação.

Desenvolvimento

Primeiro mostraremos as melhorias realizadas no código:

Melhoria nos decorators de thread safety

Foram criados esses 2 decorators de modo que os objetos das classes Match e MatchList pudesse ser decorados e se tornassem seguros, de modo que dois usuários não possam chamar métodos de uma dessas duas classes ao mesmo tempo.

require 'monitor'
module Decorators
  class MatchThreadSafeDecorator < Decorator
    include MonitorMixin
 
    def make_bet(*args)
      synchronize do
        @decorated.make_bet(*args)
      end
    end
 
    def finalize(*args)
      synchronize do
        @decorated.finalize(*args)
      end
    end
 
  end
end
require 'decorators/match_thread_safe_decorator'
module Decorators
  class MatchListThreadSafeDecorator < Decorator
    include MonitorMixin
 
    def initialize(decorated)
      super
      old_match_decorator = self.decorated.item_decorator
      self.decorated.item_decorator = lambda do |match|
        MatchThreadSafeDecorator.new( old_match_decorator.call(match) )
      end
    end
 
    def add(*args)
      synchronize do
        @decorated.add(*args);
      end
    end
  end
end

Melhoria nos decorators de persistencia

Foram criados os decorators de persistencia de modo que as informações das partidas pudessem ser salvas em um arquivo .yml.

require 'monitor'
require 'yaml'
module Decorators
  class MatchPersistanceDecorator < Decorator
 
    def initialize(obj, match_list)
      super obj
      @list=match_list
    end
 
    def make_bet(*args)
      x=@decorated.make_bet(*args)
      @list.save
      x
    end
 
    def finalize(*args)
      x=@decorated.finalize(*args)
      @list.save
      x
    end
 
  end
end
require 'yaml'
require 'decorators/list_persistance_decorator'
require 'decorators/match_persistance_decorator'
module Decorators
  class MatchListPersistanceDecorator < ListPersistanceDecorator
 
    def initialize(decorated, filename)
      super(decorated, filename)
      old_match_decorator = self.decorated.item_decorator
      self.decorated.item_decorator = lambda do |match|
        MatchPersistanceDecorator.new( old_match_decorator.call(match), self )
      end
    end
 
  end
end

Criação dos Builders de MatchList e UserList

Foi utilizado o padrão de projeto "Builder" para criar essas duas classes, de modo que possamos instanciar mais facilmente objetos dessas classes e possamos decorá-los (com thread safety, persistance ou logger) de acordo com o nosso desejo. O código das duas classes é msotrado abaixo:

module Builders
class MatchListBuilder
 
  #attr_reader :match_list
 
  def initialize
    @match_list=MatchList.new
    @added_persistance=false
  end
 
  def add_persistance
    @added_persistance=true
    @match_list=MatchListPersistanceDecorator.new(@match_list, "match_list.yml")
  end
 
  def add_logging
    @match_list=MatchListLoggerDecorator.new(@match_list)
  end
 
  def add_thread_safety
    @match_list=MatchListThreadSafeDecorator.new(@match_list)
  end
 
  def add_all
    @added_persistance=true
    self.add_persistance
    self.add_logging
    self.add_thread_safety
  end
 
  def match_list
    @match_list.load_list if @added_persistance
    @match_list
  end
 
end
end
module Builders
class UserListBuilder
 
  attr_reader :user_list 
 
  def initialize()
    @user_list=UserList.new
  end
 
  def add_persistance
    @user_list=ListPersistanceDecorator.new(@user_list, "user_list.yml")
  end
 
  def add_logging
    @user_list=UserListLoggerDecorator.new(@user_list)
  end
 
  def add_thread_safety
    @user_list=ListThreadSafeDecorator.new(@user_list)
  end
 
  def add_all
    self.add_persistance
    self.add_logging
    self.add_thread_safety
  end
 
end
end

Criação do RequestReader

Foi utilizado a biblioteca yaml para receber e enviar dados ao servidor. A classe RequestReader recebe a entrada do usuário, a interpreta e realiza o pedido, que pode ser: criar usuário, autenticar usuário, listar partidas atuais, listar partidas encerradas, listar informações detalhadas de uma partida, listar as apostas do usuário, fazer uma aposta e encerrar a conexão.
Abaixo é mostrado um teste bem sucedido em que foi criado um usuário, foi feita a sua autenticação e listadas as partidas atuais:
teste1.jpg

Criação do servidor multithread

Foi criado um servidor multithread, ou seja, que aceita que vários usuários se conectem a ele ao mesmo tempo. Abaixo é mostrado um teste bem sucedido em que dois usuários diferentes se conectam ao servidor.
multithread2.jpg

A classe servidor é mostrada abaixo. observe que foi utilizada a porta 4344. Observe que nela foram criadas e decoradas as listas de usuários e partidas globais.

m1_builder=MatchListBuilder.new
  m1_builder.add_all
  $match_list=m1_builder.match_list
  #$match_list.add("santosXsaopaulo",Time.now+10000)
  #$match_list.add("palmeirasXsaopaulo",Time.now+10000)
 
  u1_builder=UserListBuilder.new
  u1_builder.add_all
  $user_list=u1_builder.user_list  
 
server = TCPServer.new(4344)  # 4344 é a porta de conexão de rede usada
while ( io_socket = server.accept ) #aguarda até que conexão seja recebida, retornando um TCPSocket com a conexão.
    Thread.new do
      puts "conectado"
      main(io_socket, io_socket)
      io_socket.close
    end    
end

O projeto do lab5 está no link ao lado: Ces-22_Lab5

Conclusão

Considerei o laborátorio bastante difícil, especialmente para entender o código que nos foi passado anteriormente. Acredito que parte dessa dificuldade se deve ao fato de o laboratório ser em ruby, pois a linguagem fica mais simplificada, mas de entendimento mais demorado por alguém que não desenvolveu o código. No entanto pude aprender bastante com ele, principalmente o uso dos padrões builder e decorator, além de como desenvolver um aplicativo cliente servidor.

Add a New Comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License