¿Dónde colocar métodos privados en Ruby?

95

La mayoría de los blogs, tutoriales o libros tienen métodos privados al final de cualquier clase / módulo. ¿Es esta la mejor práctica?

Me parece más conveniente tener métodos privados cuando sea necesario. Por ejemplo:

public
def my_method
  # do something
  minion_method
end

private
def minion_method
  # do something
end

public
def next_method
end

De esta manera, encuentro el código más legible en lugar de desplazarme hacia arriba y hacia abajo continuamente, lo cual es muy irritante.

¿Hay algo terriblemente mal en este enfoque? ¿Tener métodos privados en la parte inferior no es solo una mejor práctica y algo más?

ZX12R
fuente
en realidad tu camino tampoco es malo. También sigo lo mismo en algunos casos, se siente más convenienteprivate def my_method...end
r3bo0t

Respuestas:

131

La mejor práctica desde mi punto de vista es ir secuencialmente y declarar sus métodos sin mantener la privacidad en el punto de vista.

Al final, puede convertir cualquier método en privado simplemente agregando: private :xmethod

Ejemplo:

class Example
 def xmethod
 end

 def ymethod
 end

 def zmethod 
 end

 private :xmethod, :zmethod

end

¿Esto justifica tu pregunta?

kiddorails
fuente
19
No creo que esta sea una gran idea desde el punto de vista de la legibilidad a medida que la clase crece cada vez más.
Alexander Suraphel
2
Realmente creo que debería ordenar los métodos por orden de importancia y por qué se llama qué cuando todas las demás cosas parecen iguales. Los métodos privados son detalles de implementación y deberían ser lo último que vea el lector, por lo que deben estar más abajo en el archivo. Estoy de acuerdo con el comentario anterior de que esto no funcionará bien con archivos más grandes. Esta no debería ser la respuesta aceptada, hay muchos mejores consejos en esta página.
Luke Cowell
58

También existe la opción de anteponer privatea la definición del método desde Ruby 2.1.

class Example

 def xmethod
 end

 private def ymethod
 end

 private def zmethod 
 end

end

Si observa la definición, sabrá instantáneamente si un método es privado, sin importar en qué parte del archivo esté definido. Es un poco más de escritura (si no se autocompleta) y no todos sus defs estarán bien alineados.

Dennis
fuente
5
Debería haber agregado una nota, que esto está disponible en Ruby 2.1 donde los métodos devuelven la clave con su propio nombre: bugs.ruby-lang.org/issues/3753
konole
Creo que lo privado también se puede usar como un bloque, también conocido como incluir algunos métodos privados en privado begin ... end
edx
vea la respuesta de @devpuppy aquí para obtener una nota sobre cómo hacer esto con métodos de clase.
manroe
Agregar privatesolo una vez, antes de ymethod, también funciona. No es necesario agregarlo varias veces.
Iulian Onofrei
@IulianOnofrei Si tuviera otro método zmethodsin él private, este método no sería privado. Entonces, necesitas repetirlo (al menos con Ruby 2.3).
tsauerwein
52

Como otros ya han señalado, la convención es poner los métodos privados al final, bajo una clase privada. Sin embargo, probablemente también debería saber que muchos programadores usan un método de doble sangría (4 espacios en lugar de 2) para esto. La razón es que muchas veces no verá "privado" en su editor de texto y asumirá que podría ser público. Vea a continuación para ver una ilustración:

class FooBar

  def some_public_method
  end

  def another_public_method
  end

private

    def some_private_method
    end

    def another_private method
    end

end

Este método debería evitar que tengas que desplazarte hacia arriba y hacia abajo y hará que otros programadores se sientan más cómodos con tu código.

Noah Clark
fuente
4
Esto estaba de moda cuando dejé este comentario en el '12. Ya no veo esto muy a menudo y ha caído en desgracia.
Noah Clark
los privados también se pueden formatear en el interior begin..endinmediatamente después private. Luego, el editor puede establecer automáticamente la sangría, ya que el código dentro de begin(en el ejemplo anterior) está sangrado semánticamente con 4 espacios.
Petrus Repo
Sigo el mismo enfoque ... primero publicy luegoprivate
Rahul Goyal
1
Nunca he visto esto y he estado trabajando con Ruby desde 2007. En general, no lo recomendaría.
Marnen Laibow-Koser
15

