Es ist eine Entwurfsmethode, keine Grammatik. Als ich es zum ersten Mal hörte, dachte ich, es sei eine Art Grammatik oder Syntax, aber das ist nicht der Fall. Es scheint, dass das richtige Verständnis darin besteht, dass Ruby eine Syntax hat, die leicht in Übereinstimmung mit der Objektorientierung zu schreiben ist.
Ich denke, da ist etwas drin. Dieses Mal werde ich mich auf diesen Punkt konzentrieren und ihn zusammenfassen.
toriaezuugoku.rb
x_max = ARGV[0]
y_max = ARGV[1]
if !x_max || !y_max
puts "Bitte geben Sie das Argument an"
exit 1
end
x_max = x_max.to_i
y_max = y_max.to_i
#Status
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
Dies ist der Code, den ich im vorherigen Artikel geschrieben habe. Es ist so geschrieben, dass die gesamte Verarbeitung von oben nach unten verläuft, ohne eine Funktion zu definieren. Dies ist der am schwersten zu lesende Code. Dies liegt daran, dass die Spezifikationen so sind, dass die Funktion nur gelesen werden kann, wenn nach der eigentlichen Verarbeitung anhand der Definition der Variablen vorhergesagt wird, was getan wird. Lassen Sie uns aufgeben, zu lesen, was dieser Code im Laufe der Zeit hier tut, und als nächstes den umgeschriebenen Code betrachten.
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 "Bitte geben Sie das Argument an"
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
Dieses Mal habe ich es mit der Funktionsdefinition und dem Hash geschrieben. Wenn man sich die Schleifenanweisung ansieht, scheint es, dass der Status des Inhalts des Hashs, der als Status bezeichnet wird, durch die Methode namens move_ball und x und y manipuliert wird, wenn der Ball im bedingten Ausdruck mit border_x und border_y springt. Ich frage mich, ob die Koordinaten durch Reflect_x und Reflect_y geändert werden ... Es wird zu etwas, das nicht gelesen werden kann. Wenn die Verarbeitung der durch die Funktion definierten Inhalte korrekt ist, kann der Leser leicht verstehen, was er tut und was dieser Code tut, indem er nur hier liest. Es gibt einen solchen Vorteil, wenn Sie den Teil, in dem der Status geändert wird, in Funktionen aufteilen. Die Verwendung von Hashes macht die Statusverwaltung sicherer als im vorherigen Code, der mit vielen globalen Variablen dargestellt wurde, und ist mit zunehmender Anzahl von Bällen immer noch etwas flexibler. (Wenn die Anzahl der Bälle unangemessen groß oder unbekannt ist, können wir damit nicht umgehen.) Es reicht jedoch immer noch nicht aus, um die Lesbarkeit zu gewährleisten. Wenn Sie einen Fehler wie einen Hash machen, gibt dieser Code nur null zurück, wodurch es schwieriger wird, den Fehler zu erkennen. Je größer das Produkt, desto schwieriger ist es zu entdecken.
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 "Bitte geben Sie das Argument an"
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
Sie können wie oben schreiben. Teilen Sie den Zustand des Balls und den Zustand des Billardtisches in Klassen ein, definieren Sie die Zustandsoperationsmethode, die für die Funktion des Balls in der Ballklasse erforderlich ist, und definieren Sie die Verarbeitung des Vorgangs auf dem Tisch, der den Ball in der Billardklasse bewegt hat. Wenn Sie also das allgemeine Verhalten dieses Codes kennen möchten, können Sie es erfassen, indem Sie das Verarbeitungssystem der Billardklasse und den Teil lesen, der das Befehlszeilenargument empfängt, dh den außerhalb der Klasse geschriebenen Codeteil. Ich kann. Die englische Namenskonvention ist auch viel einfacher zu lesen. Wenn Sie schließlich Cue (Poke) gegen BT (Billardstand) ausführen, bewegt sich der Ball. Sehr leicht zu lesen. Da die Statusoperationen sehr detailliert definiert sind, haben sich meiner Meinung nach auch die Benutzerfreundlichkeit des Codes und die Aufrufbarkeit der Methode verbessert. Ich denke, dies macht die Fehlerbehebung einfacher als die beiden zuvor erwähnten festen Codes und Hash-Codes.
Ich habe versucht, den zweistufigen Code aus dem soliden Schreibprozess, den ich zuerst geschrieben habe, neu zu schreiben, aber ich habe verstanden, wie schwierig es ist, den Code zu lesen, den ich zuerst geschrieben habe, sozusagen, es ist schmutziger Code. .. Ich habe viel Code-Verarbeitung geschrieben, wie die erste, die ich in Rails geschrieben habe. Dies ist ein Framework, das das Klassendesign durch Objektorientierung vereinfacht, also habe ich Yabe-Code erstellt. War noch prominenter und gut verstanden.
Recommended Posts