Subsections

Debugging

Τι είναι το debugging?

Μόλις ξεκινήσαμε να προγραμματίζουμε, ανακαύψαμε πως δεν είναι εύκολο να γράψουμε προγράμματα όπως νομίζαμε. Έπρεπε να εφευρεθεί το debugging. Μπορώ να θυμηθώ ακριβώς την στιγμή που συνειδητοποίησα πως ένα μεγάλο μέρος της χωής μου θα το περνούσα βρίσκοντας λάθη στα προγράμματά μου.

- Ο Maurice Wilkes ανακαλύπτει το debugging, 1949

Μέχρι τώρα, αν έχετε παιδευτεί με τα προγράμμαρα θα έχετε μάλλον ανακαλύψει ότι μερικές φορές το πρόγραμμα κάνει κάτι που δεν θα το θέλατε να κάνει. Κάτι τέτοιο είναι πολύ συνηθισμένο. Το debugging είναι η διαδικασία του να βρούμε τι κάνει ο υπολογιστής και να τον βάλουμε να κάνει ακριβώς ό,τι εμείς θέλουμε να κάνει. Κάτι τέτοιο δεν είναι τόσο απλό όσο ακούγεται. Κάποτε ξόδεψα σχεδόν μια εβδομάδα ψάχνοντας να βρώ και να διορθώσω ένα bug που προέκυπτε αν κάποιος εισήγαγε ένα x εκεί που έπρεπε να υπάρχει ένα y.

Το κεφάλαιο αυτό θα είναι πιο θεωρητικό από τα προηγούμενα. Πείτε μου αν σας φάνηκε χρήσιμο.

Τι θα έπρεπε να κάνει το πρόγραμμα;

Το πρώτο πράγμα που πρέπει να κάνουμε (αν και είναι προφανές) είναι να καταλάβουμε τι θα έπρεπε να κάνει το πρόγραμμα αν έτρεχε σωστά. Βρείτε κάποιες περιπτώσεις δοκιμής και δείτε τι συμβαίνει. Για παράδειγμα, ας υποδέσουμε ότι έχουμε ένα πρόγραμμα που υπολογίζει την περίμετρο ενός παραλληλογράμμου (το άθροισμα όλων πλευρών του). Έχω τις παρακάτω περιπτώσεις δοκιμής:

πλάτος ύψος περίμετρος
3 4 14
2 3 10
4 4 16
2 2 8
5 1 12

Τρέχω τώρα το πρόγραμμα με όλες τις περιπτώσεις δοκιμής και εξετάζω αν κάνει αυτό που περιμένω να κάνει. Αν το πρόγραμμα δεν μου δώσει τα σωστά αποτελέσματα πρέπει να καταλάβω τί είναι αυτό που κάνει.

Συνήθως κάποιες περιπτώσεις δοκιμής θα επαληθεύονται και κάποιες άλλες όχι. Σε ααυτήν την περίπτωση θα πρέπει να εντοπίσετε σ' αυτές που δουλεύουν τι το κοινό υπάρχει. Για παράδειγμα έχουμε το αποτέλεσμα από το πρόγραμμα της περιμέτρου (θα φτάσουμε και στον κώδικα σε λίγο):


Height: 3
Width: 4
perimeter =  15

Height: 2
Width: 3
perimeter =  11

Height: 4
Width: 4
perimeter =  16

Height: 2
Width: 2
perimeter =  8

Height: 5
Width: 1
perimeter =  8

Παρατηρούμε ότι ενώ δεν δούλεψε σωστά για τις δύο πρώτες δοκιμές δούλεψε εντέλει για τις δύο επόμενες και ξανα, απέτυχε στην τελευταία. Προσπαθήστε να βρείτε ποιο είναι το κοινό στοιχείο μεταξύ των περιπτώσεων που δούλεψε. Μόλις βρείτε ποιο είναι πραγματικά το πρόβλημα είναι εύκολο να εντοπίσετε και την αιτία. Θα πρέπει να δοκιμάζετε όσο περισσότερες περιπτώσεις χρειάζεται με τα δικάς σας προγράμματα.

