Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

@migf1 ευγε για τη μορφή που εχει γραφεί ο κώδικας (σχόλια, δομή, εξηγήσεις, κλπ)

Χαίρεσαι να το διαβάζεις! 

 

Δεν διαφωνώ απλά είναι περιττό-πολύ κουραστικό αυτό το πράγμα σε προγράμματα 50-60-100 γραμμών.

 

Ξέρω την συγκεκριμένη άσκηση, θέλει πολύ απλά πράγματα και όχι "επαγγελματική" λύση.

 

ΥΓ: Δεν έχω τίποτα με τον migf, το παιδί ασχολείται εδώ και προσφέρει βοήθεια και μπράβο του, απλά λέω ότι έτσι όπως το έχει ένας νεος χάνεται στα σχόλια και στον τρόπο δόμησης και θέλει κάποια σχετική γνώση.

Δημοσ.

Δεν διαφωνώ απλά είναι περιττό-πολύ κουραστικό αυτό το πράγμα σε προγράμματα 50-60-100 γραμμών.

 

Ξέρω την συγκεκριμένη άσκηση, θέλει πολύ απλά πράγματα και όχι "επαγγελματική" λύση.

 

ΥΓ: Δεν έχω τίποτα με τον migf, το παιδί ασχολείται εδώ και προσφέρει βοήθεια και μπράβο του, απλά λέω ότι έτσι όπως το έχει ένας νεος χάνεται στα σχόλια και στον τρόπο δόμησης και θέλει κάποια σχετική γνώση.

Καταρχήν να σημειώσω πως επίτηδες το έκανα με πίνακα από struct που μεταξύ άλλων περιέχει και function pointers, για να ελαχιστοποιήσω τις πιθανότητες να παραδοθεί ως έχει σε περίπτωση που πρόκειται για εργασία σχολής (κάτι τέτοιο πιστεύω θα υποψίαζε και τον πλέον αδιάφορο καθηγητή/διορθωτή σε οποιοδήποτε εισαγωγικό μάθημα προγραμματισμού).

 

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

 

Σχετικά με τη δόμηση, αν εξαιρέσεις το ότι ορίζω τις συναρτήσεις με τη σωστή σειρά τους ώστε να μη χρειάζονται forward declaration (και άρα οι ορισμοί τους πάνε από το τέλος προς την αρχή, με τη main() στο τέλος), ο γενικότερος σκελετός δόμησης αποτελεί επίσης στοιχειώδη πρακτική σε μικρά προγράμματα που υλοποιούνται σε ένα μόνο source module (δηλαδή: inclusions, macros, custom types, global variables, forward declarations, function definitions).

 

