
Στο σημερινό μου άρθρο θα αναφερθώ στο κεφάλαιο “clean code”. Θα περιγράψω τι σημαίνει γράφω “καθαρό κώδικα”, γιατί είναι χρήσιμο να γράφουμε καθαρό κώδικα ως προγραμματιστές, ποια τα οφέλη για τις επιχειρήσεις και τέλος θα αναφέρω χαρακτηριστικά παραδείγματα σε γλώσσα PHP, Laravel8.
Πρώτα θα ξεκινήσουμε με μια παραδοχή: Κάθε προγραμματιστής, εμού συμπεριλαμβανομένου, έχει γράψει μη καθαρό κώδικα και αυτό εξαιτίας διαφορετικών παραγόντων όπως απειρία, πίεση χρόνου, κακό code base, έλλειψη ανάλυσης (τι φτιάχνουμε), ενδιαφέροντος κ.α.
Ως clean code μπορούμε να πούμε πώς ορίζουμε ένα σύνολο άτυπων κανόνων που στόχο έχουν να βελτιώσουν τον τρόπο γραφής, δίνοντας έμφαση στους άξονες : Λιγότερες γραμμές - Γρηγορότερη κατανόηση - Ταχυτερη εκτελεση.
Τα παραπάνω προσφέρουν σειρά πλεονεκτημάτων
- Ταχύτερη εκτέλεση κώδικα: Γιατί να βάζουμε την CPU να πραγματοποιεί άσκοπους κύκλους, το οποίο σε large scale projects μεταφράζεται σε (σημαντικά) κόστη ή σε κατανάλωση ενέργειας (μπαταρίας) της συσκευής του χρήστη;
- Ταχύτερη υλοποίηση features: Ένας καθαρός κώδικας έχει επίπτωση στην γρηγορότερη ανάγνωση/κατανόηση το οποίο με την σειρά του επηρεάζει την παραγωγικότητα της ομάδας. Ιδιαίτερα αν μια μέθοδος πρέπει να τροποποιηθεί από άτομο που δεν την έχει ξαναδεί.
- Λιγότερα bugs - πιο εύκολα ανιχνεύσιμα: Εφαρμόζοντας τις πρακτικές του clean code, “σπάμε” τις μεθόδους μας σε μικρά κομμάτια, τα οποία διαβάζονται πιο εύκολα, επαναχρησιμοποιούνται σε άλλα σημεία και φυσικά διορθώνονται πιο εύκολα.
Τα τρία σημεία που αναλύσαμε μόλις, είναι κατανοητό πώς επηρεάζουν άμεσα τους οικονομικούς δείκτες και την ανταγωνιστικότητας μιας επιχείρησης αλλά δεν θα εμβαθύνουμε περισσότερο.
Πώς όμως μπορούμε να καταλάβουμε αν ένας κώδικας δεν πληροί τις παραπάνω προδιαγραφές. Υπάρχουν 6 χαρακτηριστικά πράγματα που μπορούν γρήγορα να μας προϊδεάσουν:
- Κακή ονοματολογία μεταβλητών και μεθόδων
- Μη ύπαρξη code formatting
- Project structure που δεν τηρεί κάποιο γνωστό pattern
- Μη σταθερός τρόπος γραφής
- Μέθοδοι που κάνουν κάτι παραπάνω από αυτό που περιγράφουν
- Nested if else συνήθως υποδηλώνουν κώδικα spaghetti
Αρκετά όμως με την σύντομη θεωρία. Πάμε σε πρακτικά, καθημερινά παραδείγματα τα οποία είναι σε γλώσσα PHP/Laravel αλλά ισχύουν σε οποιαδήποτε άλλη γλώσσα. Ξεκινάμε από τα πιο απλά και σταδιακά κλιμακώνουμε.
Παράδειγμα #1 - Μη ύπαρξη code formatting
A(Λάθος) - 19 γραμμές
B(Σωστό) - 13 γραμμές
Παράδειγμα #2 - Άστοχες ή μη περιγραφικές ονομασίες
Α(Λάθος): Ονομασίες σε greeklish, περιττά κενά - διαστήματα
B(Σωστό)
Παράδειγμα #3 - Περιττές γραμμές & hardcoded τιμές
Α(Λάθος) - 13 γραμμές: Περιττές γραμμές. Στην Golang η οποία δίνει έμφαση στον καθαρό κώδικα, το παρακάτω παράδειγμα ΔΕΝ θα έκανε compile.
Β(Σωστό) - 7 γραμμές: Στην Golang το παρακάτω παράδειγμα θα έκανε compile.
Παράδειγμα #3.a - Περιττές γραμμές - παράδειγμα #2
Παράδειγμα από το επίσημο documentation της PHP8
Α(Λάθος) - 16 γραμμές:
Β(Σωστό) - 7 γραμμές:
Παράδειγμα #4 - Ξεχασμένες μεταβλητές με κακές ονομασίες
Α(Λάθος) - 11 γραμμές:
Β(Σωστό) - 6 γραμμές:
Παράδειγμα #5 - Validation που γεννά πονοκεφάλους και γραμμές
Α(Λάθος) - 29 γραμμές:
Β(Σωστό) - 10 γραμμές:
// CreateUserRequest class
Παράδειγμα #6 - Ανούσιες Nested if else που αυξάνουν την πολυπλοκότητα και τις γραμμές
Α(Λάθος) - 21 γραμμές:
B(Σωστό) - 6 γραμμές:
Παράδειγμα #7 - Μέθοδος που κάνει κάτι extra από αυτό που περιγράφει το όνομα της
Α(Λάθος): Η συγκεκριμένη μέθοδος κάνει περισσότερα από ένα πράγματα και αποτελεί χαρακτηριστική περίπτωση κώδικα spaghetti. Κάνει handle το request, δημιουργεί χρήστη και στέλνει email χωρίς να σπάει τον κώδικα σε επίπεδα, με ξεχωριστές μεθόδους που μπορούν να επαναχρησιμοποιηθούν.
B(Σωστό)
Αρχικά είναι κοινό practice τα routes να πρέπει να δηλώνονται και να προωθούν το αίτημα σε επόμενο layer π.χ σε controller.
Στην συνέχεια μέσα από τον Usercontroller “σηκώνουμε” τα απαραίτητα services/classes και τα (επανα)χρησιμοποιούμε κατάλληλα. Εδώ για λόγους απλότητας χρησιμοποιούμε την sendEmail απο το emailService και μέσα στέλνουμε στην παράμετρο απευθείας ένα dummy email που επιστρέφει η συγκεκριμένη μέθοδος.
Σε πραγματικό παράδειγμα θα πρέπει να επιστρέφει το created object/model, να υπάρχει έλεγχος κ.α. Με αυτήν την υλοποίηση όμως, η οποία μπορεί να φαίνεται πιο σύνθετη, μπορούμε να στέλνουμε emails και από άλλα σημεία της εφαρμογής καλώντας αυτήν την μέθοδου, μπορούμε να δημιουργούμε χρήστες χωρίς να στέλνουμε emails αν αυτό πρέπει και γενικότερα κάθε μέθοδος κάνει αυτό που περιγράφει το όνομα της, με εξαίρεση φυσικά το “domain layer” το οποίο αναγκαστικά θα πρέπει να καλέσει ξεχωριστές (έτοιμες) μεθόδους για να επιτύχει το flow που θέλει.
Ελπίζω να βρήκατε ενδιαφέρον το άρθρο μου.
Προσίλης Αργύρης
Software engineer PHP/GoLang