Studium, Ausbildung und Beruf
 StudiumHome   FAQFAQ   RegelnRegeln   SuchenSuchen    RegistrierenRegistrieren   LoginLogin

Häufige Fehler bei der Programmierung
Gehe zu Seite 1, 2, 3  Weiter
Neues Thema eröffnen   Neue Antwort erstellen
Foren-Übersicht -> Informatik-Forum -> Häufige Fehler bei der Programmierung
 
Autor Nachricht
sarc
Senior Member
Benutzer-Profile anzeigen
Senior Member


Anmeldungsdatum: 21.09.2006
Beiträge: 2657

BeitragVerfasst am: 10 März 2008 - 19:05:07    Titel: Häufige Fehler bei der Programmierung

Ich will in diesem Thread einfach mal Sachen sammeln, die vor allem von Programmieranfängern häufig falsch gemacht werden. Dabei seh ich "Fehler" relativ breit gefächert - das kann einerseits Code sein, der anders funktioniert als man sich das vorstellt, aber auch Code, der zu unleserlichen oder fehleranfälligen Programmen führt. Kurz, alles das, was man eigentlich vermeiden sollte, wo oft aber gar nicht klar ist, dass das tatsächlich schlecht ist.

Natürlich ist vieles davon recht subjektiv. Wenn ihr an irgend ner Stelle anderer Meinung seit lässt sich darüber sicher auch noch diskutieren. Darüber würd ich mich natürlich auch über Ergänzung freuen. Ich schreib jetzt einfach mal das auf, was mir spontan einfällt...

Meine Beispiele sind alle erst mal auf Java bezogen. Allerdings dürfte sich das Meiste auch auf einige andere Sprachen übertragen lassen...


Attribute als globale Variablen missbrauchen

Sieht man erstaunlich häufig: Man braucht eine Variable in mehreren Methoden. Ergo wird sie als Attribut ausgelagert und kann dann einfach benutzt werden. Insbesondere bei rekursiven Methoden häufig gesehen, weil man sich komplexere Parameterübergaben sparen kann.
Größtes Problem: Man muss sicherstellen, dass diese Variablen immer richtig initialisiert werden. Außerdem müsste man sicherstellen, dass die Methoden immer in genau der richtigen Reihenfolge aufgerufen werden. Das führt in sehr vielen Fällen dazu, dass der Methodenaufruf nur einmal so funktioniert, wie man sich das vorgestellt hat.

Fazit: Man tuts einfach nicht. Nur das, was sinnvoll für die Klassenstruktur ist, wird ein Attribut. Alles andere nicht.


Öffentliche Attribute

Muss man denk ich nicht viel zu sagen. Man tuts einfach nicht. Auch nicht, wenn man für das Attribut nen Getter und nen Setter hat, der darüber hinaus keine weitere Funktionalität hat.
Mit öffentlichen Attributen verbaut man sich jegliche Chancen, später mal zusätzliche Funktionalität beim Setzen oder Auslesen hinzuzufügen. (Einfachstes Beispiel: Vielleicht möchte man ja nen Logging-Mechanismus haben...)


Komplexe for-Schleifen

Damit meine ich so was in der Art wie

for(int a = 0, b = 1; x <= y && z.isNotWasauchimmer || a * b == c; doSomething())

Das erzeugt möglicherweise kurzen, aber immer auch vollkommen unlesbaren Code. Ich hab für mich folgende Konvention: for-Schleifen werden nur da eingesetzt, wo irgendeine Variable hoch / oder runtergezählt wird (verdoppelt / halbiert oder ne andere einfache arithmetische Operation ist natürlich auch ok). Insbesondere werden nur Bedingungen geprüft, die die vorher initialisierte Variable beinhalten und diese irgendwie prüfen.
Bei allem, das komplexer ist, verwendet man stattdessen ne while-Schleife. Da ist man gewohnt, dass beliebig komplexe Abbruchbedingungen auftreten.


Benutzung des ternären Operators

Gut, machen Anfänger eher selten, weil sie den meist nicht kennen. Aber kaum dass man ihn gesehen hat kommen viele auf die Idee, dass man damit viel kürzeren Code schreiben kann. Aber leider auch kaum lesbaren...
Es gibt ein paar Fälle, wo dieser Operator auf jeden Fall Sinn macht. Zum Beispiel, wenn ne Verzweigung auf Ausdrucksebene deutlich übersichtlicher ist. Einfaches Beispiel:

String s = "Du hast " + anzahl + "Element" + (anzahl == 1 ? "" : "e") + " im Warenkorb";