Επίσης δεν είμαι σίγουρος πως εννοείς την "επαγγελματική" λύση, διότι ο κώδικας που πόσταρα απέχει πολύ από το να χαρακτηριστεί επαγγελματικός. Σε επαγγελματικό κώδικα, π.χ. αντί να σχολιάζουμε λεπτομερώς την κάθε συνάρτηση μέσα στο .c αρχείο, βάζουμε όλα τα function prototypes σε ξεχωριστό header file το οποίο κάνουμε include, και κάνουμε εκεί το documentation (στο .c αρχείο βάζουμε μόνο μια πολύ σύντομη περιγραφή της κάθε συνάρτησης, όχι περισσότερες από 2-3 γραμμές για την κάθε μια τους, και όχι σε όλες.

 

Αποφεύγουμε επίσης να σκορπάμε strings μέσα στον κώδικα δεξιά κι αριστερά (εκτός αν είναι για debugging purposes) και προτιμάμε να τα έχουμε όλα μαζί μαζεμένα κάπου (είτε σε header αρχείο, είτε σε εξωτερικό αρχείο που το διαβάζουμε στο runtime) για να μπορεί να γίνει εύκολα internationalized... ακόμα και αν χρησιμοποιήσουμε το gettext() interface για το internationalization, το οποίο δημιουργεί αυτόματα τέτοιο αρχείο, εξυπηρετεί μακράν περισσότερο όταν τα strings μας είναι όλα μαζεμένα σε ένα μέρος.

 

Επίσης, σε επαγγελματικές λύσεις, τα debugging messages είναι conditional (είτε μέσω διαφορετικών releases, είτε με conditional compilation). Ακόμα, σε επαγγελματικές λύσεις το project χωρίζεται σε modules (π.χ. οι generic συναρτήσεις μπαίνουν σε δικό τους source-code module). Κλπ, κλπ, κλπ.

 

Εν ολίγοις, ο κώδικας που πόσταρα απέχει παρασάγγας από το να χαρακτηριστεί "επαγγελματική λύση".

 

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

  • Like 1
Δημοσ.

Αν δεν μας δώσει την εκφώνηση το παιδί δεν μπορώ να μιλήσω και συγκεκριμένα, έχω καταλάβει ότι είναι μια κλασική άσκηση που λέει

  • Ζήτα έναν αριθμό (το βαφτίζει επίπεδο δυσκολίας)
  • Ανάλογα με το επίπεδο δυσκολίας δημιουργεί 2 αριθμούς (Εύκολο: 1-9, Μέτριο: 10-99, Δύσκολο: 100-999 ...)
  • Αφού δημιουργήσει τους 2 αυτούς αριθμούς ζητάει από τον χρήστη να απαντήσει σε κάποιες πράξεις
  • Ελέγχει την απάντηση και επιστρέφει το κατάλληλο μήνυμα.

Για κάθε ενέργεια θέλει και υποπρόγραμμα μάλλον. (δεν ξέρω αν το ζητάει ή το αφήνει στην ευχέρεια του καθενός).

 

 

Γιατί λοιπόν έγραψα αυτά που έγραψα!

 

Γιατί πιστεύω ότι είναι "too much", κάθε συνάρτηση και σχόλιο 10+ γραμμών. Αυτό να το κάνεις όταν φτιάχνεις ένα πρόγραμμα στην δουλειά (και σε ένα δικό σου Project 'Χόμπι') αλλά όχι σε μια απλή εργασία. (αυτή η γνώμη μου).

 

Δεν είπα και δεν λέω ότι είναι λάθος, αντίθετα!, απλά η λογική όπως το έγραψες απέχει από αυτήν ενός 1οετή.

 

Το ζητούμενο από έναν 1οετή (1ο εξάμηνο) είναι:

  • Πως δηλώνουμε local ή global μεταβλητές
  • Πως αρχικοποιούμε μεταβλητές, με ποια κριτήρια επιλέγουμε τον τύπο
  • Πως δηλώνουμε-καλούμε συναρτήσεις
  • Πως επιστρέφουμε κάτι από μια συνάρτηση.
  • Πως ελέγχουμε κάτι

Ας μάθουν πρώτα αυτά και κάποια άλλα που ίσως μου ξέφυγαν και μετά μιλάμε για Inline συναρτήσεις.

 

Έχεις 3 structs, πολλές δεν είναι για μια άσκηση που κυρίως θέλει να εξετάσει τους φοιτητές σε αυτά που έγραψα πάνω? έρχεται 2ο δηλαδή το "αν ο φοιτητής μπορεί να δηλώσει σύνθετους τύπους δεδομένων". (κρατάω παραθυράκι εδώ, δέχομαι και αυτόν τον "δύσκολο" τρόπο απλά όπως είπα πρέπει πρώτα να μάθουν τα βασικά που έγραψα πάνω )

 

Έχεις κάποια defines, συμφωνώ! απλά έχω μια ερώτηση στο παρακάτω

#define FLOAT_EQUAL(f1, f2)	( fabsf((f1)-(f2)) <= FLOAT_DELTA )

μήπως είναι λίγο ζόρικο; μιλάμε τώρα για ανθρώπους που κάνουν τα πρώτα τους βήματα, και εδώ κρατάω παραθυράκι γιατί αν δεν ασχοληθείς - παιδευτείς δεν θα μάθεις.

 

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

 

Για να μην νομίζει και κανείς δηλαδή... δεν είπα τίποτα για σένα και δεν έχω τίποτα, βλέπω ότι κάνεις δουλειά στο φορουμ και από μένα αξίζεις μπραβο.

 

Απλά ρώτησα αν ήταν κάπως "too much" για έναν που είναι 1ο εξάμηνο? βάζω στοίχημα ότι δεν θα μπορέσει να το στηρίξει αυτό. Θα μπορούσε αν ήξερε από μόνος του μερικά πράγματα αλλά αν ήξερε θα ζήταγε βοήθεια? 


....

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

 

Δεν έγραψα ότι έγραψα για να σε κοντράρω, με αυτά που βλέπω γνωρίζεις πολύ περισσότερα από μένα :P . απλά όπως και έγραψα έχω την απορία "μήπως είναι δύσκολος ο κώδικας για έναν αρχάριο" ?

Δημοσ.

Δεν διαφωνώ απλά είναι περιττό-πολύ κουραστικό αυτό το πράγμα σε προγράμματα 50-60-100 γραμμών.

 

Ξέρω την συγκεκριμένη άσκηση, θέλει πολύ απλά πράγματα και όχι "επαγγελματική" λύση.

 

ΥΓ: Δεν έχω τίποτα με τον migf, το παιδί ασχολείται εδώ και προσφέρει βοήθεια και μπράβο του, απλά λέω ότι έτσι όπως το έχει ένας νεος χάνεται στα σχόλια και στον τρόπο δόμησης και θέλει κάποια σχετική γνώση.

Διαφωνώ. Τα σχόλια ειναι το Α και το Ω και για τον προγραμματιστή (φοιτητή ή όχι) αλλά και τον εξεταστή. Ο φοιτητής/προγραμματιστής γιατί μπορεί να καταλάβει τι γίνεται στο Χ σημείο και ο εξεταστής τι σκατά κάνει σε εκείνο το σημείο ο φοιτητής. Ο προγραμματισμός απαιτεί «οργανωτικό τρόπο σκέψης» και τα σχόλια είναι απαραίτητα. Όσες φορές μου πασάρανε κωδικα για έλεγχο (δεν είμαι εξεταστής) και δεν είχε επαρκή σχόλια, τον έστελνα πίσω για προσθήκη σχολίων. Αυτός που διαβάζει τον κώδικα δεν εχει τη μαγική σφαίρα μαντείας. Το άλλο που θεωρώ πολύ σημαντικό ειναι η καλή ονοματολογία μεταβλητών και συναρτήσεων. 

 

Αντί λοιπον για 

int sd1(char onoma, int ct)
{
....
return ct;
}

είναι πολύ πιο ευκολο για ΟΛΟΥΣ το

/* metrisi plithous grammaton onomatos kai epistrofi*/
int countChars(char onoma, int plithos)
  {
      ....
     return plithos; //epistrofi plithos xaraktiron
  } //of countChars
Δημοσ.

@arc: Τις περισσότερες φορές συμφωνώ μαζί σου αλλά εδώ έχω μια ένσταση. Όχι στην ουσία της απάντησής σου, απλά στο παράδειγμα που χρησιμοποίησες. Είναι contrived και φτάνει σε επίπεδο αντι-παραδείγματος. Ας μη ξεχνάμε πως ακόμα και το καλύτερο πράγμα στον κόσμο (το ροκφόρ) υπάρχει ένα σημείο από το οποίο και μετά η χρήση του γίνεται κατάχρηση. Έτσι και στα comments.

 

Μου θύμισε λίγο το κλασικό παράδειγμα του τι δεν πρέπει να κάνεις...

// check if amount is greater than 100
if (amount > 100) {
    // print message
    printf("That's quite a lot!\n");
} // if

Σίγουρα δε λέω κάτι που δεν ξέρεις, αλλά επειδή το παράδειγμα το βλέπουν κι άλλοι είπα να βάλω και τον αντίλογο.

  • Like 1
Δημοσ.

Αν δεν μας δώσει την εκφώνηση το παιδί δεν μπορώ να μιλήσω και συγκεκριμένα, έχω καταλάβει ότι είναι μια κλασική άσκηση που λέει

  • Ζήτα έναν αριθμό (το βαφτίζει επίπεδο δυσκολίας)
  • Ανάλογα με το επίπεδο δυσκολίας δημιουργεί 2 αριθμούς (Εύκολο: 1-9, Μέτριο: 10-99, Δύσκολο: 100-999 ...)
  • Αφού δημιουργήσει τους 2 αυτούς αριθμούς ζητάει από τον χρήστη να απαντήσει σε κάποιες πράξεις
  • Ελέγχει την απάντηση και επιστρέφει το κατάλληλο μήνυμα.
Για κάθε ενέργεια θέλει και υποπρόγραμμα μάλλον. (δεν ξέρω αν το ζητάει ή το αφήνει στην ευχέρεια του καθενός).

 

Όπως το κατάλαβα εγώ από τον κώδικα του ts (όπως το υλοποίησα δηλαδή) το πρόγραμμα ζητάει αρχικά seed για την srand και έναν αριθμό που εσωτερικά τον αξιοποιεί μονάχα για τιμές από 1 έως και 5 (οτιδήποτε άλλο το κάνει treat ως 5). Ο αριθμός αυτός καθορίζει από ποιο εύρος τιμών θα επιλέγονται τυχαία 2 floats, που χρησιμοποιούνται ως οι όροι μιας αριθμητικής πράξης.

 

Κατόπιν, επί 10 γύρους διαλέγει τυχαία 2 όρους και μια πράξη, εκτελεί την πράξη στους επιλεγμένους όρους και κρατάει το αποτέλεσμα. Στη συνέχεια παρουσιάζει την πράξη στον χρήστη ( όρος1 σύμβολο-πράξης όρος2 = ; ) του ζητάει το αποτέλεσμα κι ανάλογα αν είναι σωστό ή λάθος τον ενημερώνει και τον βαθμολογεί.

 

Στο τέλος των 10 γύρων του παρουσιάζει τους μέσους όρους της βαθμολογίας του ανά τύπο πράξης, μαζί με προφορική αξιολόγηση βασισμένη σε βαθμιαία ποσόστωση επιτυχών απαντήσεων ανά τύπο πράξης. Ο πίνακας αναγράφει και τις ονομασίες της κάθε πράξης, καθώς και τη συχνότητα εμφάνισης πράξεων από τον κάθε τύπο (στον κώδικα του ts οι πληροφορίες αυτές παρουσιάζονταν πιο "χύμα" αντί για πινακάκι, αλλά η ουσία είναι πως τις τύπωνε όλες).

EPIDOSEIS
---------
Prosthesh (5)   : -50   Den ta phges katholoy kala
Afairesh  (2)   : -20   Den ta phges katholoy kala
Pol/smos  (1)   : -10   Den ta phges katholoy kala
Diairesh  (2)   : -20   Den ta phges katholoy kala
Έχοντας πλέον μια σαφώς ορισμένη εκφώνηση, μπορείς να δοκιμάσεις να γράψεις το πρόγραμμα.

 

Πραγματικά έχω περιέργεια να δω τι ακριβώς εννοείς στο προηγούμενο ποστ σου. Δεν τίθεμαι θέμα κόντρας, δεν κάνουμε διαγωνισμό. Ενδεχομένως να παρουσιάσεις πολύ πιο καθαρή, πιο κατανοητή, πιο robust και πιο επεκτάσιμη υλοποίηση, από την οποία θα μπορέσω να επωφεληθώ κι εγώ και άλλοι που θα τύχει να διαβάσουν το νήμα.

 

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

 

Εγώ επέλεξα το 1ο, μιας και θεώρησα πως αφενός δυσκολεύει τον ts να το παραδώσει ως δικιά του εργασία (αφού πιθανότατα περιέχει πολλά πράγματα εκτός ύλης του) κι αφετέρου επειδή η χρήση πινάκων με function pointers για τέτοιες δουλειές αποτελούν λίγο-πολύ τον κανόνα.

 

Λογικά με parallel arrays θα χρειαστούν περισσότερες γραμμές κώδικα, κι ενδεχομένως λίγο πιο messy, χωρίς να είναι κατ' ανάγκη πιο κατανοητή η λογική. Με χύμα μεταβλητές θα γεμίσει ο τόπος από switch και από duplicated κώδικα (ή από monster-size συναρτήσεις).

 

Θα μπορούσε επίσης να γραφεί και όλο το πρόγραμμα μόνο στη main ή με 2-3 μόνο επιπλέον συναρτήσεις. Το μέγεθός του μόνο απαγορευτικό δεν είναι για κάτι τέτοιο, ειδικά αν χρησιμοποιηθούν structs παρόμοια με αυτά που έδειξα. Νομίζω όμως πως κάτι τέτοιο δεν εμπίπτει στα ζητούμενα της συγκεκριμένης εργασίας (αν και προσωπικά δεν το θεωρώ καθόλου κακή προσέγγιση για κάποιον που θέλει να εξοικειωθεί με πίνακες και δομές όταν τις πρωτο-συναντάει... πριν αρχίσει δηλαδή να τα μπαινο-βγάζει ως ορίσματα σε συναρτήσεις, κλπ.)

 

Ωστόσο πρώτος μου στόχος ήταν να τεκμηριώσω με κώδικα τα σημεία που είχα θίξει αμέσως νωρίτερα, δηλαδή τις επισημάνσεις περί καθαρού & στοιχισμένου κώδικα, σχολίων, εύστοχων ονομασιών σε μεταβλητές, τύπους, συναρτήσεις, κλπ και χρήση όσο το δυνατόν μικρότερου scope στους ορισμούς τους. Αυτά είναι γενικής φύσης, ανεξάρτητα από projects, αλγόριθμους και προσέγγιση, τα οποία είναι θεμελιώδη και κρίσιμα σε όλες τις γλώσσες και σε όλα τα επίπεδα (από αρχάριους μέχρι βετεράνους).

 

Btw, δεν ξέρω τι εννοείτε όταν λέτε "υποπρόγραμμα" σε αυτό το νήμα. Μήπως θέλετε να πείτε "συνάρτηση";

 

Γιατί λοιπόν έγραψα αυτά που έγραψα!

 

Γιατί πιστεύω ότι είναι "too much", κάθε συνάρτηση και σχόλιο 10+ γραμμών. Αυτό να το κάνεις όταν φτιάχνεις ένα πρόγραμμα στην δουλειά (και σε ένα δικό σου Project 'Χόμπι') αλλά όχι σε μια απλή εργασία. (αυτή η γνώμη μου).

 

Δεν είπα και δεν λέω ότι είναι λάθος, αντίθετα!, απλά η λογική όπως το έγραψες απέχει από αυτήν ενός 1οετή.

 

Το ζητούμενο από έναν 1οετή (1ο εξάμηνο) είναι:

  • Πως δηλώνουμε local ή global μεταβλητές
  • Πως αρχικοποιούμε μεταβλητές, με ποια κριτήρια επιλέγουμε τον τύπο
  • Πως δηλώνουμε-καλούμε συναρτήσεις
  • Πως επιστρέφουμε κάτι από μια συνάρτηση.
  • Πως ελέγχουμε κάτι
Ας μάθουν πρώτα αυτά και κάποια άλλα που ίσως μου ξέφυγαν και μετά μιλάμε για Inline συναρτήσεις.

 

Έχω τελείως διαφορετική άποψη. Για μένα τα πρώτα που πρέπει να διδάσκονται σε πρωτοετείς προγραμματισμού ειδικά για τη C είναι (χωρίς απαραίτητα με αυτή τη σειρά): το command line sequence για την παραγωγή ενός εκτελέσιμου, το memory layout ενός εκτελέσιμου, ο γενικός σκελετός ενός πηγαίου αρχείου (βλέπε το spoiler που ακολουθεί), η σωστή στοίχιση του κώδικα, η σωστή χρήση σχολίων, η χρήση εύστοχων ή ιδιωματικών ονομασιών, η αποφυγή της scanf() για interactive input, η έννοια του scope και τέλος η χρήση debugger.

 

 

 

Σκελετός ενός αρχείου .c

/***********************************************
 * Description of what this program does,
 * along with additional information such
 * as author, date, compilation notes, etc.
 ***********************************************
 */

/* -----------------------
 * Header File Inclusions
 * -----------------------
 */

/* ----------------------------------
 * Type Forward Declarations (typedefs)
 * ----------------------------------
 */

/* ----------------------------------
 * Macros & Global Constants
 * ----------------------------------
 */

/* ----------------------------------
 * Custom Types
 * ----------------------------------
 */

/* ----------------------------------
 * Global Variables
 * ----------------------------------
 */

/* ----------------------------------
 * Function Forward Declarations (prototypes)
 * ----------------------------------
 */

/* ----------------------------------
 * Function Definitions
 * ----------------------------------
 */

/*******************************************//**
 * Application's entry point.
 ***********************************************
 */
int main( int argc, char *argv[] )
{
	

	return 0;
}

 

Και προφανώς συνδυαζόμενα με απλά προγράμματα, που θα έχουν ως στόχο να εντυπωθούν σε πρώτη φάση οι παραπάνω έννοιες.

 

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

 

 

Έχεις 3 structs, πολλές δεν είναι για μια άσκηση που κυρίως θέλει να εξετάσει τους φοιτητές σε αυτά που έγραψα πάνω? έρχεται 2ο δηλαδή το "αν ο φοιτητής μπορεί να δηλώσει σύνθετους τύπους δεδομένων". (κρατάω παραθυράκι εδώ, δέχομαι και αυτόν τον "δύσκολο" τρόπο απλά όπως είπα πρέπει πρώτα να μάθουν τα βασικά που έγραψα πάνω )

Τον κώδικα τον έγραψα χωρίς να γνωρίζω τι γνωρίζουν και τι όχι. Όπως είπα και παραπάνω όμως, ο βασικός μου στόχος ήταν τα σημεία που είχα θίξει αμέσως πριν από τον κώδικα. Η οργανωτική υλοποίηση έπεται ως concept (παρεμπιπτόντως, κανονικά θα έβαζα και τις προφορικές αξιολογήσεις σε πίνακα, αλλά είπα να μην το... παραχέσω :P ).

 

Έχεις κάποια defines, συμφωνώ! απλά έχω μια ερώτηση στο παρακάτω

#define FLOAT_EQUAL(f1, f2)	( fabsf((f1)-(f2)) <= FLOAT_DELTA )
μήπως είναι λίγο ζόρικο; μιλάμε τώρα για ανθρώπους που κάνουν τα πρώτα τους βήματα, και εδώ κρατάω παραθυράκι γιατί αν δεν ασχοληθείς - παιδευτείς δεν θα μάθεις.

 

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

 

Χωρίς αυτό το macro, το συγκεκριμένο παιχνίδι πολύ απλά δεν δουλεύει! Τις μισές (αν όχι όλες) τις σωστές απαντήσεις του παίκτη θα τις βγάζει λάθος.

 

Για να μην νομίζει και κανείς δηλαδή... δεν είπα τίποτα για σένα και δεν έχω τίποτα, βλέπω ότι κάνεις δουλειά στο φορουμ και από μένα αξίζεις μπραβο.

 

Απλά ρώτησα αν ήταν κάπως "too much" για έναν που είναι 1ο εξάμηνο? βάζω στοίχημα ότι δεν θα μπορέσει να το στηρίξει αυτό. Θα μπορούσε αν ήξερε από μόνος του μερικά πράγματα αλλά αν ήξερε θα ζήταγε βοήθεια?

 

 

Δεν έγραψα ότι έγραψα για να σε κοντράρω, με αυτά που βλέπω γνωρίζεις πολύ περισσότερα από μένα :P . απλά όπως και έγραψα έχω την απορία "μήπως είναι δύσκολος ο κώδικας για έναν αρχάριο" ?

Δεν το πήρα ως κόντρα ρε συ. Ούτε με ενδιαφέρει να κοντραριστώ με τον οποιονδήποτε. Απλώς προσπαθώ να μεταφέρω εμπειρίες σε ένα αντικείμενο που τυγχάνει να έχω έχω ασχοληθεί πολύ (C programming), με την ελπίδα και την ευχή οι μελλοντικοί συνάδελφοι να γίνουν ταχύτερα καλύτεροι από μας και να προχωρήσουν τον κλάδο στη χώρα μας.

 

Επίσης, μέσα από τέτοιες συζητήσεις βελτιώνομαι κι εγώ. Αυτός είναι και ο βασικός λόγος που σου ζητάω να παραθέσεις κώδικα. Διότι δηλαδή δεν το θεωρώ καθόλου απίθανο να περιέχει είτε στο σύνολό του είτε αποσπασματικά καλύτερες υλοποιήσεις/προσεγγίσεις.

  • Like 1
Δημοσ.

Συνήθως σχολια βαζουμε για να εξηγήσουμε το "γιατι" και όχι το "τι κανει".

 

Ολοι καταλαβαινουν τι κανει ο παρακατω κώδικας. 

Το σχόλιο εξηγει το γιατι κοβουμε το path.

 
            string newFile = GetNewFileName();
            if(newFile.Length > 250)
                newFile = newFile.Substring(0, 250); //Windows doesn't allow paths >250
            File.Copy(oldFile, newFile);
Δημοσ.

Συνήθως σχολια βαζουμε για να εξηγήσουμε το "γιατι" και όχι το "τι κανει".

 

Ολοι καταλαβαινουν τι κανει ο παρακατω κώδικας. 

Το σχόλιο εξηγει το γιατι κοβουμε το path.

 

 

            string newFile = GetNewFileName();
            if(newFile.Length > 250)
                newFile = newFile.Substring(0, 250); //Windows doesn't allow paths >250
            File.Copy(oldFile, newFile);

 

Όλα εξαρτώνται από το context κι από το intended audience. Για παράδειγμα, μιας και στο νήμα μιλάμε για C, προσπάθησε να γράψεις το παραπάνω 4-γραμμο C# snippet σε C, χωρίς χρήση custom συναρτήσεων (δηλαδή μόνο με standard συναρτήσεις) και χωρίς διαστήματα ανάμεσα στα logical blocks (όπως δηλαδή δεν έχεις και στο παραπάνω snippet).

 

Νομίζω ότι στο C snippet που θα προκύψει, θα χρειαστείς περισσότερα σχόλια και καλύτερες ονομασίες μεταβλητών αν θέλεις να μεγιστοποιήσεις τις πιθανότητες να το καταλάβουν γρήγορα και αρχάριοι.

 

Π.χ. το newFile φαντάζει καλό candidate και ως file-name και ως file-pointer. Μάλλον λοιπόν είναι καλύτερα να γίνει dropped τελείως και στη θέση του να χρησιμοποιηθούν είτε τα 2 ιδιωματικά fnameNew και fpNew, είτε κάτι πιο wordy π.χ. του στυλ newFilename & newFilePtr... bliax :P

Δημοσ.

Πάνω στο σχολιασμό (από Linus Torvalds, Linux kernel coding style):

 

Chapter 8: Commenting


Comments are good, but there is also a danger of over-commenting. NEVER
try to explain HOW your code works in a comment: it's much better to
write the code so that the _working_ is obvious, and it's a waste of
time to explain badly written code.

 

Είναι πολύ χρήσιμο να το διαβάσει κανείς όλο, ανεξάρτητα απ' το αν είναι linux contributor ή όχι.

  • Like 1
Δημοσ.

Θα το πω εν συντομία για να μη πάει αλλού το πράγμα, αλλά:

 

Ο σκοπός είναι στο τέλος ο κώδικας να είναι ευκολοδιάβαστος και κατανοητός. Τα σχόλια είναι ένα από τα μέσα για να επιτευχθεί αυτός ο σκοπός.

 

Επομένως:

  • Θρησκευτική προσήλωση ή υπερβολή στα comments μπορεί να καταλήξει να είναι χειρότερη από καθόλου comments.
  • Όπως και σε διάφορα άλλα πράγματα, αρκετές φορές το λιγότερο είναι καλύτερο.
  • Κώδικας που είναι μαύρο χάλι δε σώζεται με comments.
  • Υπάρχουν κι άλλες τεχνικές οι οποίες εφαρμόζονται παράλληλα ή αντί για comments και οι οποίες μπορεί να έχουν καλύτερο αποτέλεσμα, ανάλογα την περίπτωση, π.χ. ονοματολογία και σπάσιμο των functions.

Ειδικά το τελευταίο ξέρω κόσμο που μπορεί να αρχίσει να σου λέει το μακρύ του και το κοντό του για comments χωρίς να έχει καταλάβει την ουσία (τα comments δεν είναι ούτε πανάκεια ούτε αυτοσκοπός).

  • Like 1
Δημοσ.

Φαντάζομαι θα έχει συζητηθεί κι άλλες φορές το κομμάτι του σχολιασμού του κώδικα. Προσωπικά να παραθέσω το τι μας είχε πει ο καθηγητής όταν είχα ξεκινήσει C στη σχολή. Η αναλλογία κώδικα-σχολίων πρέπει να είναι περίπου στο (40%-60%) και μάλιστα όταν κάνεις extract τα σχόλια από το source code να μπορεί κάποιος να καταλάβει τι κάνει το πρόγραμμα σου διαβάζοντας μόνο τα σχόλια (χωρίς υπερβολές). Να βγαίνει κάτι σαν διάγραμμα ροής για παράδειγμα.

 

π.χ.

/* Διάβασμα παραμέτρων */
printf("Δώσε ....")
scanf("...");    //τη scanf τη βάζω για παράδειγμα μην αρχίσουμε για τα fgets κτλ 
printf("Δώσε ....")
scanf("...");
printf("Δώσε ....")
scanf("...");

/* Υπολογισμός του τάδε... */
radius = compute_radius(...);
pi = compute_pi(...);
result = 2 * p i * radius;

/* Εκτύπωση αποτελεσμάτων */
printf("Αποτελέσματα \n");
printf("΄Παράμετροι: ....\n")
printf("Περίμετρος: %f\n",result);

κι όχι

/* Διάβασμα παραμέτρων */
printf("Δώσε ....")
scanf("...");                          //Διαβάζει το τάδε
printf("Δώσε ....")
scanf("...");                          //Διαβάζει το άλλο τάδε
printf("Δώσε ....")
scanf("...");                          //Διαβάζιε το δείνα τάδε

/* Υπολογισμός του τάδε... */
radius = compute_radius(...);          // Υπολογίζει την ακτίνα
pi = compute_pi(...);                  // Υπολογίζει το π
result = 2 * p i * radius;             // Υπολογίζει την περίμετρο

/* Εκτύπωση αποτελεσμάτων */
printf("Αποτελέσματα \n");           // Εκτυπώνει τον τίτλο
printf("΄Παράμετροι: ....\n")        // Εκτυπώνει τις παραμέτρους
printf("Περίμετρος: %f\n",result);   // Εκτυπώνει το αποτέλεσμα

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

 

Απο εκεί και πέρα, όταν ασχολείσαι επαγγελματικά και κάνεις ένα μεγάλο project και όταν συνεργάζεσαι με άλλα άτομα κάποια πράγματα αλλάζουν.

Δημοσ.

Όπως είπα και παραπάνω, εξαρτάται από το context και το intended audience. Τα σχόλια εμπίπτουν κι αυτά στο coding-style που υιοθετεί το κάθε project.

 

Υπάρχουν όμως οδηγίες που συναντώνται στα περισσότερα coding-styles, και η συγγραφή σχολίων στην αρχή των συναρτήσεων είναι μια από αυτές. Σίγουρα ότι προορίζεται για public view σχολιάζεται με αυτόν τον τρόπο... είτε στο .h interface (κοινός τόπος στα libraries, APIs, κλπ) είτε απευθείας μέσα στο .c (είτε σε όλες τις συναρτήσεις είτε μόνο στις public... δλδ τις non-static... είτε και στις static, συνήθως όμως αυτές δεν σχολιάζονται όλες).

 

Όποιο σοβαρό κώδικα και να δείτε δεν υπάρχει περίπτωση να μη δείτε σχολιασμένη public συνάρτηση πάνω από τον κώδικά της (ή το πρότυπό της). Είτε πρόκειται για 2 γραμμές είτε για 10, είτε για 20. Το ζητούμενο δεν είναι το πλήθος των γραμμών σε αυτή την περίπτωση, αλλά η επεξήγηση του κώδικα.

 

H κάθε επεξήγηση εμπίπτει κι αυτή στο επιλεγμένο coding-style. Μπορεί να ακολουθεί συγκεκριμένη μορφή (με ή χωρίς χρήση documentation tool), μπορεί όχι. Και πάλι δεν είναι αυτό το πρωτεύον ζητούμενο. Το πρωτεύον ζητούμενο είναι να υπάρχει σχολιασμός της public συνάρτησης πάνω από τον κώδικά της (ή το πρότυπό της).

 

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

 

Παραθέτω και ενδεικτικά παραδείγματα από γνωστά σοβαρά projects γραμμένα σε C, για πληρέστερη εικόνα...

 

1. GLib (g_array):

http://bazaar.launchpad.net/~registry/glib/glib-2-30/view/head:/glib/garray.c

Οι public συναρτήσεις έχουν όλες doxygen-style σχολιασμό πάνω από τον κώδικά τους. Οι static έχουν ανάμικτο σχολιασμό (είτε καθόλου, είτε απλό, είτε doxygen-style).

 

2. GCC (c parser):

http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/c/c-parser.c?revision=206463&view=markup

Σχολιασμός όλων των συναρτήσεων ανεξαιρέτως accessibility.

 

3. NetBSD (stdlib | getenv.c):

http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdlib/getenv.c?rev=1.18.26.1&content-type=text/x-cvsweb-markup

Σχολιασμός όλων των συναρτήσεων.

 

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

 

Σε ότι αφορά τώρα τα σχόλια μέσα στον κώδικα, εμπίπτουν κι αυτά μέσα στο coding-style αλλά οι κανόνες είναι πολύ πιο γενικοί και χαλαροί, γιατί δεν είναι καθόλου εύκολο (για πολλούς δεν είναι ούτε πρέπον) να στανταριστεί η δημιουργικότητα.

 

Συγκρίνετε αυτού του είδους τα σχόλια στα 3 παραπάνω παραδείγματα, και θα δείτε ότι ακολουθούνται διαφορετικοί κανόνες ή και καθόλου στανταρισμένοι κανόνες (π.χ. ο gcc είναι γεμάτος από τέτοια σχόλια, η glib από ελάχιστα έως καθόλου, κλπ).

 

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

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...