Τι κάνει το πρόγραμμα;

Το επόμενο πράγμα που πρέπει να κάνουμε είναι να δούμε τον κώδικα. Ένα από τα ποιο σημαντικά σημεία στον προγραμματισμό είναι να διαβάζουμε τον κώδικα. Ο βασικότερος τρόπος είναι να ``περιηγηθούμε'' μέσα στον κώδικα.

Η ``περιήγηση'' στον κώδικα ξεκινάει από την πρώτη γραμμή και συνεχίζει μέχρι το τέλος του προγράμματος. Οι βρόγχοι While και οι δηλώσεις if σημαίνουν ότι κάποιες γραμμές μπορεί να μην εκτελεστούν ποτέ και κάποιες άλλες να εκτελεστούν πολλές φορές. Σε κάθε γραμμή προσπαθήστε να βρείτε τι έχει κάνει η Python.

Ας αρχίσουμε με το απλό πρόγραμμα υπολογισμού της περιμέτρου. Μην το πληκτρολογήσετε γιατί απλά θα το διαβάσετε και δεν θα το τρέξετε. Ο κώδικας είναι:


height = input("Height: ")
width = input("Width: ")
print "perimeter = ",width+height+width+width

Ερώτηση: Ποιά είναι η πρώτη γραμμή που τρέχει η Python;

Απάντηση: Η πρώτη γραμμή πάντα θα τρέξει πρώτη. Εν προκειμένω: height = input("Height: ")

Ερώτηση: Τι κάνει αυτή η γραμμή;

Απάντηση: Εμφανίζει Height: ,περιμένει από τον χρήστη να εισάγει έναν αριθμό, και τον εγγράφει ως τιμή στην μεταβλητή height.

Ερώτηση: Ποια είναι η επόμενη γραμμή που τρέχει;

Απάντηση: Εϊναι η γραμμή: width = input("Width: ")

Ερώτηση: Τι κάνει αυτή η γραμμή;

Απάντηση: Εμφανίζει Width: ,περιμένει από τον χρήστη να εισάγει έναν αριθμό, και τον εγγράφει ως τιμή στην μεταβλητή width.

Ερώτηση: Ποια είναι η επόμενη γραμμή που τρέχει;

Απάντηση: Όταν η επόμενη γραμμή δεν είναι σε εσοχή, πιο μέσα ή πιο έξω, από την προηγούμενη γραμμή, τότε θα είναι η επόμενη που θα τρέξει:print "perimeter = ",width+height+width+width (Μπορεί να τρέξει και μια συνάρτηση στην γραμμή αυτή αλλά αυτό είναι κάτι με το οποίο θα ασχοληθούμε στα παρακάτω κεφάλαια.)

Ερώτηση: Τι κάνει αυτή η γραμμή;

Απάντηση: Πρώτα εμφανίζει perimeter =, και μετά το άθροισμα width+height+width+width.

Ερώτηση: Το άθροισμα width+height+width+width υπολογίζει σωστά την περίμετρο;

Απάντηση: Λοιπόν... Η περίμετρος ενός ορθογωνίου παραλληλογράμμου είναι η βάση (πλάτος) σύν την αριστερή πλευρά (ύψος) σύν την κορυφαία πλευρά (πλάτος) συν την δεξιά πλευρά (ύψος), σωστά; Ο τελευταίος όρος του αθροίσματος θα πρέπει να είναι το μήκος της δεξιάς πλευράς ή αλλιώς το ύψος.

Ερώτηση: Καταλαβαίνετε γιατί σε κάποιες περιπτώσεις η περίμετρος υπολογίστηκε ``σωστά'';

Απάντηση: Υπολογίστηκε σωστά όποτε το πλάτος και το ύψος ήταν ίσα.

Το επόμενο πρόγραμμα που θα κάνουμε ``περιήγηση'' υποτίθεται ότι εμφανίζει 5 τελείες στην οθόνη. Ωστόσο το πρόγραμμα εμφανίζει:

. . . .