Creo que los métodos públicos son una especie de interfaz del objeto, y es lógico colocarlos en el lugar más destacado, es decir, en la parte superior del archivo.

Flexoide
fuente
5
Sí, coloque los métodos públicos donde es más probable que los encuentre, generalmente cerca de la parte superior del archivo, y las cosas que probablemente no debería mirar deben enterrarse cerca del fondo. Como se escribe un artículo de periódico, ponga lo más importante primero.
tadman
14

No es necesario poner publico por privateencima de cada método. Por lo general, pongo todos mis métodos privados al final de mi clase. Además, no es necesario que lo diga explícitamente publicque los métodos son públicos de forma predeterminada. Por ejemplo:

class FooBar

  def some_public_method
  end

  def another_public_method
  end

private

  def some_private_method
  end

  def another_private method
  end

end
Kyle Decot
fuente
Por favor, lea mi pregunta nuevamente. Lo he editado para ser más específico
ZX12R
1
Es más una convención que cualquier otra cosa. Lo que estás haciendo es válido y si tiene más sentido para ti, entonces debes ceñirte a él. Encuentro que la convención es más legible, pero probablemente sea porque así es como me enseñaron a escribirla, así que estoy acostumbrado.
Kyle Decot
¿Qué significa / hace realmente declarar un método como "público"?
ZX12R
6

Vengo de Java Background y odio tener que desplazarme para ver el tipo de método. Creo que es una locura que no se pueda especificar la visibilidad del método por método sin fealdad. Así que terminé poniendo un comentario #privateantes de cada método de succión y luego declarando private :....

Akostadinov
fuente
1
y el rubí reciente puede ponerlo private def method...para tenerlo mejor
akostadinov
5

No me gusta tener que especificar público o privado para cada método. Poner todos los métodos privados en la parte inferior me permite tener una sola instancia de "privado" por archivo. Supongo que es cuestión de gustos.

David
fuente
5

Un estilo es a métodos de grupo juntos para que utilice sólo privatey protecteduna vez por clase como máximo. Otro estilo es especificar la visibilidad justo después de la definición del método:

class Example
  def my_private_method
  end
  private :my_private_method

  def my_public_method
  end
end

A partir de Ruby 2.1.0 defdevuelve el nombre del método como símbolo, por lo que es posible un estilo más simplificado:

class Example
  private def my_private_method
  end

  def my_public_method
  end

  protected def my_protected_method
  end

  private_class_method def self.my_private_class_method
  end
end

(Tenga en cuenta que usamos private_class_methodpara métodos de clase; de ​​lo contrario, obtendríamos NameError: undefined methodya que privateespera un método de instancia. Incluso cuando se usa como una macro como en el ejemplo original, solo afecta la visibilidad de los métodos de instancia).

Me gusta más este estilo de visibilidad en línea, ya que le permite organizar los métodos como desee. Disminuye el riesgo de agregar un nuevo método en el lugar equivocado y hacerlo privado inadvertidamente.

En cuanto a la sintaxis del método de clase, puede manejarlo de esta manera:

class Example
  private def my_private_method
  end

  class << self
    private def my_private_class_method
    end
  end
end
devpuppy
fuente
este es el único lugar en el que he visto mencionar la private_class_methodllamada antes, y la última parte sobre cómo usar el class << selfbloque para evitar tener que usarlo es un buen consejo. Hasta ahora, no sabía que los métodos de clase "nornal" (declarados con en def self.foo; endlugar de class << self; def foo; endno se verían afectados por el privateespecificador.
manroe
3

Dennis tenía la respuesta perfecta, es decir, cuando usa ruby> = 2.1, simplemente prefija la definición con privado (o protegido, público)

Pero creo que ahora también es posible usar privado como un bloque como en:

private begin
   def foo
   end
   def bar
   end
end

def zip
end
edx
fuente
0

Generalmente ordeno mis métodos de la siguiente manera:

  1. Constructor
  2. Otros métodos públicos, en orden alfabético
  3. private, escrito solo una vez
  4. Métodos privados, en orden alfabético

Utilizo funciones de "ir a la definición" en mi editor para que esto no implique mucho desplazamiento y, en cualquier caso, si la clase es lo suficientemente grande como para que el desplazamiento se vuelva problemático, probablemente debería dividirse en varias clases.

Marnen Laibow-Koser
fuente
También debo mencionar que generalmente coloco métodos de conversión (como to_s) cerca del final de la sección pública.
Marnen Laibow-Koser