Code-Wiederholung gegen Multi-Responsible-Methode


11

Ich versuche, dem Single Responsibility Principle (SRP) zu folgen und auch Code-Wiederholungen wegzulassen. Es gibt jedoch häufig Stellen, an denen es Code-Wiederholungen gibt, die nichts anderes als Codeblöcke von Aufrufen sind, die sich nicht in eine zumindest aussagekräftige benannte Methode extrahieren lassen:

DoAction1();
DoAction2();

if (value)
    DoAction3();

DoAction4();

Was ist der beste Weg, um solchen Code in eine Methode zu extrahieren und wie man ihn benennt?


1
Warum können sie nicht in eine andere sinnvolle Methode extrahiert werden?
Chandranshu

Alle Aktionen haben etwas ohne Bezug. Ich müsste schreiben : void MethodThatDoAction1ThenAction2AndAction3IfValueAndThenAction4(). Ich würde lieber mehr Bedeutung sehen in : CodeBlock1().
yBee

4
Dann geht es nur noch darum, die extrahierte Methode richtig zu benennen, oder? Ich fürchte, es gibt keine universelle Lösung, und Sie müssen dies von Fall zu Fall tun. Wenn Sie genau denselben Code an mehr als einer Stelle wiederholen, müssen Ihre Handlungen eine Bedeutung haben, und Sie müssen genau hinschauen (möglicherweise wird diskutiert), um diese Bedeutung zu finden und ihm einen Namen zu geben.
Chandranshu

1
Wenn es ein Trost ist, ist der Frühlingssieger für lange Klassennamen AbstractInterruptibleBatchPreparedStatementSetternur ein bisschen kleiner als Ihre Methode.
Chandranshu

1
@Chandranshu Ich glaube, Ihre Kommentare würden als Antwort auf diese Frage gut funktionieren.
Simon Forsberg

Antworten:


13

Ich denke, es geht nur darum, die extrahierte Methode richtig zu benennen. Ich fürchte, es gibt keine universelle Lösung, und Sie müssen dies von Fall zu Fall tun. Wenn Sie genau denselben Code an mehr als einer Stelle wiederholen, müssen Ihre Handlungen eine Bedeutung haben, und Sie müssen genau hinschauen (möglicherweise wird diskutiert), um diese Bedeutung zu finden und ihm einen Namen zu geben.

Wenn es ein Trost ist, liegt der Frühlingssieger für lange Klassennamen AbstractInterruptibleBatchPreparedStatementSetterbei 49 Zeichen.


11

Tatsächlich leiden Sie unter der schwierigsten Aufgabe eines Programmierers - Naming Things . Entschuldigung für eine so ausgereifte Antwort, aber ich konnte nicht widerstehen. Sie können feststellen, dass viele Menschen darunter leiden , auch im Internet finden Sie diese Art von Aufsatz .

Wenn Ihr sich wiederholender Code zusammen eine Arbeit ergibt und diese Methoden nicht von anderen Methoden verwendet werden, handelt es sich einfach um eine Helpers-Methode, und die resultierende Methode kann als doXXXoder benannt werden makeXXX. Ich denke, Sie verstehen, worum es geht.

Wie Chandranshu sagte: "Wenn Sie diese [...] Bedeutung wiederholen und ihm einen Namen geben." ist auf den Punkt und angemessen.

Geben Sie hier die Bildbeschreibung ein

Mit freundlicher Genehmigung von CodeChef Facebook Page Photo


2

Ich denke, Sie gehen mit dem Prinzip der Code-Wiederholung zu weit. Denken Sie daran, Code-Wiederholungen zu vermeiden. Es geht darum, die Menge an Code zu reduzieren, die bei einer Änderung der Logik überprüft werden muss, und das Verständnis zu verbessern, indem offensichtlich ähnlich beabsichtigte Blöcke herausgerechnet werden.

Die Nachteile des Ausklammerns, um Wiederholungen zu vermeiden, bestehen darin, dass Sie, wenn sich einer der gemeinsam genutzten Blöcke ändern muss, jetzt eine noch komplexere Vererbung oder einen Wechsel zwischen Standard- und Nicht-Standard-Implementierung benötigen.

