it-swarm.dev

Gibt es zu viele private Funktionen / Methoden?

Ich verstehe die Bedeutung von gut dokumentiertem Code. Ich verstehe aber auch die Bedeutung von selbstdokumentierendem Code. Je einfacher es ist, eine bestimmte Funktion visuell zu lesen, desto schneller können wir während der Softwarewartung fortfahren.

Vor diesem Hintergrund möchte ich große Funktionen in andere kleinere Funktionen unterteilen. Aber ich mache das bis zu einem Punkt, an dem eine Klasse mehr als fünf haben kann, nur um einer öffentlichen Methode zu dienen. Multiplizieren Sie jetzt fünf private Methoden mit fünf öffentlichen, und Sie erhalten ungefähr fünfundzwanzig versteckte Methoden, die von diesen öffentlichen Methoden wahrscheinlich nur einmal aufgerufen werden.

Sicher, es ist jetzt einfacher, diese öffentlichen Methoden zu lesen, aber ich kann nicht anders, als zu denken, dass es eine schlechte Praxis ist, zu viele Funktionen zu haben.

[Bearbeiten]

Die Leute haben mich gefragt, warum ich denke, dass es eine schlechte Praxis ist, zu viele Funktionen zu haben.

Die einfache Antwort: Es ist ein Bauchgefühl.

Mein Glaube stützt sich nicht auf stundenlange Erfahrung in der Softwareentwicklung. Es ist nur eine Unsicherheit, die mir einen "Schreibblock" gab, aber für einen Programmierer.

In der Vergangenheit habe ich nur persönliche Projekte programmiert. Erst kürzlich bin ich zu teambasierten Projekten übergegangen. Jetzt möchte ich sicherstellen, dass andere meinen Code lesen und verstehen können.

Ich war mir nicht sicher, was die Lesbarkeit verbessern wird. Einerseits dachte ich daran, eine große Funktion in andere kleinere mit verständlichen Namen zu trennen. Aber es gab eine andere Seite von mir, die sagte, dass es nur überflüssig ist.

Also bitte ich dies, mich selbst aufzuklären, um den richtigen Weg zu wählen.

[Bearbeiten]

Im Folgenden habe ich zwei Versionen aufgeführt, wie ich mein Problem lösen kann. Der erste löst es, indem nicht große Codestücke getrennt werden. Der zweite trennt Dinge.

Erste Version:

public static int Main()
{
    // Displays the menu.
    Console.WriteLine("Pick your option");
    Console.Writeline("[1] Input and display a polynomial");
    Console.WriteLine("[2] Add two polynomials");
    Console.WriteLine("[3] Subtract two polynomials");
    Console.WriteLine("[4] Differentiate two polynomials");
    Console.WriteLine("[0] Quit");
}

Zweite Version:

public static int Main()
{
    DisplayMenu();
}

private static void DisplayMenu()
{
    Console.WriteLine("Pick your option");
    Console.Writeline("[1] Input and display a polynomial");
    Console.WriteLine("[2] Add two polynomials");
    Console.WriteLine("[3] Subtract two polynomials");
    Console.WriteLine("[4] Differentiate two polynomials");
    Console.WriteLine("[0] Quit");
}

In den obigen Beispielen ruft letzteres eine Funktion auf, die während der gesamten Laufzeit des Programms nur einmal verwendet wird.

Hinweis: Der obige Code ist verallgemeinert, entspricht jedoch meinem Problem.

Hier ist meine Frage: Welche? Wähle ich den ersten oder den zweiten aus?

63
Sal

Multiplizieren Sie jetzt fünf private Methoden mit fünf öffentlichen, und Sie erhalten ungefähr fünfundzwanzig versteckte Methoden, die von diesen öffentlichen Methoden wahrscheinlich nur einmal aufgerufen werden.

Dies ist als Kapselung bekannt, wodurch auf der höheren Ebene ein Kontrollabstraktion erzeugt wird. Das ist eine gute Sache.

Dies bedeutet, dass jeder, der Ihren Code liest, alle Details der unteren Ebene wie startTheEngine(), openIgnitionModule() ignorieren kann, wenn er zur Methode turnDistributorMotor() in Ihrem Code gelangt , sendSparksToSparkPlugs(), injectFuelIntoCylinders(), activateStarterSolenoid() und alle anderen komplexen, kleinen Funktionen, die ausgeführt werden müssen, um die viel größere, abstraktere Funktion zu ermöglichen von startTheEngine().

