@Hellstorm: Vorweg: Es kommt auch auf die Programmiersprache an. Ich könnte mir *nicht* vorstellen Java ohne IDE zu schreiben, weil dort die IDE tatsächlich Vorteile bietet.
Einen Debugger brauche ich in Python nicht. Oder nur *ganz* selten. Ich denke das liegt hauptsächlich an drei Dingen: Man kann mit ``print`` oder dem `logging`-Modul und `type()` und `repr()` sehr einfach Debugausgaben zu einem Programm hinzufügen um zu überprüfen ob bestimmte Programmteile ausgeführt werden, in welcher Reihenfolge, und welche Werte dort jeweils vorliegen.
Zweitens schreibt man für gewöhnlich kleine in sich abgeschlossene Code-Teile die man einzeln testen kann, heutzutage auch mit Unit-Tests, und die dann zu komplexeren Lösungen zusammengesetzt werden. Man findet Fehler also in der Testphase, wo man die bisher bestehenden Teile ausprobiert und mit Testwerten füttert.
Und drittens sehe ich den wirklichen Nutzen von Debuggern bei kompliziertem, „kleinteiligen”, aber langem Code wie man ihn häufig in hardwarenäheren Programmiersprachen findet, wo man deutlich mehr Code in einer Funktion oder Methode benötigt um den selben Effekt zu erzielen wie in Python, Code bei dem man mehr Namen hat, weil man für alles mögliche noch Index-, Lauf-, und Hilfsvariablen braucht, und damit auch schneller den Über- oder Durchblick verlieren kann. Bei Python hingegen bestehen Funktionen und Methoden oft aus nur wenigen Zeilen und Schleifen und ausgiebig getestete Algorithmen sind in Funktionen „versteckt”, von denen es viele schon fertig in der Standardbibliothek gibt.
C ist zum Beispiel eine Programmiersprache bei der ich mir vorstellen kann einen Debugger zu verwenden, weil man durch den Compiler nicht so leicht wie bei Python immer wieder kleine Änderungen vornehmen und das Programm neu laufen lassen kann. Man kann auch keine Ausdrücke oder bereits bestehenden Code in einer interaktiven Shell ausprobieren. Hier mal ein Extrembeispiel was ich mit „kleinteiligem” aber langem Code meine (Datentypen und Funktionen aus der Glib, grossteils ungetestet):
Code: Alles auswählen
GHashTable* read_word_file(const gchar *filename, GError **error)
{
GIOChannel *word_file;
GHashTable *result;
gchar *word;
g_assert(filename != NULL);
if ((word_file = g_io_channel_new_file(filename, "r", error)) == NULL) {
return NULL;
}
result = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
while (
g_io_channel_read_line(word_file, &word, NULL, NULL, NULL)
== G_IO_STATUS_NORMAL
) {
g_hash_table_add(result, g_strstrip(word));
}
if (*error != NULL) {
g_hash_table_unref(result);
result = NULL;
}
g_io_channel_unref(word_file);
return result;
}
void intersection(GHashTable *set_a, GHashTable *set_b)
{
GHashTableIter iterator;
gchar *word;
g_assert(set_a != NULL && set_b != NULL);
g_hash_table_iter_init(&iterator, set_a);
while (g_hash_table_iter_next(&iterator, (gpointer*) &word, NULL)) {
if (!g_hash_table_lookup_extended(set_b, word, NULL, NULL)) {
g_hash_table_iter_remove(&iterator);
}
}
}
GHashTable* get_common_words(
gint filename_count, gchar **filenames, GError **error
) {
gint i;
GHashTable *result, *word_set;
g_assert(filename_count != 0 && filenames != NULL);
if ((result = read_word_file(filenames[1], &error)) == NULL) {
return NULL;
}
for (i = 1; i < filename_count; i++) {
if ((word_set = read_word_file(filenames[i], &error)) == NULL) {
g_hash_table_unref(result);
return NULL;
} else {
intersection(result, word_set);
g_hash_table_unref(word_set);
}
}
return result;
}
Das gleiche in Python (`and_()` ist aus dem `operator`-Modul):
Code: Alles auswählen
def read_tokens(filenames):
for filename in filenames:
with io.open(filename, encoding='utf8') as lines:
yield set(line.strip() for line in lines)
def get_common_tokens(filenames):
return reduce(and_, read_tokens(filenames))
Hier wüsste ich nicht einmal wo ich den Debugger sinnvoll ansetzen sollte.
Keine IDE zu verwenden bedeutet übrigens auch nicht auf einen Debugger verzichten zu müssen. Python hat einen in der Standardbibliothek im `pdb`-Modul. Man kann im Quelltext die Zeile ``import pdb; pdb.set_trace()`` schreiben und an der Stelle wird das Programm dann angehalten und man ist im Debugger. Wenn man eine GUI haben möchte, gibt es WinPDB. Nicht vom Namen irreführen lassen: Das läuft nicht nur unter Windows.
Springen zu Funktionsdefinitionen hat ein guter Texteditor wie lunar schon sagte. Das ist letztendlich nichts anderes als eine spezielle Suchfunktion. Und so viel anderes gibt es bei dynamischen Sprachen ja nicht. Mir persönlich reicht eine Autovervollständigung die sich die Vorschläge aus den offenen Textdateien nimmt. Andere nehmen noch die bei sehr dynamischen Sprachen naturgemäss nicht perfekte statische Analyse von installierten Modulen und Paketen hinzu, die auch die meisten guten Editoren bieten.