Ja, es ist tatsächlich so, dass die eigentliche Arbeit (und das, wofür manche Programmierer so viel Geld bekommen) nicht das eigentliche „Hinschreiben des Codes“ ist, sondern sich im Vorfeld „auf höherer Ebene“ klar zu machen, wie man etwas schreiben wird. Das kann man sehr weit treiben, es gibt unterschiedliche Philosophien und ganze Wissenschaften über „das richtige Programmierparadigma“, aber speziell am Anfang kann man solche Fragen mal außen vor lassen, und sich erstmal klarmachen, wie Methoden (und Klassen) aussehen sollten.
Anhand der Beispiele, die du angedeutet hast (und die du für konkretere Hinweise noch etwas weiter ausführen müßtest) :
aus jeder Zeile die eine gerade Summ enthält e die Wurzel ziehen
Man könnte natürlich etwas schreiben, was so aussieht:
public void computeSquareRootsOfEveryRowThatHasAnEvenSum(File file) throws IOException
{
BufferedReader br = new BufferedReader(... new FileInputStream(file) ...);
...
int numbers[][] = new int[1000][10];
while (line != null)
{
...
numbers**[j] = Integer.parseInt(token);
}
...
int sums[] = new int[1000];
for (int i=0; i<1000; i++)
{
for (int j=0; j<10; j++)
{
sums** += numbers[j];
}
}
...
for (int i=0; i<1000; i++)
{
if (sums** % 2 == 0)
{
for (int j=0; j<10; j++)
{
System.out.println(Math.sqrt(numbers**[j];
}
}
}
}
Wenn du das jetzt nicht Zeile für Zeile nachvollzogen hast, ist das ja schon ein deutliches Zeichen dafür, dass das nicht so gut ist (und noch aus vielen, vielen anderen Gründen). Wenn man so eine „komplizierte“ Aufgabe so detailliert und ohne Hilfsmethoden hinschreibt, kann man sie kaum noch nachvollziehen. Besser wäre es doch, wenn sie zum Beispiel(!) ungefähr(!) so aussehen würde
public double[][] computeSquareRootsOfEveryRowThatHasAnEvenSum(String fileName)
{
int numbers[][] = readFile(fileName);
int sums[] = computeSums(numbers);
double squareRoots[][] = new double[sums][];
for (int i=0; i<sums.length i++)
{
if (isEven(sums**))
{
squareRoots** = computeSquareRoots(numbers**);
}
}
}
(Nur zur Verdeutlichung, macht so nicht viel Sinn)
Das ist durch die sprechenden Methodennamen schneller und leichter lesbar, fast wie normaler englischer Text. Zusätzlich hat das den Vorteil, dass man die „vielen“ kleinen Methoden wie Bausteine zusammensetzen und immer wieder verwenden kann. Z.B. könnte es eine Methode geben
public static int computeSum(int array[]) {…}
die die Summe eines Arrays berechnet, und diese könnte dann verwendet werden innerhalb einer Methode
public static int[] computeSums(int array[][]) {…}
um die Summen der einzelnen Zeilen eines 2D-Arrays zu berechnen, und diese Methode wird ja im oben anskizzierten Code verwendet - aber vielleicht auch in anderen, ähnlichen Funktionen, denn schließlich ist sie sehr allgemein und erfüllt nur eine kleine, spezifische Teilaufgabe.
Wenn man sie wiederverwenden will wird die Frage, wie die Methodensignatur aussehen soll aber besonders wichtig. Eine kleine private Hilfsmethode kann man mit weniger Nachdenken „mal schnell“ hinschreiben, aber wenn sie „public“ ist und überall verwendet werden soll, sollte sie besser durchdacht sein.
Das ganze bezieht sich bisher aber nur auf Methoden - wenn man das ganze im Kontext von Klassen sieht, kommen nochmal etliche Aspekte dazu, die weit darüber hinausgehen. Für die Aufgaben, die du angedeutet hast, könnte man auch auf Ebene der Klassen (und interfaces) die man definiert in bezug auf die Abstraktion sehr weit gehen. Und sogar in bezug auf die Sprache: Es gibt funktional angehauchte Sprachen (wie Groovy oder Scala) bei denen man diese Methode mit… vielleicht 5 Zeilen oder so schreiben könnte…
Aber alles der Reihe nach