Sofern sich das Problem, mit dem Sie sich in Ihrem Code befassen, nicht direkt mit einer dieser Komponenten befasst, können Codebetreuer fortfahren und die gekapselte Sandbox-Funktionalität ignorieren.

Dies hat auch den zusätzlichen Vorteil, dass das Testen Ihres Codes einfacher wird. . Zum Beispiel kann ich einen Testfall für turnAlternatorMotor(int revolutionRate) schreiben und dessen Funktionalität völlig unabhängig von den anderen Systemen testen. Wenn es ein Problem mit dieser Funktion gibt und die Ausgabe nicht meinen Erwartungen entspricht, weiß ich, wo das Problem liegt.

Code, der nicht in Komponenten unterteilt ist, ist viel schwieriger zu testen. Plötzlich betrachten Ihre Betreuer nur noch die Abstraktion, anstatt in messbare Komponenten zu graben.

Mein Rat ist, weiterhin das zu tun, was Sie tun, da Ihr Code skaliert, einfach zu warten ist und über Jahre hinweg verwendet und aktualisiert werden kann.

36
jmort253

Ja und nein. Der grundlegende Grundsatz lautet: eine Methode sollte eine Sache und nur eine Sache tun

Es ist richtig, Ihre Methode in kleinere Methoden aufzuteilen. Andererseits sollten diese Methoden optimalerweise allgemein genug sein, um nicht nur dieser "großen" Methode zu dienen, sondern an anderen Stellen wiederverwendbar zu sein. In einigen Fällen folgt eine Methode jedoch einer einfachen Baumstruktur, z. B. eine Initialize-Methode, die InitializePlugins, InitializeInterface usw. aufruft.

Wenn Sie eine wirklich große Methode/Klasse haben, ist dies normalerweise ein Zeichen dafür, dass sie zu viel bewirkt, und Sie müssen einige Umgestaltungen vornehmen, um den "Blob" aufzubrechen. Perphaps verbergen eine gewisse Komplexität in einer anderen Klasse unter einer Abstraktion und verwenden die Abhängigkeitsinjektion

22
Homde

Ich denke im Allgemeinen ist es besser, auf der Seite zu vieler Funktionen zu irren, als zu wenig. Die beiden Ausnahmen von dieser Regel, die ich in der Praxis gesehen habe, sind TROCKEN und YAGNI = Prinzipien. Wenn Sie viele nahezu identische Funktionen haben, sollten Sie diese kombinieren und Parameter verwenden, um Wiederholungen zu vermeiden. Sie können auch zu viele Funktionen haben, wenn Sie sie "nur für den Fall" erstellt haben und sie nicht verwendet werden. Ich sehe absolut nichts Falsches daran, eine Funktion zu haben, die nur einmal verwendet wird, wenn sie die Lesbarkeit und Wartbarkeit erhöht.

17
Karl Bielefeldt

die großartige Antwort von jmort253 hat mich dazu inspiriert, eine "Ja, aber" Antwort zu geben ...

Viele kleine private Methoden zu haben ist keine schlechte Sache, aber achten Sie auf das unangenehme Gefühl, das Sie dazu bringt, hier eine Frage zu stellen :). Wenn Sie an einem Punkt angelangt sind, an dem Sie Tests schreiben, die sich nur auf private Methoden konzentrieren (entweder indem Sie sie direkt aufrufen oder indem Sie ein Szenario so einrichten, dass eines auf eine bestimmte Weise aufgerufen wird, damit Sie das Ergebnis testen können), dann Sie sollten einen Schritt zurück machen.

Was Sie vielleicht haben, ist eine neue Klasse mit einer eigenen, fokussierteren öffentlichen Schnittstelle, die versucht zu entkommen. An diesem Punkt möchten Sie möglicherweise darüber nachdenken, eine Klasse zu extrahieren, um den Teil Ihrer vorhandenen Klassenfunktionalität zu kapseln, der derzeit in einer privaten Methode ausgeführt wird. Jetzt kann Ihre ursprüngliche Klasse Ihre neue Klasse als Abhängigkeit verwenden und Sie können direktere Tests für diese Klasse direkt schreiben.

10
Pete Hodgson

Fast jedes OO Projekt, an dem ich jemals teilgenommen habe, litt stark unter zu großen Klassen und zu langen Methoden.