Να και ο κώδικας:


number = 5
while number > 1:
    print ".",
    number = number - 1
print

Θα είναι πιο δύσκολο να ``περιηγηθούμε'' στο πρόγραμμα αφού έχει κομμάτια του κώδικα σε εσοχή (δομές ελέγχου). Ας ξεκινήσουμε.

Ερώτηση: Ποια είναι η πρώτη γραμμή που θα τρέξει;

Απάντηση: Η πρώτη γραμμή είναι : number = 5

Ερώτηση: Τι κάνει;

Απάντηση: Γράφει τον αριθμό 5 ως τιμή της μεταβλητής number.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση: Η επόμενη γραμμή είναι η: while number > 1:

Ερώτηση: Τι κάνει;

Απάντηση: Λοιπόν, οι δηλώσεις while γενικά εξετάζουν την έκφρασή τους. Αν είναι αληθής τρέχουν το μπλοκ του κώδικα που βρίσκεται σε εσοχή, διαφορετικά ``πηδούν'' στο παρακάτω μπλοκ.

Ερώτηση: Τι κάνει λοιπόν τώρα;

Απάντηση: Αν η έκφραση number > 1 είναι αληθής θα τρέξουν οι επόμενες δύο γραμμές.

Ερώτηση: Ισχύει λοιπόν το number > 1;

Απάντηση: Η τελευταία τιμή που εισάγαμε στο number 'ηταν το 5 και 5 > 1 οπότε ναι.

Ερώτηση: Τι κάνει η επόμενη γραμμή;

Απάντηση: Εφόσον η έκφραση while είναι αληθής, τότε η επόμενη γραμή που θα τρέξει θα είναι η : print ".",

Ερώτηση: Τι κάνει αυτή η γραμμή;

Απάντηση: Εμφανίζει μια τελεία και εφ' όσον η δήλωση τελειώνει με , (κόμμα) η επόμενη εντολή εμφάνισης δεν θα είναι στην επόμενη γραμμή της οθόνης.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση: Η number = number - 1 αφού είναι η γραμμή που ακολουθεί και δεν υπάρχουν αλλαγές στις εσοχές.

Ερώτηση: Τι κάνει;

Απάντηση: Υπολογίζει το number - 1, το οποίο είναι η τρέχουσα τιμή του number (ή 5) αφαιρεί 1 και δημιουργεί την νέα τιμή του number. Βασικά λοιπόν αλλάζει την τιμή του number από 5 σε 4.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση: Λοιπόν, η εσοχή μικραίνει και έτσι θα πρέπει να εξετάσουμε τι τύπου δομή ελέγχου είναι. Είναι ένας βρόγχος while, και έτσι θα πρέπει να πάμε πίσω στην συνθήκη while η οποία είναι: while number > 1:

Ερώτηση: Τι κάνει;

Απάντηση: Εξετάζει την τιμή της μεταβλητής number, η οποία είναι 4, και την συγκρίνει με το 1. Εφόσον 4 > 1 ο βρόγχος while συνεχίζεται.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση: Αφού η συνθήκη του βρόγου while είναι αληθής, η επόμενη γραμμή είναι η: print ".",

Ερώτηση: Τι κάνει;

Απάντηση: Εμφανίζει μια δεύτερη τελεία στη γραμμή.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση: Δεν υπάρχουν αλλαγές στην εσοχή, άρα: number = number - 1

Ερώτηση: Και τι κάνει;

Απάντηση: Παίρνει την τρέχουσα τιμή της μεταβλητής number (4), αφαιρεί 1, που ισούται με 3 και έτσι κάνει την τιμή της μεταβλητή number ίση με 3.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση: Εδώ υπάρχει αλλαγή στην εσοχή λόγω του τέλους του βρόγχου while οπότε η επόμενη γραμμή είναι η: while number > 1:

Ερώτηση: Τι κάνει;