Sobald es jedoch komplexer wird, muss man sehr genau hinschauen. Insbesondere ist der Operator kein Ersatz für if-else, wenn in jedem Zweig nur eine Anweisung vorkommt!

Nicht erwähnen muss ich wohl, dass man den Operator niemals und unter keinen Umständen schachteln sollte. (Genauso, wie man switch nicht schachtelt...)


Kryptische Bezeichner

Das wär vermutlich ne ganze eigene Diskussion für sich. Fakt ist auf jeden Fall, dass man sich klare und vernünftige Bezeichner für Methoden, Attribute und Variablen ausdenken sollte. Ein guter Name zeichnet sich dadurch aus, dass ohne zusätzliche Kommentare klar wird, um was es geht.
Schlecht ist es dagegen, Variablen der Form a, b, c1, c2, d, ... zu erzeugen. Ganz schlecht sind Variablen der Form __, ___, _____, ... Erschlagen wird, wer Unicode-Bezeichner wählt, die gleich aussehen, intern aber unterschieden werden können (Stichwort: kyrillisches a).


Stringvergleich mit ==

In Java ein ganz böses Foul, weil er in den meisten Fällen unerwartete Ergebnisse liefert. Noch schlimmer ist, dass in einigen Fällen das Ergebnis mit den Erwartungen doch übereinstimmt...

Ein paar Beispiele (an denen all die, dich sich damit noch nicht beschäftigt haben, mal überlegen können, wie das sein kann... Wink)

"test" == "test" -> true

"test" == "te" + "st" -> true

String s = "te";
"test" == s + "st" -> false

String s = "test";
"test" == s -> true

Damit es zu so was nicht kommen kann, sollte bei Stringvergleichen immer equals genutzt werden. Zumindest bis die auf die Idee kommen, dass Überladen von Operatoren in einigen Fällen nicht so dumm wär...


Increment / decrement in komplexeren Ausdrücken

Auch hier sollte man aufpassen. Sobald man nicht mehr sieht, was ein Ausdruck alles macht, ist Vorsicht geboten.

So was wie

if(--count == 0)

ist sicher kein Problem. Ausdrücke wie

i += ++i/i++

dagegen definitiv... (Sieht einer, was obiger Ausdruck tut?)




So viel erstmal... Ich bin gespannt, was euch noch so alles einfällt.
Wirt.-Inf.07
Senior Member
Benutzer-Profile anzeigen
Senior Member


Anmeldungsdatum: 04.06.2007
Beiträge: 1101

BeitragVerfasst am: 10 März 2008 - 23:18:01    Titel:

Das ist wirklich mal ein richtig interessanter Thread Exclamation

Viele dieser "Fehler" kenne ich aus eigener Erfahrung. Sad
Aber mir fallen gerade leider keine weiteren "Fehler" ein die erwähnenswert wären...
Wirt.-Inf.07
Senior Member
Benutzer-Profile anzeigen
Senior Member


Anmeldungsdatum: 04.06.2007
Beiträge: 1101

BeitragVerfasst am: 10 März 2008 - 23:37:43    Titel:

Zwei Fehler sind mir doch noch eingefallen:

Das Verwechseln von logischen Operatoren && und || mit den Bitoperatoren & und |.

Bei Arrays muss man auf den Index achten. Denn beispielsweise bei int test[20] ist der höchste Index 19 und NICHT 20, denn der kleinste Index eines Arrays ist 0.
Whoooo
Valued Contributor
Benutzer-Profile anzeigen
Valued Contributor


Anmeldungsdatum: 08.06.2005
Beiträge: 8988

BeitragVerfasst am: 11 März 2008 - 00:01:25    Titel:

Was steckt hinter dem Stringvergleich per == ? Benutzt Java Nullterminierung für Strings und speichert diese mit im String?

Außerdem kann man mit einer Sprache die weder Pointer noch Inline Assembler kennt doch gar keinen wirklichen Mist bauen. Wink
Fleischkind
Junior Member
Benutzer-Profile anzeigen
Junior Member


Anmeldungsdatum: 05.03.2008
Beiträge: 51

BeitragVerfasst am: 11 März 2008 - 00:17:52    Titel:

Whoooo hat folgendes geschrieben:
Was steckt hinter dem Stringvergleich per == ? Benutzt Java Nullterminierung für Strings und speichert diese mit im String?

Außerdem kann man mit einer Sprache die weder Pointer noch Inline Assembler kennt doch gar keinen wirklichen Mist bauen. Wink