Wägen Sie daher die Möglichkeit, dass sich die Logik für einen dieser Blöcke ohne die anderen ändert, sorgfältig gegen die Verständnisvorteile ab, die durch das Ausklammern dieser Gemeinsamkeit erzielt werden. Wenn sich eine Implementierung von den anderen trennen könnte, ist es möglicherweise besser, den Code einfach zu wiederholen.

Während Sie diesen wiederholten Code beibehalten, da er komplexer wird und Ihre Problemdomäne definierter wird, ist es möglicherweise angemessener, die wiederholten, jetzt komplexeren, aber auch definierteren Abschnitte herauszufiltern.

Normalerweise versuche ich, die Gleichheit des Texteditors für eine Weile beizubehalten, bis ich sehe, ob sich etwas, das sich wiederholt, als faktorisierbar herausstellt. Ich behalte nur die Wiederholung bei, aber ich behalte die Zukunft dieses Blocks im Auge, indem ich es textlich einfach halte, ihn später abzugleichen.

Die meiste Zeit beginnt sich die Gleichheit und das mögliche Factoring als reale, launische Geschäftsregeln und stark abhängige, oft willkürliche Logik aufzulösen. B. der Umgang mit den Kuriositäten mehrerer gängiger Datenbankimplementierungen (ANSI_NULLS oder ähnliches) wird hinzugefügt; etwas, das wie eine reine Logik schien, in ein verdrehtes Chaos zu zwingen und zu versuchen, eine vernünftige, vertretbare Entscheidungslogik zu liefern , wenn man mit dem Chaos des Zustands der Branche konfrontiert wird.

Es scheint mir, dass wir eine ganze Bibliothek wertloser Konstrukte wie Do1Then2If2False Do1IfTrueDo2 haben würden, wenn die Leute herausfinden würden, was Sie zu berücksichtigen versuchen.

Es muss komplexer und klarer sein, dass sich der Block nicht ändern wird, um das Ausklammern zu rechtfertigen.

Es ist Software . Sie können zurückgehen und einige Blöcke bearbeiten, die im Moment gleich sind. Es dauert 5 Minuten. Und Sie können Stunden verschwendeten Factorings und dann Stunden mehr verschwendeter Vererbung und Switching-Entwicklung sparen, indem Sie es einfach verlassen und sicherstellen, dass Sie eine gute Anti-RSI-Tastatur haben.


Ich mag den Teil, der die Essenz der Code-Wiederholung extrahiert: um die Menge an Code zu reduzieren, die überprüft werden muss, wenn sich die Logik
ändert

1

Wenn Sie wirklich dem Prinzip der Einzelverantwortung folgen, muss dieser Codeblock einen bestimmten Zweck haben, oder? Andernfalls würden diese Methoden in getrennten Klassen sein.

Was ist dann der Zweck dieses Codeblocks? Bestimmen Sie das und Sie sollten in der Lage sein, einen Namen zu finden.

Wenn Sie den Namen für dieses Ding immer noch nicht herausfinden können, gehören diese Methoden möglicherweise überhaupt nicht zusammen. Dh dieser Klassen- / Codeblock hat mehr als eine Verantwortung. In diesem Fall kann das Refactoring zur Aufteilung der Aufgaben einen besseren, zweckentdeckenden Namen ergeben.


1

Ich hatte eine ähnliche Situation wie Sie:

Es gibt eine Klasse, die die Funktionalität des Objekts definiert, das es darstellt:

class Functionality
{
protected:
void functionA();
void functionB();
...
void functionZ();
}

Dann gibt es eine Klasse, die die Workflows für Operationen auf hoher Ebene definiert, die das Objekt ausführt:

class Workflows: private Functionality
{
    void WorkflowA()
    {
        functionA();

        if (m_bValue) {
            functionB();
        }

        functionC();
    }
    ...
    void WorkflowB();
}

Wenn Sie sich in einer ähnlichen Situation befinden, identifizieren Sie, was Ihre Klassen darstellen (in diesem Fall Funktionalität / Workflows), und benennen Sie die Methoden entsprechend.

Haftungsausschluss: Die in diesem Beispiel verwendeten Klassennamen sind grob ungenau, aber die Methodennamen geben einen Hinweis. Diskretion empfohlen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.