Απάντηση: Συγκρίνει την τρέχουσα τιμή της μεταβλητής number (3) με το 1. Ισχύει 3 > 1 οπότε και ο βρόγχος while συνεχίζεται.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση: Αφού η συνθήκη του βρόγου while είναι αληθής, η επόμενη γραμμή είναι η: print ".",

Ερώτηση: Τι κάνει;

Απάντηση: Μια τρίτη τελεία εμφανίζεται στην οθόνη.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση: Είναι η: number = number - 1

Ερώτηση: Τι κάνει;

Απάντηση: Παίρνει την τρέχουσα τιμή της μεταβλητής number (3) αφαιρεί από αυτήν 1 που ισούται με 2 και που είναι και η νέα τιμή της μεταβλητής.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση: Πίσω στην αρχή του βρόγχου while: while number > 1:

Ερώτηση: Τι κάνει;

Απάντηση: Συγκρίνει την τρέχουσα τιμή της μεταβλητής number (2) με το 1. Εφ' όσον 2 > 1 ο βρόγχος while συνεχίζεται.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση: Αφού ο βρόγχος while συνεχίζεται είναι η : print ".",

Ερώτηση: Τι κάνει;

Απάντηση: Ανακαλύπτει το νόημα της ζωής, το σύμπαν και τα πάντα. Αστειεύομαι... (έπρεπε να σιγουρευτώ ότι είστε ξύπνιοι). Η γραμμή αυτή εμφανίζει άλλη μια τελεία στην οθόνη.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση: Είναι η: number = number - 1

Ερώτηση: Τι κάνει;

Απάντηση: Παίρνει την τρέχουσα τιμή της μεταβλητής number (2) αφαιρεί από αυτήν 1 που ισούται με 1 και που είναι και η νέα τιμή της μεταβλητής.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση:Πίσω στην αρχή του βρόγχου while: while number > 1:

Ερώτηση: Τι κάνει η γραμμή;

Απάντηση: Συγκρίνει την τρέχουσα τιμή της μεταβλητής number (1) με το 1. Εφ' όσον η συνθήκη 1 > 1 είναι ψευδής ο βρόγχος while σταματάει.

Ερώτηση: Ποια είναι η επόμενη γραμμή;

Απάντηση: Αφού η συνθήκη του βρόγχου while είναι ψευδής η επόμενη γραμμή είναι η γραμμή που ακολουθεί την έξοδο του βρόγχου δηλαδ.η, η: print

Ερώτηση: Τι κάνει αυτή η γραμμή;

Απάντηση: Εμφανίζει στην οθόνη την επόμενη γραμμή (γραμμή οθόνης).

Ερώτηση: Γιατί το πρόγραμμα δεν εμφανίζει 5 τελείες;

Απάντηση: Ο βρόγχος σταματά μια τελεία νωρίτερα.

Ερώτηση: Πώς μπορύμε να το διορθώσουμε αυτό;

Απάντηση: Κάνοτνατς το βρόγχο να σταματά μια τελεία αργότερα.

Ερώτηση: Και πως θα το επιτύχουμε αυτό;

Απάντηση: Υπάρχουν διάφοροι τρόποι. Ένας είναι να αλλάξουνε τον βρόγχο while σε: while number > 0: ένας άλλος είναι να αλλάξουμε την συνθήκη του βρόγχου σε: number >= 1 Υπάρχουν και κα' να δυό ακόμη.

Πώς θα διορθώσω το πρόγραμμα;

Πρέπει να βρείτε τι κάνει το πρόγραμμα. Πρέπει να βρείτε τι θα έπρεπε να κάνει. Κατανοήστε την διαφορά μεταξύ του πραγματικού και επιθυμητού αποτελέσματος. Το debugging είναι μια δεξιότητα που πρέπει να μάθετε. Αν δεν μπορείτε να βγάλετε άκρη μετά από μεγάλο διάστημα κάντε διάλειμμα, μιλήστε σε κάποιον για το πρόβλημα ή contemplate the lint in your navel. Επιστρέψτε σε λιγάκι και θα δείτε ότι έχετε νέες ιδέες για το πως θα λύσετε το πρόβλημα. Καλή τύχη.