Pregunta

Todavía soy muy nuevo en Ruby (leyendo el Pickaxe y pasando la mayor parte del tiempo en irb ), y ahora que sé que es posible parchear clases en Ruby, me pregunto cuándo. es aceptable hacerlo, específicamente si es aceptable parchar las clases base de Ruby. Por ejemplo: respondí a otra pregunta de Ruby aquí donde el cartel quería saber cómo restar horas de un DateTime . Como la clase DateTime no parece proporcionar esta funcionalidad, publiqué una respuesta que parchea las clases DateTime y Fixnum como una posible solución. Este es el código que envié:

require 'date'

# A placeholder class for holding a set number of hours.
# Used so we can know when to change the behavior
# of DateTime#-() by recognizing when hours are explicitly passed in.

class Hours
   attr_reader :value

   def initialize(value)
      @value = value
   end
end

# Patch the #-() method to handle subtracting hours
# in addition to what it normally does

class DateTime

   alias old_subtract -

   def -(x) 
      case x
        when Hours; return DateTime.new(year, month, day, hour-x.value, min, sec)
        else;       return self.old_subtract(x)
      end
   end

end

# Add an #hours attribute to Fixnum that returns an Hours object. 
# This is for syntactic sugar, allowing you to write "someDate - 4.hours" for example

class Fixnum
   def hours
      Hours.new(self)
   end
end

Parché las clases porque pensé que en este caso daría como resultado una sintaxis clara y concisa para restar un número fijo de horas de un DateTime . Específicamente, podría hacer algo como esto como resultado del código anterior:

five_hours_ago = DateTime.now - 5.hours

Que parece ser bastante agradable de ver y fácil de entender; sin embargo, no estoy seguro de si es una buena idea estar jugando con la funcionalidad del operador - de DateTime .

Las únicas alternativas que se me ocurren para esta situación serían:

1. Simplemente cree un nuevo objeto DateTime sobre la marcha, calculando el nuevo valor de hora en la llamada a new

new_date = DateTime.new(old_date.year, old_date.year, old_date.month, old_date.year.day, old_date.hour - hours_to_subtract, date.min, date.sec)


2. Escriba un método de utilidad que acepte un DateTime y la cantidad de horas que se le restarán

Básicamente, solo un método de envolver alrededor de (1):

def subtract_hours(date, hours)
  return DateTime.new(date.year, date.month, date.day, date.hour - hours, date.min, date.sec)
end


3. Agregue un nuevo método a DateTime en lugar de cambiar el comportamiento existente de #-()

Quizás un nuevo método DateTime # less que podría funcionar junto con el parche Fixnum # hours , para permitir una sintaxis como esta:

date.less(5.hours)

Sin embargo, como ya mencioné, adopté el enfoque de parcheo porque pensé que daba como resultado una sintaxis mucho más expresiva.

¿Hay algún problema con mi enfoque o debo utilizar una de las 3 alternativas (u otra en la que no haya pensado) para hacer esto? Tengo la sensación de que la aplicación de parches se está convirtiendo en mi nuevo 'martillo' para problemas en Ruby, por lo que me gustaría saber si estoy haciendo las cosas de la manera '' Ruby '' o no.

¿Fue útil?

Solución

Mi respuesta personal, en pocas palabras: el martillo parcheador de clase principal debería estar en la parte inferior de su caja de herramientas . Hay muchas otras técnicas disponibles para usted, y en casi todos los casos son suficientes, más limpias y más sostenible .

Sin embargo, realmente depende del entorno en el que estés codificando. Si es un proyecto personal, claro, ¡parchelo al contenido de su corazón! Los problemas comienzan a surgir cuando se trabaja en una base de código grande durante un largo período de tiempo con un gran grupo de programadores. En la organización para la que trabajo, que tiene bases de código de Ruby de más de 100KLOC y una veintena de desarrolladores, hemos empezado a tomar medidas enérgicas contra los parches de monos, porque hemos visto que esto se traduce en un comportamiento de despeje de cabeza y pérdida de horas de trabajo. con demasiada frecuencia En este punto, prácticamente solo lo toleramos para parchear temporalmente el código de terceros que aún no ha incorporado o no incorporará nuestros parches de origen.

Otros consejos

Personalmente, creo que es aceptable agregar métodos a las clases base, pero no es aceptable modificar la implementación de los métodos existentes.

La forma más segura es definir su propia clase que se hereda de la incorporada, luego agregar sus nuevas cosas a su nueva clase.

class MyDateTime < DateTime
  alias...
  def...

Pero obviamente ahora solo obtienes el nuevo comportamiento si declaras objetos de tu nueva clase.

Creo que es así: si honestamente sientes que la mayoría de los otros programadores estarían de acuerdo con tus parches, entonces está bien. Si no es así, ¿quizás debería implementar una biblioteca de códigos?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top