Wenn ich einen Kommentar für den nächsten Codeabschnitt benötige, extrahiere ich diesen Abschnitt in eine separate Methode. Auf lange Sicht verkürzt dies den Code. Diese kleinen Methoden werden mehr als ursprünglich erwartet wiederverwendet. Sie sehen Möglichkeiten, einige davon in einer separaten Klasse zu sammeln. Bald denken Sie auf einer höheren Ebene über Ihr Problem nach, und die ganze Anstrengung geht viel schneller. Neue Funktionen sind einfacher zu schreiben, da Sie auf den kleinen Klassen aufbauen können, die Sie mit diesen kleinen Methoden erstellt haben.

8
kevin cline

Eine Klasse mit 5 öffentlichen und 25 privaten Methoden scheint mir nicht so groß zu sein. Stellen Sie einfach sicher, dass Ihre Klassen genau definierte Verantwortlichkeiten haben, und sorgen Sie sich nicht zu sehr um die Anzahl der Methoden.

Diese privaten Methoden sollten sich jedoch auf einen bestimmten Aspekt der gesamten Aufgabe konzentrieren, jedoch nicht auf die Weise "doSomethingPart1", "doSomethingPart2". Sie gewinnen nichts, wenn diese privaten Methoden nur Teile einer willkürlich geteilten langen Geschichte sind, die außerhalb des gesamten Kontexts bedeutungslos sind.

7
user281377

Auszug aus R. Martins Clean Code (S. 176):

Selbst Konzepte, die so grundlegend sind wie die Beseitigung von Duplikaten, die Ausdruckskraft des Codes und die SRP, können zu weit gehen. Um unsere Klassen und Methoden klein zu machen, erstellen wir möglicherweise zu viele kleine Klassen und Methoden. Diese Regel [Anzahl der Klassen und Methoden minimieren] legt nahe, dass wir auch unsere Funktion und Klassenanzahl niedrig halten. Hohe Klassen- und Methodenzahlen sind manchmal das Ergebnis sinnlosen Dogmatismus.

4
user2418306

Einige Optionen:

  1. Das ist gut. Nennen Sie einfach die privaten Methoden sowie Ihre öffentlichen Methoden. Und benennen Sie Ihre öffentlichen Methoden gut.

  2. Fassen Sie einige dieser Hilfsmethoden in Hilfsklassen oder Hilfsmodule zusammen. Und stellen Sie sicher, dass diese Hilfsklassen/Module gut benannt sind und solide Abstraktionen für sich sind.

3
yfeldblum

Ich glaube nicht, dass es jemals ein Problem mit "zu vielen privaten Methoden" gibt, wenn es sich so anfühlt, als wäre es wahrscheinlich ein Symptom für eine schlechte Codearchitektur.

So denke ich darüber nach ... Wenn die Architektur gut gestaltet ist, ist es im Allgemeinen offensichtlich, wo sich der Code für X befinden sollte. Es ist akzeptabel, wenn es ein paar Ausnahmen gibt - aber diese müssen wirklich außergewöhnlich sein, sonst überarbeiten Sie die Architektur, um diese als Standard zu behandeln.

Wenn das Problem darin besteht, dass Ihre Klasse beim Öffnen voller privater Methoden ist, die größere Teile in kleinere Codestücke aufteilen, ist dies möglicherweise ein Symptom für eine fehlende Architektur. Anstelle von Klassen und Architektur wurde dieser Codebereich prozedural in einer Klasse implementiert.

Hier ein Gleichgewicht zu finden, hängt vom Projekt und seinen Anforderungen ab. Das Gegenargument dazu ist das Sprichwort, dass ein Junior-Programmierer die Lösung in 50 Codezeilen aufschlagen kann, für die ein Architekt 50 Klassen benötigt.

1
Michael Shaw

Gibt es zu viele private Funktionen/Methoden?

Ja.

In Python das Konzept von "privat" (wie von C++ verwendet, Java und C #) existiert nicht wirklich.

Es gibt eine "Art von privater" Namenskonvention, aber das war's.

Privat kann zu schwer zu testendem Code führen. Es kann auch das "Open-Closed-Prinzip" brechen, indem Code einfach geschlossen wird.

Folglich haben private Funktionen für Leute, die Python verwendet haben, keinen Wert. Machen Sie einfach alles öffentlich und fertig.

0
S.Lott