na klar man muss nur kreativ sein *gg*
gotcha
Full Member
Benutzer-Profile anzeigen
Full Member


Anmeldungsdatum: 15.01.2007
Beiträge: 249

BeitragVerfasst am: 11 März 2008 - 08:23:50    Titel:

Moin,

mit == werden die Referenzen zweier Objekte verglichen, nicht der Inhalt der Objekte. Dafür gibt es, wie sarc schrieb die Methode equals.

Das kann man aber auch so lange falsch machen, bis man das verstanden hat. Wink Ich finde, das ist halt ein fundamentales Konzept in _dieser_ Programmiersprache.

Noch ein gern gemachter Fehler:

Wer oder was sind this und super.

Gruß
Whoooo
Valued Contributor
Benutzer-Profile anzeigen
Valued Contributor


Anmeldungsdatum: 08.06.2005
Beiträge: 8988

BeitragVerfasst am: 11 März 2008 - 10:06:29    Titel:

this dürfte wie in c++ ein Zeiger auf sich selbst sein (äh.. Java kennt keine Zeiger - was ist es dann?). Demnach vermute ich, dass super ein Zeiger (?) auf ein Objekt der Klasse ist, von der das Objekt abgeleitet worden ist - ähnlich dem inherited-Keyword bei TP/Delphi. So kann man auf überschriebene Methoden zurückgreifen. Aber wo sind diese Keywords eine Fehlerquelle?
gotcha
Full Member
Benutzer-Profile anzeigen
Full Member


Anmeldungsdatum: 15.01.2007
Beiträge: 249

BeitragVerfasst am: 11 März 2008 - 10:43:34    Titel:

Moin,

Richtig! this ist eine Referenz auf das aktuelle Objekt und super referenziert das Objekt von dem das aktuelle Objekt abgeleitet ist.

Die Keywords selbst sind nicht das Problem, sondern wann man sie einsetzt.

Z.B. beim Überladen von geerbten Methoden kann man mit super.geerbteMethode() auf die Methode des Objektes zugreifen von dem das aktuelle abgeleitet wurde.
Unschön, bzw je nach Ausprägung falsch, ist es für solche Zwecke eine Methode mit einer anderen Signatur in der abgeleiteteten Klasse zu erstellen.

this und super sind also in sofern Fehlerquellen, als das ein Programmieranfänger oft sagt: Ich will auf das da zugreifen, aber der Compiler meckert!

Das Problem ist wahrscheinlich eher das Verständnis für OO.

Gruß
Wirtschaftsinformatiker
Valued Contributor
Benutzer-Profile anzeigen
Valued Contributor


Anmeldungsdatum: 30.06.2006
Beiträge: 7083

BeitragVerfasst am: 11 März 2008 - 11:45:45    Titel:

Zitat:
(äh.. Java kennt keine Zeiger - was ist es dann?).


richtig Java kennt keine richtigen Zeiger, this ist eine Referenz, genauso wie

ClassA x = new ClassA();

x eine Referenz ist.

Falls man wie in C++ verkettete Listen selbst programmieren will, kann man das auch mit Referenzen machen.

Das tolle bei Java ist, dass der Garbage Collector nicht mehr referenzierte Objekte automatisch löscht.

Daher hilft man dem GC am besten, in dem man nicht mehr benötigte Instanzen auf null setzt.
TK1985
Senior Member
Benutzer-Profile anzeigen
Senior Member


Anmeldungsdatum: 16.09.2005
Beiträge: 988

BeitragVerfasst am: 11 März 2008 - 17:48:16    Titel:

Was sicher noch zu den häufigen Fehlern zählt ist folgendes:

Nicht initialisierte Zeiger/Referenzen

Einen Zeiger sollte man nach der Deklaration zumindest auf NULL zeigen lassen. So kann man recht leicht eine Ausnahembehandlung realisieren, indem man einen Zeiger auf NULL abfragt. Zeigt ein Pointer auf einen nicht initialisierten Speicherbereich und man versucht von dort zu lesen/schreiben verursaht das recht schnell Programmabstürze.
Beiträge der letzten Zeit anzeigen:   
Foren-Übersicht -> Informatik-Forum -> Häufige Fehler bei der Programmierung
Neues Thema eröffnen   Neue Antwort erstellen Alle Zeiten sind GMT + 1 Stunde
Gehe zu Seite 1, 2, 3  Weiter
Seite 1 von 3

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.

Chat :: Nachrichten:: Lexikon :: Bücher :: Impressum