Eine gute Faustregel ist, dass Methodennamen Verben oder Prädikate sein sollten, sodass das Objekt, auf das Sie sie aufrufen ( self
in der Standard-Python-Konvention this
in den meisten anderen Sprachen), zum Thema wird.
Diese Regel file.close
ist falsch, es sei denn, Sie gehen von dem mentalen Modell aus, dass die Datei sich selbst schließt oder dass das file
Objekt nicht die Datei selbst darstellt, sondern ein Datei-Handle oder eine Art Proxy-Objekt.
Ein Boxsack schlägt sich aber nie von selbst, punchingBag.punch()
ist also in beiden Fällen falsch. be_punched()
ist technisch korrekt, aber hässlich. receive_punch()
könnte funktionieren, oder handle_punch()
. Ein anderer Ansatz, der in JavaScript sehr beliebt ist, besteht darin, solche Methodenaufrufe als Ereignisse zu behandeln, und die Konvention besteht darin, den Ereignisnamen mit dem Präfix "on" zu verwenden, sodass dies on_punched()
oder ist on_hit()
. Alternativ können Sie die Konvention übernehmen, dass frühere Partizipien Passiv anzeigen, und nach dieser Konvention wäre der Methodenname gerecht punched()
.
Ein weiterer zu berücksichtigender Aspekt ist, ob der Boxsack tatsächlich weiß, was ihn getroffen hat: Macht es einen Unterschied, ob Sie ihn schlagen, mit einem Stock schlagen oder mit einem Lastwagen hineinfahren? Wenn ja, was ist der Unterschied? Können Sie den Unterschied auf ein Argument reduzieren, oder benötigen Sie verschiedene Methoden für verschiedene Arten der empfangenen Bestrafung? Eine einzelne Methode mit einem generischen Parameter ist wahrscheinlich die eleganteste Lösung, da sie die Gradkopplung niedrig hält, und eine solche Methode sollte nicht punched()
oder genannt werden handle_punch()
, sondern eher etwas generischeres wie receive_hit()
. Mit einer solchen Methode können Sie alle Arten von Akteuren implementieren, die Boxsäcke treffen können, ohne den Boxsack selbst zu ändern.
Hitable
.Ich denke, es ist eine konzeptionelle Frage (wie wir über die Welt denken). Es ist in Ordnung zu sagen:
door.close()
paper.fold()
file.close()
Es ist seltsam zu sagen:
bag.punch()
Es müsste etwas haben, mit dem es sich an erster Stelle schlagen kann (z. B. Arme). Sie würden wahrscheinlich sagen:
punching_bag.move()
Es ist in Ordnung für programmatische Objekte, Dinge zu tun, die normalerweise andere mit ihnen machen (in der "realen Welt"). Aber ich denke, es sollte immer mindestens einen Sinn ergeben, dass das Ding es mit sich selbst macht . Sie sollten es sich leicht vorstellen können, ohne dunkel zu werden (wie im Fall von
punching_bag
).quelle
Es ist Geschmackssache, denke ich.
Punching bag
Diepunch()
Methode von ist zumindest konsistent mitfile.close()
oderframe.move()
im Sinne des Erlebens von Handlungen an sich. Die größere Frage wäre, warumBoxer
überhaupt einepunch(something)
Methode zur Verfügung steht.quelle
Coach.sayPunchToBoxer()
,Boxer.punchNearestBag()
undBag.punch()
. Andernfalls müssen Sie jedes Mal raten, was passiert, wenn Sie anrufenCoach.punch()
. Die allgemeine Regel lautet: Wenn das Objekt, für das eine Aktion ausgeführt wird, nicht im Methodennamen angegeben ist, ist der Empfänger dieses Objekt.Sie haben zwei verschiedene Nachrichten: eine, um einem Objekt das Lochen zu befehlen, und eine, um einem Objekt mitzuteilen, dass es gelocht wurde. Bedenken Sie, dass ein Boxer-Objekt wahrscheinlich auf beide antworten muss . Anders . Das ist ein guter Grund, ihnen andere Namen zu geben.
Meine Neigung wäre
punch(boxer, object, strength)
, die entgegengesetzte Methode zu behalten und umzubenennenpunched
. Sie könnten eshandle_punch
oder so etwas nennen, aber dann ist es immer noch zweideutig, ob es sich um einen Punch-Befehl oder die Benachrichtigung handelt, dass er gepuncht wurde.quelle
defend
in diesem speziellen Fall). Aber Boxsack wird niemals so bidirektional sein. Und es gibt bereits diese file.close () ...defend
ist ein Befehl. Dies ist eine mögliche Aktion, auf die ein Objekt reagieren könntepunched
, aber Sie möchten nicht, dass andere Objektedefend
direkt aufgerufen werden.Ihr Ansatz wird schließlich zu einem sehr gekoppelten Code führen.
Um Eric Lippert hier ideal zusammenzufassen, möchte man, dass der Boxer in der Lage ist, sehr viele Dinge zu schlagen. Wenn der Boxsack die Signatur der Boxerfunktion ist, bedeutet dies, dass der Boxer mit dem unmittelbaren Wissen von All erstellt wird (das heißt, dass er stanzbar ist). Plus einen Schlag zu geben und einen Schlag zu erhalten sind zwei SEHR verschiedene Dinge, daher sollten sie nicht den gleichen Namen haben.
Ich würde dies eher als Boxer modellieren, der einen Schlag erzeugt (ein anderes Objekt, das die Attribute Kraft, Reichweite, Richtung usw. des Schlags enthält).
Dann muss der Boxsack mit einer Methode wie onPunch, die dieses Punch-Objekt empfängt, die Wirkung des Punchs auf sich selbst berechnen können.
Vor diesem Hintergrund ist der Name der Dinge sehr wichtig. Es muss zu dem mentalen Modell passen, das Sie von der Situation haben. Wenn Sie versuchen zu erklären, wie etwas passieren kann, das auf den ersten Blick keinen Sinn ergibt, oder wenn es Ihnen am schwersten fällt, etwas zu benennen, ist Ihr Modell möglicherweise falsch und muss geändert werden.
Es ist schwierig, ein Modell zu ändern, nachdem Sie begonnen haben. Im Allgemeinen neigen die Leute dazu, die Realität so zu ändern, dass sie zum Modell passt. Das Problem dabei ist, dass die Welt, die Sie erstellen, immer komplexer wird und die Interaktionen immer schwieriger zu implementieren sind, wenn Sie Dinge biegen, die passen (z. B. einen Boxsack, der Dinge stanzen kann). Sie werden irgendwann einen Punkt erreichen, an dem das Hinzufügen des Trivialsten zum Albtraum von Veränderungen und Fehlern wird. Diese konzeptionelle technische Verschuldung kann einen sehr hohen Preis haben, selbst wenn die anfänglichen Kosten zu diesem Zeitpunkt als das günstigste angesehen wurden.
quelle
Dies ist das Problem, das ich als "Objekt / Subjekt" -Verwirrung bezeichne, und es ist ziemlich weit verbreitet.
Sätze haben im Allgemeinen ein Subjekt , das das Verb auf seinem Zielobjekt ausführt .
Was die Programmierung angeht, so ist das Einzige, was die Dinge tatsächlich tut, der Computer. Oder praktisch ein Prozess, ein Faden oder eine Faser. Die Objekte werden standardmäßig nicht animiert. Sie haben keine eigenen Threads, so dass sie eigentlich nichts tun können.
Dies bedeutet, dass Methoden auf sie einwirken, sie sind das Ziel der Aktion und nicht derjenige, der die Aktion ausführt. Deshalb nennen wir sie "Objekte", nicht "Subjekte"!
Wenn Sie sagen,
File.close
es ist nicht die Datei, die sich selbst schließt, ist es der aktuelle Thread, der die Datei schließt. Wenn Sie sagenArray.sort
, sortiert der aktuell ausgeführte Thread das Array. Wenn Sie sagenHttpServer.sendRequest
, sendet der aktuell ausgeführte Thread die Anfrage an den Server (nicht umgekehrt!). ÄhnlichesPunchingBag.punch
bedeutet, dass der aktuell laufende Faden den Beutel stanzt.Das heißt, wenn Sie möchten
Boxer
, dass der Punch in der Lage ist, dann muss es eine Unterklasse von a sein,Thread
damit er in seiner Thread-Funktion Dinge wie Boxsäcke ausführen kann.Manchmal ist es jedoch auch sinnvoll zu sagen, dass sich der Boxsack selbst stanzt, wenn jedes Objekt einen eigenen Thread hat. Möglicherweise möchten Sie Rennbedingungen vermeiden und Methodenaufrufe als Nachrichtenübergabe implementieren: Sie stanzen den Beutel, indem Sie die
punch
Nachricht senden selbst sendet Ihnen dann diepunch successful
Nachricht zurück, aber das ist nur ein Implementierungsdetail.quelle
Ich bin damit einverstanden, dass "punch" ein guter Methodenname für die Boxer-Klasse ist, da er (mit einigen Optimierungen) für andere Objekte wiederverwendet werden kann. Es wird auch genau beschrieben, dass ein Objekt einer Klasse eine Aktion für ein anderes Objekt ausführt. Allerdings würde ich die Methode in "doPunch" umbenennen, um die Beziehung klarer darzustellen.
Für die PunchingBag-Klasse ist der Methodenname jedoch entweder zu vage oder ein wenig ungenau. Wenn ich "Punsch" sehe, denke ich, dass etwas etwas anderes schlägt. In diesem Fall reagiert das PunchingBag-Objekt jedoch auf einen Schlag eines Objekts (in diesem Fall eines Boxer-Objekts). Daher würde ich die Methode hier in "isPunched" umbenennen, um zu veranschaulichen, dass das Objekt auf einen Schlag reagiert.
Dies ist jedoch meine Interpretation, wie ich die Methoden benennen würde. Es ist alles eine Frage des Geschmacks und der Standards, denen Sie folgen.
quelle
isPunched
ist wirklich irreführend (je nach Framework-Benennungsschema mehr oder weniger).punch()
?hmmmm. Ich frage Boxsack als Klasse, weil Sie sich nicht wirklich für den Boxsack interessieren - Sie interessieren sich für die Wirkung und Stärke der Boxerfaust. Die Methoden sollten sich also auf das beziehen, was auch immer die Messung und Berichterstattung der Schlagstöße ist. auch wenn dies aus dem "Boxsack" kommt, sollte die Benennung dennoch die Verantwortung offenbaren - wie punchImpactMeter usw.
quelle
Der Boxer schlägt den Boxsack -> boxer.punch
Der Boxsack wird vom Boxer gestanzt -> punchingbag.get_punch
quelle