Refactor : Extraer una Clase y Metodo

Podemos hacer muchos tipos de Refactor pero hoy nos concentraremos en la extracción de una clase "extract class". Este se refiere al extraer una clase y agrupar los metodos relacionados con esta para terminar con dos clases que definan un poco mejor lo que esta pasando. Aqui les dejo un ejemplo:

                
                class CachedEvent
                
                  def self.destroy_all
                    @db = Mongo::Connection.new('localhost').db("mydb")
                    coll = @db.collection('cached_events')
                    coll.remove()
                  end
                
                  def self.destroy(options={})
                    @db = Mongo::Connection.new('localhost').db("mydb")
                    coll = @db.collection('cached_events')
                    coll.remove(options)
                  end
                
                  def self.create(attributes)
                    ## PROBLEM
                    @db = Mongo::Connection.new("localhost").db("mydb")
                    coll = @db.collection('cached_events')
                    coll.insert(attributes)
                    return coll
                  end
                
                  def self.all
                    @document = Array.new
                    @db = Mongo::Connection.new("localhost").db("mydb")
                    coll = @db.collection('cached_events')
                    coll.find().each {|doc| @document << doc }
                    @document
                  end
                
                  def self.last
                    self.all[-1]
                  end
                end
                

En el código anterior podemos ver que hay bastante duplicación. Esto es un olor que nos indica que algo esta mal. Recuerden que la duplicación es la causa de muchos problemas en la programación. Pedemos ver que duplicamos la llamada a la conexión a la base de datos, en este caso MongoDB, como tambien duplicamos el llamado a la colección llamada "cached_events".

                
                class MongoC
                  def self.conection
                    $mongo_connection ||= Mongo::Connection.new('localhost').db('mydb')
                  end
                end
                
                MongoC.conection
                
                class CachedEvent
                
                  def self.collection_name
                     self.name.underscore.pluralize
                  end
                
                  def self.find_collection
                    $mongo_connection.collection(collection_name)
                  end
                
                  def self.destroy_all
                    self.find_collection.remove()
                  end
                
                  def self.destroy(options={})
                    self.find_collection.remove(options)
                  end
                
                  def self.create(attributes)
                    self.find_collection.insert(attributes)
                  end
                
                  def self.all
                    document = Array.new
                    self.find_collection.find().each {|doc| document << doc }
                    document
                  end
                
                  def self.last
                    self.all[-1]
                  end
                end
                

En este segundo ejemplo podemos ver que el código esta factorizado mucho mejor. Tenemos dos clases. La primera clase se encarga de hacer la llamada de conexión a la base de datos. En la segunda clase podrán ver que realizamos algo parecido al "extract class" pero con el metodo find_collection. Esto lo llamamos "extract method".

Recapitulando podemos decir que:

Una señal para realizar un Refactor es ver parte de nuestro código que son parecidas o identicamente iguales.

Extract Class: es una tecnica en la cual de una clase extraemos otra para separar responsabilidades.

Extract Method: es una tecnica en la cual extraemos un metodos para rehusar en varios metodos dentro de la misma clase.