Κάποτε, σε μια μακρινή γωνιά του διαδικτύου, ένας προγραμματιστής έγραψε μια συνάρτηση 500 γραμμών που ονόμασε handle_data(). Αυτός ο προγραμματιστής ήμουν εγώ, στα πρώτα μου βήματα, και νιώθω ακόμα τις συνέπειες εκείνης της απόφασης.
Από τότε, κύλησε πολύ νερό στο αυλάκι της PHP, και η αναζήτησή μου για τον “Καθαρό Κώδικα” έγινε λιγότερο ακαδημαϊκή και περισσότερο μια πράξη επαγγελματικής επιβίωσης.
Σε αυτό το άρθρο, δεν θα σας παραθέσω απλώς κανόνες. Θα μοιραστώ μαζί σας μια φιλοσοφία—μια φιλοσοφία που διαμορφώθηκε μέσα από αμέτρητα code reviews, αποτυχημένα deployments και εκείνες τις μαγικές στιγμές στις 3 τα ξημερώματα.
Τι είναι ο Καθαρός Κώδικας και γιατί να σας ενδιαφέρει;
Ας ξεκινήσουμε από τα βασικά. “Καθαρός κώδικας” (Clean Code) είναι ένας όρος που εκλαΐκευσε ο Robert C. Martin (“Uncle Bob”), και στην ουσία του, σημαίνει κώδικας που είναι ευανάγνωστος, κατανοητός και, κυρίως, συντηρήσιμος από κάποιον άλλον που θα την επεξεργαστεί, εκτός από τον αρχικό του συγγραφέα.
Και ναι, “κάποιος άλλος” πολύ συχνά περιλαμβάνει ακόμα και τον εαυτό σας έξι μήνες αργότερα, όταν θα έχετε ξεχάσει πλήρως γιατί κάνατε αυτό το έξυπνο “hack”.
Σε μια ομάδα, ο καθαρός κώδικας είναι η κόλλα που κρατά το project ενωμένο. Είναι η διαφορά μεταξύ μιας ομαλής ενσωμάτωσης νέων μελών και ενός εφιάλτη όπου κανείς δεν τολμά να αγγίξει τον “παλιό” κώδικα από φόβο μήπως καταρρεύσει. Η σημασία του δεν μειώνεται ούτε στα προσωπικά projects.
Πόσα side projects έχετε εγκαταλείψει επειδή το αρχικό “γρήγορο” prototype μετατράπηκε σε ένα απροσπέλαστο τέρας από spaghetti code; Ο καθαρός κώδικας είναι πειθαρχία, αλλά πάνω απ’ όλα, είναι σεβασμός—σεβασμός στους συναδέλφους σας και στον μελλοντικό σας εαυτό.
Ποιος αποφασίζει ποιες είναι οι “Καλές Πρακτικές”;
Αυτό είναι ένα ερώτημα που βασανίζει πολλούς. Η αλήθεια είναι πως δεν υπάρχει κάποια μυστική Σύνοδος Σοφών Προγραμματιστών που να εκδίδει διατάγματα.
Οι “βέλτιστες πρακτικές” είναι, στην πραγματικότητα, ένα σύνολο από συλλογικά διδάγματα πόνου. Όταν αρκετοί άνθρωποι “κάηκαν” από τα global variables, γεννήθηκε η ιδέα του Dependency Injection. Όταν τα τεράστια “God Objects” έγιναν ασυντήρητα, γεννήθηκε το Single Responsibility Principle (το ‘S’ του SOLID).
Τα Design Patterns (GoF) και οι αρχές SOLID είναι θεμελιώδεις οδηγοί, αλλά δεν είναι αλάνθαστοι νόμοι. Το context (το πλαίσιο) είναι ο βασιλιάς. Μια πρακτική είναι “καλύτερη” μόνο αν λύνει το συγκεκριμένο πρόβλημα με τρόπο που να είναι ταυτόχρονα αποδοτικός και συντηρήσιμος σε αυτό το project.
Η συνέπεια (consistency) συχνά υπερτερεί της θεωρητικής “τελειότητας”. Προτιμώ μια βάση κώδικα που χρησιμοποιεί με συνέπεια ένα “αμφιλεγόμενο” pattern, παρά μια που είναι ένα χάος από δέκα διαφορετικές “τέλειες” αρχιτεκτονικές.
Τα εργαλεία στατικής ανάλυσης και τα tests είναι οι πραγματικοί, αντικειμενικοί κριτές που επιβάλλουν ό,τι εμείς αποφασίσουμε ως “καλή πρακτική”.
Γράψτε κώδικα, μην κάνετε επίδειξη
Έχω δει κώδικα που έμοιαζε περισσότερο με διαγωνισμό “ποιος ξέρει τα πιο σκοτεινά σημεία της PHP” παρά με λύση σε ένα επιχειρησιακό πρόβλημα.
Ο κώδικας γράφεται μία φορά, αλλά διαβάζεται δεκάδες. Ο σκοπός του δεν είναι να αποδείξει πόσο έξυπνοι είμαστε, αλλά να επικοινωνήσει την πρόθεσή μας ξεκάθαρα, τόσο στον υπολογιστή όσο και στους ανθρώπους. Η συντηρησιμότητα (maintainability) είναι το άλφα και το ωμέγα.
Αποφύγετε τις “ακροβασίες”. Μια φωλιασμένη τριαδική σύγκριση (nested ternary) μπορεί να γλιτώνει τρεις γραμμές, αλλά κοστίζει πέντε λεπτά εγκεφαλικής προσπάθειας σε όποιον τη διαβάσει.
Το ίδιο ισχύει για τους “έξυπνους” τελεστές bitwise (binary operators) για δικαιώματα, όταν ένα απλό, ευανάγνωστο Enum ή ένα set από constants θα έκανε την ίδια δουλειά με μηδενικό πνευματικό κόστος.
Οι συντομογραφίες σε ονόματα μεταβλητών ($avgUsrLgn αντί για $averageUserLogin) είναι ένα κατάλοιπο από εποχές που οι editor δεν είχαν autocomplete.
Και ας μιλήσουμε για τα σχόλια. Τα σχόλια πρέπει να εξηγούν το “γιατί”, όχι το “τι”. Αν ο κώδικάς σας είναι τόσο πολύπλοκος που χρειάζεται σχόλια για να εξηγήσει τι κάνει, τότε το πρόβλημα δεν είναι η έλλειψη σχολίων—είναι ο ίδιος ο κώδικας. Αντί να σχολιάσετε, κάντε refactor.
Επίσης, η μικρο-βελτιστοποίηση (micro-optimization) είναι σχεδόν πάντα μια κακή ιδέα. Μην ξαναγράφετε μεθόδους της Standard PHP Library (SPL) επειδή “νομίζετε” ότι μπορείτε να το κάνετε ταχύτερα. Δεν μπορείτε, και ακόμα κι αν μπορούσατε, το κέρδος είναι αμελητέο σε σύγκριση με το κόστος συντήρησης.
Η PHP είναι κάτι περισσότερο από τον κώδικα
Η PHP δεν είναι απλώς μια γλώσσα· είναι ένα ολόκληρο οικοσύστημα. Το να γράφεις καθαρό κώδικα σημαίνει επίσης να πλοηγείσαι έξυπνα σε αυτό το οικοσύστημα. Η επιλογή των βιβλιοθηκών (libraries) είναι κρίσιμη. Ένα project είναι τόσο ισχυρό όσο ο πιο αδύναμος κρίκος του στο composer.json.
Και εδώ έρχεται το Semantic Versioning (SemVer). Δεν μπορώ να τονίσω αρκετά τη σημασία του. Το MAJOR.MINOR.PATCH (π.χ., 2.5.1) δεν είναι απλοί αριθμοί· είναι μια υπόσχεση. Μια αλλαγή στο PATCH σημαίνει bug fix. Μια αλλαγή στο MINOR σημαίνει νέα λειτουργικότητα, αλλά με οπίσθια συμβατότητα (backward compatibility).
Μια αλλαγή στο MAJOR σημαίνει “Προσοχή! Έσπασαν πράγματα!”. Η σωστή διαχείριση του SemVer στο composer.json (χρησιμοποιώντας το ^ έναντι του ~ ή του “καρφώματος” μιας έκδοσης) είναι θεμελιώδης για την υγεία του project.
Πρέπει πάντα να εξισορροπούμε τη σταθερότητα (π.χ., επιλέγοντας πακέτα με μακρά υποστήριξη – LTS) με τις τάσεις (το νέο, λαμπερό “async” framework που όλοι συζητούν αλλά κανείς δεν έχει χρησιμοποιήσει σε production).
Βελτιστοποιώντας τον χρόνο σας και διαχωρίζοντας τις ευθύνες
Η οργάνωση είναι η σιωπηλή αρετή του καθαρού κώδικα. Οι συμβάσεις ονομασίας (naming conventions) και η δομή των φακέλων είναι το πρώτο πράγμα που βλέπει ένας νέος προγραμματιστής.
Εδώ, τα πρότυπα PSR (PHP Standards Recommendations), ειδικά το PSR-12, δεν είναι απλές προτάσεις· είναι ο κανόνας. Τα ονόματα των κλάσεων πρέπει να είναι ουσιαστικά (Nouns) σε UpperCamelCase. Τα ονόματα των μεθόδων πρέπει να είναι ρήματα (Verbs) σε lowerCamelCase.
Η πιο σημαντική αρχή, ωστόσο, είναι ο Διαχωρισμός των Ευθυνών (Separation of Concerns). Αυτή είναι η καρδιά του “S” στο SOLID (Single Responsibility Principle). Μια κλάση πρέπει να κάνει ένα πράγμα και να το κάνει καλά.
Ένα κλασικό παράδειγμα κακής πρακτικής είναι ένας UserController που χειρίζεται το HTTP request, κάνει validate τα δεδομένα, μιλάει απευθείας στη βάση δεδομένων, επεξεργάζεται τα δεδομένα ΚΑΙ επιστρέφει ένα view. Αυτό είναι ένα τέρας που περιμένει να καταρρεύσει.
Για να το πετύχουμε αυτό, χρησιμοποιούμε εργαλεία όπως το Polymorphism. Τα Interfaces είναι το κλειδί. Ένα interface είναι ένα συμβόλαιο. Δεν λέει πώς να γίνει κάτι, αλλά τι πρέπει να μπορεί να γίνει.
Οι Abstract Classes είναι χρήσιμες όταν θέλουμε να μοιραστούμε κάποια υλοποίηση, αλλά τα interfaces είναι ο ακρογωνιαίος λίθος του ευέλικτου, αποσυζευγμένου (decoupled) κώδικα.
Επιτρέπουν σε διαφορετικά μέρη του συστήματος να επικοινωνούν χωρίς να γνωρίζουν τις εσωτερικές λεπτομέρειες το ένα του άλλου, συχνά μέσω μηχανισμών όπως το Event Dispatching.
Η PHP εξελίσσεται – Απόσυρση παλαιών πρακτικών
Αν η εικόνα σας για την PHP είναι ακόμα γεμάτη από mysql_query() και include('header.php'), τότε έχετε μείνει πίσω. Η σύγχρονη PHP (ειδικά από την 7.x και μετά, και τώρα στην 8.x) είναι μια γρήγορη, ισχυρή και εξαιρετικά εκφραστική γλώσσα. Η μεγαλύτερη επανάσταση;
Το Strict Typing. Η γραμμή declare(strict_types=1); στην αρχή κάθε αρχείου είναι, κατά τη γνώμη μου, η πιο σημαντική δήλωση που μπορείτε να κάνετε για την ποιότητα του κώδικά σας. Σε συνδυασμό με τα return types και τα property types, εξαλείφει ολόκληρες κατηγορίες σφαλμάτων χρόνου εκτέλεσης (runtime errors).
Η επανάσταση της έκδοσης 8 έφερε εργαλεία που αλλάζουν τον τρόπο που γράφουμε κώδικα. Τα Attributes (π.χ., #[Route("/path")]) μας επιτρέπουν να προσθέτουμε μεταδεδομένα στον κώδικά μας με δομημένο τρόπο, αντικαθιστώντας το χάος των DocBlock annotations.
Η σύνταξη match είναι ένας θεόσταλτος, πιο ασφαλής και ευανάγνωστος αντικαταστάτης του παλιού switch.
Τα Named Arguments κάνουν τις κλήσεις συναρτήσεων, ειδικά για αντικείμενα μεταφοράς δεδομένων (DTOs) ή constructors με πολλά προαιρετικά ορίσματα, απείρως πιο ευανάγνωστες. Οι Read-only classes και properties επιτέλους επιβάλλουν το immutability (αμεταβλητότητα) σε επίπεδο γλώσσας.
Εργαλεία ποιότητας κώδικα
Εδώ χωρίζεται η ήρα από το στάρι. Μπορείτε να λέτε ότι γράφετε καθαρό κώδικα, ή μπορείτε να το αποδείξετε αυτοματοποιώντας τον έλεγχο. Ο έλεγχος σύνταξης (linting) με το php -l είναι το απόλυτο ελάχιστο.
Το επόμενο βήμα είναι τα “code sniffers” όπως το PHP-CS-Fixer ή το PHP_CodeSniffer.1 Αυτά τα εργαλεία δεν ελέγχουν τη λογική· ελέγχουν το στυλ. Εξασφαλίζουν ότι όλος ο κώδικας ακολουθεί τα ίδια πρότυπα (π.χ., PSR-12), εξαλείφοντας τις ανούσιες διαφωνίες στα code reviews.
Η πραγματική μαγεία, όμως, βρίσκεται στη Στατική Ανάλυση (Static Code Analysis). Εδώ, εργαλεία όπως το PHPStan και το Psalm είναι οι αδιαμφισβήτητοι βασιλιάδες.
Αυτά τα εργαλεία αναλύουν τον κώδικά σας χωρίς να τον εκτελέσουν και βρίσκουν πιθανά σφάλματα: μεταβλητές που μπορεί να είναι null και δεν το ελέγχετε, κλήσεις μεθόδων σε αντικείμενα που δεν τις έχουν, λάθος τύπους δεδομένων.
Το να δουλεύεις σε ένα project με PHPStan στο επίπεδο 8 ή 9 είναι μια εμπειρία που αλλάζει τον τρόπο σκέψης σου. Άλλα εργαλεία όπως το PHPMD (PHP Mess Detector) ψάχνουν για “μυρωδιές” κώδικα (code smells) όπως υπερβολικά πολύπλοκες μεθόδους, ενώ το phpcpd βρίσκει διπλότυπο κώδικα (copy-paste detector).
Φυσικά, όλα αυτά πρέπει να είναι ενσωματωμένα απευθείας στο IDE σας (με extensions όπως το Intelephense) για άμεσο feedback.
Μέτρηση ποιότητας κώδικα
Ό,τι δεν μετριέται, δεν βελτιώνεται. Ή μήπως όχι; Οι μετρικές ποιότητας κώδικα είναι ένα δίκοπο μαχαίρι. Μας δίνουν μια ποσοτική ματιά στην υγεία του project, αλλά μπορούν εύκολα να γίνουν αυτοσκοπός (vanity metrics).
Υπάρχουν διάφορες πτυχές της ποιότητας λογισμικού που μπορούμε να μετρήσουμε, όπως η συντηρησιμότητα (Maintainability), η πολυπλοκότητα (Complexity) και η σύζευξη (Coupling).
Εργαλεία όπως το phploc μας δίνουν μια γρήγορη επισκόπηση του μεγέθους του project (π.χ., Γραμμές Κώδικα, αριθμός κλάσεων).3 Το PHP Depend (pdepend) πηγαίνει βαθύτερα, υπολογίζοντας κρίσιμες μετρικές όπως η Κυκλωματική Πολυπλοκότητα (Cyclomatic Complexity)—ένας αριθμός που δείχνει πόσο “διακλαδισμένη” και δύσκολη στο test είναι μια μέθοδος.
Το PhpMetrics είναι ένα εξαιρετικό εργαλείο που συγκεντρώνει πολλά από αυτά τα δεδομένα και δημιουργεί όμορφες, οπτικές αναφορές. Μπορεί να υπολογίσει τον Δείκτη Συντηρησιμότητας (Maintainability Index) και να εντοπίσει “hotspots” στον κώδικά σας.
Τα πλεονεκτήματα είναι προφανή: μπορείς γρήγορα να δεις πού πονάει ο κώδικας. Τα μειονεκτήματα; Οι μετρικές μπορούν να “παραποιηθούν”. Ένας προγραμματιστής μπορεί να σπάσει μια πολύπλοκη μέθοδο σε πέντε μικρότερες, απλώς και μόνο για να μειώσει τον αριθμό της Κυκλωματικής Πολυπλοκότητας, χωρίς όμως να βελτιώσει ουσιαστικά την αρχιτεκτονική.
Ακολουθεί ένας πίνακας με ορισμένες κοινές μετρικές και τι πραγματικά (ή υποθετικά) μας λένε:
| Μετρική (Metric) | Εργαλείο | Τι (Υποτίθεται) Μετράει | Η Δική μου Άποψη |
| Cyclomatic Complexity (CC) | pdepend, phpmd | Τον αριθμό των “μονοπατιών” που μπορεί να πάρει ο κώδικας. Πόσα if, while, case έχεις. | Οτιδήποτε πάνω από 10 σημαίνει “Μην αγγίζετε, θα σκάσει”. |
| Lines of Code (LOC) | phploc | Το μέγεθος. | Μια μετρική ματαιοδοξίας. Δεν λέει τίποτα για την ποιότητα. |
| Maintainability Index (MI) | PhpMetrics | Ένας σύνθετος τύπος που συνδυάζει CC, LOC και άλλα. | Ένας χρήσιμος, αν και ασαφής, δείκτης. Αν πέσει κάτω από 60, μάλλον ήρθε η ώρα για refactoring. |
| Coupling Between Objects (CBO) | pdepend | Πόσο “κολλημένες” είναι οι κλάσεις μεταξύ τους. | Υψηλό CBO σημαίνει ότι δεν μπορείς να αλλάξεις τίποτα χωρίς να σπάσουν άλλα δέκα πράγματα. |
Οργανώνοντας τα εργαλεία που βοηθούν στην ποιότητα
Το να έχεις εργαλεία είναι το ένα βήμα. Το να τα χρησιμοποιείς αποτελεσματικά είναι το άλλο. Η σύγχρονη προσέγγιση είναι η εγκατάστασή τους ανά project μέσω του Composer, χρησιμοποιώντας το require-dev.
Αυτό εξασφαλίζει ότι όλα τα μέλη της ομάδας (και ο CI server) χρησιμοποιούν τις ακριβώς ίδιες εκδόσεις των εργαλείων, αποφεύγοντας το “ναι, αλλά σε μένα δουλεύει”.
Μόλις εγκατασταθούν, ο ευκολότερος τρόπος να τα εκτελέσετε είναι μέσω των Composer scripts στο composer.json. Μπορείτε να ορίσετε ένα script με όνομα test που εκτελεί το PHPUnit, ένα analyze που εκτελεί το PHPStan, και ένα lint που εκτελεί το PHP-CS-Fixer.
Για εργαλεία που προτιμάτε να έχετε global, ή για να αποφύγετε συγκρούσεις εξαρτήσεων (dependency conflicts), τα phar files είναι μια λύση. Αλλά η διαχείρισή τους μπορεί να γίνει χαοτική.
Εδώ λάμπει ένα εργαλείο όπως το Phive (PHAR Installation and Verification Environment). Το Phive είναι σαν το Composer, αλλά για PHARs. Σας επιτρέπει να ορίζετε τις εκδόσεις των εργαλείων σας σε ένα αρχείο phive.xml, εξασφαλίζοντας επαναλήψιμες (reproducible) εγκαταστάσεις.
Αυτοματοποιημένος Έλεγχος (Automated Testing)
Αν έπρεπε να διαλέξω ένα πράγμα που ορίζει τον καθαρό κώδικα, θα ήταν αυτό. Ο αυτοματοποιημένος έλεγχος (κυρίως μέσω του PHPUnit) δεν είναι ένα “nice to have”. Είναι η απόλυτη προϋπόθεση για να κάνεις refactoring με ασφάλεια. Χωρίς tests, κάθε αλλαγή είναι ένα ρίσκο. Με τα tests, κάθε αλλαγή είναι μια επαλήθευση.
Η “Πυραμίδα του Ελέγχου” (Testing Pyramid) είναι το μοντέλο μας εδώ. Η βάση της είναι τα Unit Tests: γρήγορα, απομονωμένα, ελέγχουν μία κλάση ή μέθοδο.
Πάνω από αυτά είναι τα Integration Tests: πιο αργά, ελέγχουν πώς συνεργάζονται δύο ή περισσότερα μέρη (π.χ., η κλάση σας και η βάση δεδομένων). Στην κορυφή είναι τα End-to-End (E2E) Tests: πολύ αργά, ελέγχουν ολόκληρη την εφαρμογή μέσα από ένα browser (π.χ., με Cypress ή Selenium).
Η Κάλυψη Κώδικα (Code Coverage), που παράγεται συνήθως με Xdebug ή PCOV, είναι μια άλλη επικίνδυνη μετρική. Δείχνει ποιο ποσοστό του κώδικά σας “εκτελέστηκε” κατά τη διάρκεια των tests. Δεν δείχνει αν αυτός ο κώδικας ελέγχτηκε σωστά.
Έχω δει 100% coverage σε tests που δεν είχαν κανένα assertion. Είναι άχρηστο. Χρησιμοποιήστε την κάλυψη για να βρείτε τι δεν έχετε τεστάρει, όχι για να καυχηθείτε για το ποσοστό. Η χρήση της annotation @covers βοηθά να είστε σαφείς για το τι ακριβώς σκοπεύει να ελέγξει κάθε test.
Συνεχής Ολοκλήρωση (Continuous Integration)
Το Continuous Integration (CI) είναι η αυτοματοποίηση όλων όσων συζητήσαμε. Είναι το σύστημα που εξασφαλίζει ότι κάθε φορά που κάποιος κάνει “push” τον κώδικά του, ένας αυτόματος “φύλακας” αναλαμβάνει δράση. Ο λόγος; Το κόστος ενός bug αυξάνεται εκθετικά όσο πιο αργά το ανακαλύπτουμε. Ένα bug που βρίσκει ο linter στο IDE σας κοστίζει δευτερόλεπτα. Ένα bug που βρίσκει το CI κοστίζει λεπτά. Ένα bug που βρίσκει ο QA tester κοστίζει ώρες. Ένα bug που βρίσκει ο πελάτης… κοστίζει τη φήμη σας.
Ένα τυπικό build pipeline σε ένα CI σύστημα (όπως το GitHub Actions ή το GitLab CI) έχει τα εξής στάδια:
- Build: Κάνει
composer installγια να πάρει τις εξαρτήσεις. - Code Analysis: Εκτελεί τα PHPStan, PHP-CS-Fixer, PHPMD. Αν αποτύχουν, το build “σπάει” αμέσως.
- Tests: Εκτελεί τα PHPUnit (unit και integration tests).
- Deploy: Αν όλα τα προηγούμενα περάσουν, αναπτύσσει αυτόματα τον κώδικα (π.χ., στο staging environment).
Αλλά το CI δεν ξεκινάει στον server. Ξεκινάει τοπικά. Τα Git Hooks (ειδικά το pre-commit hook) είναι η προσωπική σας, τοπική γραμμή άμυνας.
Μπορείτε να τα ρυθμίσετε ώστε πριν από κάθε commit, να εκτελούνται αυτόματα οι linter και ίσως τα πιο γρήγορα unit tests. Αυτό εξασφαλίζει ότι “βρώμικος” κώδικας δεν φεύγει ποτέ καν από τον υπολογιστή σας.
Δουλεύοντας σε ομάδα
Ο καθαρός κώδικας είναι, τελικά, μια κοινωνική σύμβαση. Μπορείτε να έχετε όλα τα εργαλεία του κόσμου, αλλά αν η ομάδα δεν μοιράζεται την ίδια φιλοσοφία, το χάος θα επικρατήσει.
Τα Coding Standards (όπως το PSR-12) πρέπει να είναι αδιαπραγμάτευτα και να επιβάλλονται από τα εργαλεία, όχι από τους ανθρώπους. Οι Coding Guidelines είναι ένα βήμα παραπέρα: είναι οι κανόνες που δεν μπορεί να ελέγξει ένας linter, π.χ., “Προτιμάμε τη σύνθεση έναντι της κληρονομικότητας” (Composition over Inheritance).
Τα Code Reviews είναι η ανθρώπινη πλευρά του CI. Ένα καλό code review δεν ψάχνει για λάθος κενά (αυτό το έκανε ο linter). Επικεντρώνεται στη λογική: “Αυτή η προσέγγιση λύνει το πρόβλημα; Υπάρχει απλούστερος τρόπος; Καλύπτει τις γωνιακές περιπτώσεις (edge cases);”. Τα καλύτερα reviews γίνονται σε μικρά, εστιασμένα Pull Requests.
Τα Design Patterns (Factory, Strategy, Observer, Decorator κ.λπ.) είναι η κοινή μας γλώσσα. Όταν λέω “ας χρησιμοποιήσουμε ένα Strategy pattern εδώ”, ο συνάδελφός μου καταλαβαίνει αμέσως την αρχιτεκτονική πρόταση.
Το ίδιο σημαντικό είναι να αναγνωρίζουμε τα Anti-Patterns—λύσεις που φαίνονται καλές με την πρώτη ματιά αλλά οδηγούν σε προβλήματα (όπως το Singleton που συχνά δεν είναι παρά ένα “ένδοξο” global state, ή το Active Record σε πολύπλοκα domains).
Δημιουργώντας αποτελεσματική τεκμηρίωση
Φτάσαμε στο τέλος. Και όπως κάθε καλός κώδικας, χρειαζόμαστε και καλή τεκμηρίωση. Γιατί;
Επειδή ο κώδικας λέει πώς γίνεται κάτι, αλλά η τεκμηρίωση εξηγεί γιατί. Η καλή τεκμηρίωση δεν είναι τα σχόλια μέσα στον κώδικα. Είναι το README.md που εξηγεί πώς να στήσεις το project. Είναι τα διαγράμματα αρχιτεκτονικής (π.χ., C4 model) που δείχνουν τη μεγάλη εικόνα. Είναι η τεκμηρίωση του API (π.χ., OpenAPI/Swagger) που επιτρέπει σε άλλες ομάδες να δουλέψουν.
Όσο για τα inline comments, η στάση μου είναι ξεκάθαρη: ο καλύτερος κώδικας είναι αυτός που δεν χρειάζεται σχόλια για να εξηγήσει τι κάνει. Αν γράφετε ένα σχόλιο, αναρωτηθείτε: “Μπορώ να αλλάξω το όνομα αυτής της συνάρτησης ή μεταβλητής για να γίνει το σχόλιο περιττό;”. Τα σχόλια που έχουν μείνει πίσω και είναι πλέον λάθος (outdated comments) είναι χειρότερα από καθόλου σχόλια. Τα TODO comments είναι χρήσιμα, αρκεί να έχετε ένα σύστημα για να τα ελέγχετε, αλλιώς μένουν εκεί για πάντα.
Και ίσως η πιο σημαντική μορφή τεκμηρίωσης, που συχνά ξεχνάμε: τα ίδια τα tests. Ένα καλά γραμμένο unit test, με ένα περιγραφικό όνομα όπως it_throws_exception_when_user_is_not_found, είναι η καλύτερη τεκμηρίωση για τη συμπεριφορά του συστήματός σας. Δεν μπορεί ποτέ να είναι “outdated”, γιατί αν ήταν, το build θα “έσπαγε”.
Η πορεία προς τον καθαρό κώδικα δεν είναι ένας προορισμός, αλλά ένα συνεχές ταξίδι. Είναι μια δέσμευση για επαγγελματισμό και ποιότητα που ξεπερνά την ίδια τη γλώσσα προγραμματισμού. Καλή τύχη.
