Creo que hay otra ventaja de usar métodos internos, que es la claridad. Piénselo: una clase con una lista de métodos es una lista de métodos plana y no estructurada. Si te preocupa la separación de las preocupaciones y mantener las cosas en el mismo nivel de abstracción Y la pieza de código se usa solo en un lugar, los métodos internos ayudan a la vez que insinúan que solo se usan en el método de encierre.
Suponga que tiene este método en una clase:
class Scoring
# other code
def score(dice)
same, rest = split_dice(dice)
set_score = if same.empty?
0
else
die = same.keys.first
case die
when 1
1000
else
100 * die
end
end
set_score + rest.map { |die, count| count * single_die_score(die) }.sum
end
# other code
end
Ahora, eso es una especie de simple transformación estructura de datos y más código de nivel superior, la adición de puntuación de los dados que forman un conjunto y los que no pertenecen a el conjunto. Pero no está muy claro qué está pasando. Vamos a hacerlo más descriptivo. Una refactorización sencilla sigue:
class Scoring
# other methods...
def score(dice)
same, rest = split_dice(dice)
set_score = same.empty? ? 0 : get_set_score(same)
set_score + get_rest_score(rest)
end
def get_set_score(dice)
die = dice.keys.first
case die
when 1
1000
else
100 * die
end
end
def get_rest_score(dice)
dice.map { |die, count| count * single_die_score(die) }.sum
end
# other code...
end
idea de get_set_score() y get_rest_score() es un documento en el uso de un descriptiva (aunque no es muy buena en este ejemplo inventado) lo hacen los animales divididos.Pero si tienes muchos métodos como este, el código en la puntuación() no es tan fácil de seguir, y si refactorizas cualquiera de los métodos, es posible que necesites comprobar qué otros métodos usan (incluso si son privados, otros métodos de la misma clase podrían usarlos).
En cambio, estoy empezando a preferir esto:
class Scoring
# other code
def score(dice)
def get_set_score(dice)
die = dice.keys.first
case die
when 1
1000
else
100 * die
end
end
def get_rest_score(dice)
dice.map { |die, count| count * single_die_score(die) }.sum
end
same, rest = split_dice(dice)
set_score = same.empty? ? 0 : get_set_score(same)
set_score + get_rest_score(rest)
end
# other code
end
En este caso, debería ser más obvio que get_rest_score() y get_set_score() se envuelven en métodos para mantener la lógica de la puntuación() en el propio mismo nivel de abstracción, sin intromisión con los hashes etc.
Tenga en cuenta que técnicamente se puede llamada alcanzaron el # get_set_score y alcanzaron el # get_rest_score, pero en este caso se trataría de un mal estilo de la OMI, ya que son semánticamente métodos simplemente privadas para la puntaje de método único()
Por lo tanto, al tener esta estructura siempre puede leer toda la implementación de la puntuación() sin buscar ningún otro método definido fuera del puntaje # de Puntuación. Aunque no veo ese código de Ruby a menudo, creo que voy a convertir más en este estilo estructurado con métodos internos.
NOTA: Otra opción que no se ve tan limpia, pero evita el problema de los conflictos de nombres es simplemente utilizar lambdas, que ha existido en Ruby desde el primer momento. Siguiendo con el ejemplo, se convertiría en
get_rest_score = -> (dice) do
dice.map { |die, count| count * single_die_score(die) }.sum
end
...
set_score + get_rest_score.call(rest)
Se ISN tan bonita - alguien que busca en el código podría preguntarse por qué todos estos lambdas, mientras que el uso de métodos internos es bastante auto-documentado. Todavía me inclinaría más hacia las lambdas, ya que no tienen el problema de filtrar nombres potencialmente conflictivos al alcance actual.
pequeña comunidad de desarrolladores de rubíes aquí supongo. – zengr
¿Sabe que una vez que llama a 'outer_method', cualquiera puede llamar a' inner_method'? –