C'est une méthode de conception, pas une grammaire. Quand je l'ai entendu pour la première fois, je pensais que c'était une sorte de grammaire ou de syntaxe, mais ce n'est pas le cas. Il semble que la compréhension correcte est que Ruby a une syntaxe facile à écrire en fonction de l'orientation de l'objet.
Je pense qu'il y a quelque chose dedans. Cette fois, je vais me concentrer sur ce point et le résumer.
toriaezuugoku.rb
x_max = ARGV[0]
y_max = ARGV[1]
if !x_max || !y_max
puts "Veuillez spécifier l'argument"
exit 1
end
x_max = x_max.to_i
y_max = y_max.to_i
#Statut
x = 1
y = 1
step = 1
x_way = 1
y_way = 1
puts " #{step} (#{x},#{y})"
x += 1
y += 1
loop do
step += 1
puts " #{step} (#{x},#{y})"
if y == 1 && x == x_max || x == 1 && y == y_max || x == 1 && y == 1 || x == x_max && y == y_max
puts "GOAL!!"
break
elsif x == x_max
x_way = -1
elsif y == y_max
y_way = -1
elsif x == 1
x_way = 1
elsif y == 1
y_way = 1
end
x += x_way
y += y_way
end
C'est le code que j'ai écrit dans l'article précédent. Il est écrit de manière à ce que tous les traitements se déroulent de haut en bas sans définir de fonction. C'est le code le plus difficile à lire. En effet, les spécifications sont telles que la fonction ne peut être lue que si le traitement réel est suivi par la prédiction de ce qui est fait à partir de la définition de la variable. Abandonnons d'essayer de lire ce que ce code fait au fil du temps ici et regardons le code réécrit ensuite.
methodtohash.rb
def move_ball(hash)
hash["x"] += hash["x_way"]
hash["y"] += hash["y_way"]
hash["step"] += 1
end
def reflect_x(hash)
if hash["x_way"] == 1
hash["x_way"] = -1
elsif hash["x_way"] == -1
hash["x_way"] = 1
end
end
def reflect_y(hash)
if hash["y_way"] == 1
hash["y_way"] = -1
elsif hash["y_way"] == -1
hash["y_way"] = 1
end
end
def goal?(hash, x_max, y_max)
hash["y"] == 1 && hash["x"] == x_max \
|| hash["x"] == 1 && hash["y"] == y_max \
|| hash["x"] == 1 && hash["y"] == 1 \
|| hash["x"] == x_max && hash["y"] == y_max
end
def boundary_x?(hash, x_max)
hash["x"] == x_max || hash["x"] == 1
end
def boundary_y?(hash, y_max)
hash["y"] == y_max || hash["y"] == 1
end
x_max = ARGV[0]
y_max = ARGV[1]
if !x_max || !y_max
puts "Veuillez spécifier l'argument"
exit 1
end
x_max = x_max.to_i
y_max = y_max.to_i
state = {
"x" => 1,
"y" => 1,
"step" => 1,
"x_way" => 1,
"y_way" => 1
}
puts " #{state["step"]} (#{state["x"]},#{state["y"]})"
loop do
move_ball(state)
puts " #{state["step"]} (#{state["x"]},#{state["y"]})"
if goal?(state, x_max, y_max)
puts "GOAL!!"
break
elsif boundary_x?(state, x_max)
reflect_x(state)
elsif boundary_y?(state, y_max)
reflect_y(state)
end
end
Cette fois, je l'ai écrit en utilisant la définition de la fonction et le hachage. En regardant l'instruction de boucle, il semble que l'état du contenu de l'état appelé par hachage est manipulé par la méthode appelée move_ball, et x et y lorsque la balle rebondit avec boundary_x et boundary_y dans l'expression conditionnelle. Je me demande si les coordonnées sont changées par reflect_x et reflect_y ... Cela devient quelque chose qui ne peut pas être lu. Si le traitement du contenu défini par la fonction est correct, le lecteur pourra facilement comprendre ce qu'il fait et ce que fait ce code en ne lisant qu'ici. Il y a un tel mérite si vous divisez la partie du moment où l'état est changé en fonctions. En outre, l'utilisation de hachages rend la gestion des états plus sûre que dans le code précédent, qui était représenté à l'aide de nombreuses variables globales, et est toujours un peu plus flexible à mesure que le nombre de balles augmente. (Si le nombre de balles est déraisonnablement grand ou inconnu, nous ne pouvons pas le gérer) Cependant, cela ne suffit toujours pas à la recherche de la lisibilité. De plus, si vous faites une erreur telle qu'un hachage, ce code ne retournera que nul, ce qui rend plus difficile la détection de l'erreur. Plus le produit est gros, plus il est difficile à découvrir.
object.rb
class Ball
attr_accessor :x, :y, :x_way, :y_way, :step
def initialize(x: 1, y: 1, x_way: 1, y_way: 1, step: 1)
@x = x
@y = y
@x_way = x_way
@y_way = y_way
@step = step
end
def move
@x += @x_way
@y += @y_way
@step += 1
end
def reflect_x
if @x_way == 1
@x_way = -1
elsif @x_way == -1
@x_way = 1
end
end
def reflect_y
if @y_way == 1
@y_way = -1
elsif @y_way == -1
@y_way = 1
end
end
def goal?(x_max, y_max)
@x == x_max && y == 1 \
|| @x == 1 && @y == y_max \
|| @x == 1 && @y == 1 \
|| @x == x_max && @y == y_max
end
def boundary_x?(x_max)
@x == x_max || @x == 1
end
def boundary_y?(y_max)
@y == y_max || @y == 1
end
end
class BilliardTable
attr_accessor :length_x, :length_y, :ball
def initialize(length_x: nil, length_y: nil, ball: nil)
@length_x = length_x
@length_y = length_y
@ball = ball
end
def cue
print_status
loop do
@ball.move
print_status
if @ball.goal?(@length_x, @length_y)
puts "GOAL!!"
break
elsif @ball.boundary_x?(@length_x)
@ball.reflect_x
elsif @ball.boundary_y?(@length_y)
@ball.reflect_y
end
end
end
def print_status
puts "#{@ball.step}, (#{@ball.x}, #{@ball.y})"
end
end
x_max = ARGV[0]
y_max = ARGV[1]
if !x_max || !y_max
puts "Veuillez spécifier l'argument"
exit 1
end
x_max = x_max.to_i
y_max = y_max.to_i
ball = Ball.new()
bt = BilliardTable.new(length_x: x_max, length_y: y_max, ball: ball)
bt.cue
Vous pourrez écrire comme ci-dessus. L'état de la balle et l'état de la table de billard sont divisés en classes, et la méthode d'opération d'état requise pour la fonction de la balle est définie dans la classe de balle, et le traitement de l'opération sur la table sur laquelle la balle est déplacée est défini dans la classe de billard. Donc, en fait, si vous voulez connaître le comportement général de ce code, vous pouvez le saisir en lisant le système de traitement de la classe billiard et la partie qui reçoit l'argument de ligne de commande, c'est-à-dire la partie de code écrite en dehors de la classe. Je peux. La convention de dénomination anglaise est également beaucoup plus facile à lire. Enfin, lorsque vous exécutez cue (poke) contre bt (billard stand), la balle bouge. Très facile à lire. De plus, comme les opérations d'état sont définies avec beaucoup de détails, je pense que la facilité de modification du code et la facilité d'appeler la méthode se sont également améliorées. Je pense que cela rend la résolution de bogues plus facile que les deux codes solides et le code de hachage que j'ai mentionnés plus tôt.
J'ai essayé de réécrire le code en deux étapes du processus d'écriture solide que j'ai écrit en premier, mais j'ai compris à quel point il est difficile de lire le code que j'ai écrit en premier, pour ainsi dire, c'est du code sale. .. J'écrivais beaucoup de traitement de code comme le premier que j'ai écrit dans rails, qui est un cadre conçu pour faciliter la conception de classes par orientation objet, donc je créais du code yabe. Était encore plus important et bien compris.
Recommended Posts