Απομάκρυνση από τη μαγεία - ή: γιατί δεν θέλω πλέον να χρησιμοποιώ το Laravel

Ήρθε η ώρα για μια αλλαγή στα εργαλεία που χρησιμοποιώ. Και θα σας πω γιατί!

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

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

Εισαγωγή

Έχω συνεργαστεί με τον Laravel για περίπου 2 χρόνια τώρα. Πάντα μου άρεσε πόσο εύκολο ήταν να κάνω μια εφαρμογή και να ξεκινήσω μέσα σε λίγα λεπτά. Παρέχει τόσα πολλά χρήσιμα εργαλεία έξω από το κουτί. Οι εντολές της κονσόλας σας υποστηρίζουν σε κάθε πτυχή κατά την κωδικοποίηση. Δημιουργούν μαθήματα, ικριώματα για έλεγχο ταυτότητας και πολλά άλλα.

Όσο βαθύτερα πηγαίνετε και όσο μεγαλύτερα γίνονται τα έργα, τόσο πιο περίπλοκη θα είναι η ανάπτυξη με τον Laravel. Ή, επιτρέψτε μου να το επαναδιατυπώσω: όσο καλύτερα άλλα εργαλεία θα κάνουν τη δουλειά. Δεν λέω καν ότι φταίει μόνο ο Laravel. Αυτό οφείλεται επίσης εν μέρει στο ότι η PHP δεν είναι πολύ καλά σχεδιασμένη.

Τώρα, ας ξεκινήσουμε!

Έγγραφο ORM

Εάν έχετε ήδη συνεργαστεί με τον Laravel, σίγουρα γνωρίζετε για το Eloquent. Είναι το ORM που αποστέλλεται με μια προεπιλεγμένη εγκατάσταση. Έρχεται με πολλά τακτοποιημένα χαρακτηριστικά. Ωστόσο, ο σχεδιασμός του καθιστά την εφαρμογή σας περίπλοκη και εμποδίζει το IDE να αναλύσει σωστά τον κώδικά σας.

Αυτό οφείλεται εν μέρει στο μοτίβο Active Record ORM που χρησιμοποιείται και εν μέρει στο γεγονός ότι η Eloquent θέλει να σώσει τον προγραμματιστή από το να χρειαστεί να γράψει περισσότερο κώδικα. Για να το κάνει αυτό, επιτρέπει στον προγραμματιστή να προσθέσει πολλά πράγματα στο μοντέλο που δεν ανήκει εκεί.

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

Ας ρίξουμε μια ματιά σε ένα παράδειγμα:

Το πρώτο πράγμα που βλέπετε είναι ότι δεν υπάρχουν ιδιότητες στο μοντέλο. Αυτό φαίνεται άσχετο, αλλά για μένα κάνει πολύ τη διαφορά. Όλα εισάγονται «μαγικά» στην τάξη διαβάζοντας τα μεταδεδομένα του πίνακα. Φυσικά, το IDE σας δεν το καταλαβαίνει χωρίς βοήθεια. Και δεν έχετε καμία ευκαιρία να ονομάσετε τις ιδιότητές σας διαφορετικά από τις στήλες σας.

Τώρα ελέγξτε τη μέθοδο εμβέλειας. Για τους χρήστες του Laravel, είναι αρκετά σαφές τι κάνει. Εάν καλέσετε αυτήν τη μέθοδο, καλύπτει το υποκείμενο ερώτημα SQL προσθέτοντας τον δεδομένο όρο WHERE.

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

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

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

Επιπλέον, όταν τοποθετείτε τέτοιες μεθόδους στο μοντέλο σας, παραβιάζετε το S of SOLID. Σε περίπτωση που δεν είστε εξοικειωμένοι με αυτό, το SOLID είναι ένα αρκτικόλεξο που σημαίνει:

  • S Ingle Ευθύνη Αρχή
  • O στυλό / Κλειστή αρχή
  • Αρχή υποκατάστασης L iskov
  • Θα nterface Διαχωρισμός Αρχή
  • Δ ependency Αντιστροφή Αρχή

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

Παγκόσμιοι βοηθοί

Το Laravel διαθέτει πολλές παγκόσμιες λειτουργίες βοηθού. Φαίνονται πολύ βολικό και ναι, είναι βολικό.

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

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

  • app_path()- Γιατί? Εάν χρειάζεστε τη διαδρομή της εφαρμογής, ρωτήστε το αντικείμενο της εφαρμογής. Το παίρνετε με υποδείξεις τύπου.
  • app()- ε; Δεν χρειαζόμαστε αυτήν τη μέθοδο. Μπορούμε να εισαγάγουμε την παρουσία της εφαρμογής!
  • collect()- Αυτό δημιουργεί μια νέα παρουσία της κλάσης Συλλογή. Μπορούμε απλά να ανανεώσουμε ένα αντικείμενο από εμάς.

Ένα ακόμη συγκεκριμένο παράδειγμα:

Χρησιμοποιούμε τον παγκόσμιο request()βοηθό του Laravel για να ανακτήσουμε τα δεδομένα POST και να τα βάλουμε στο μοντέλο μας ως χαρακτηριστικά.

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

Και μπορούμε να το κάνουμε ένα βήμα παραπέρα για να αποσυνδέσουμε ακόμη περισσότερο. Το Laravel είναι συμβατό με το PSR-7. Έτσι, αντί να υποδείξετε τον τύπο του αιτήματος αντικειμένου, θα μπορούσατε επίσης να πληκτρολογήσετε υπόδειξη ServerRequestInterface. Αυτό σας επιτρέπει να αντικαταστήσετε ολόκληρο το πλαίσιο με οτιδήποτε συμβατό με το PSR-7. Όλα σε αυτήν τη μέθοδο θα συνεχίσουν να λειτουργούν. Αυτό θα αποτύχει εάν εξακολουθείτε να χρησιμοποιείτε τις μεθόδους βοηθού. Το νέο πλαίσιο δεν θα έρθει με τη μέθοδο βοηθού και επομένως, θα πρέπει να ξαναγράψετε αυτό το μέρος του κώδικα σας.

Σπάνια αλλάζετε ολόκληρο το πλαίσιο, αλλά υπάρχουν άνθρωποι που κάνουν. Και ακόμη και αν δεν μπορείτε ποτέ να αλλάξετε, εξακολουθεί να είναι σημαντικό για τη διαλειτουργικότητα. Το να μπορείτε να κάνετε ένεση εξαρτήσεων και να έχετε μια συνοπτική ροή δεδομένων αντί να επιλύετε και να ζητάτε εξαρτήσεις και δεδομένα από μέσα είναι ο τρόπος να πάτε. Διευκολύνει τη δοκιμή, την επανακατασκευή και σχεδόν τα πάντα όταν το καταλαβαίνετε.

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

Προσόψεις

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

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

Επειδή μιλούσαμε για υποστήριξη IDE, ξέρω ότι ορισμένοι από εσάς μπορεί να με κατευθύνουν στο πακέτο βοηθού IDE από το barryvdh. Δεν χρειάζεται. Γνωρίζω ήδη αυτό το πακέτο. Αλλά γιατί χρειάζεται ακόμη; Επειδή ορισμένες αποφάσεις σχεδιασμού στο Laravel δεν είναι καθόλου καλές. Υπάρχουν πλαίσια όπου δεν το χρειάζεστε. Πάρτε για παράδειγμα το Symfony. Δεν υπάρχει ανάγκη για βοηθητικά αρχεία IDE, επειδή είναι καλά σχεδιασμένο και εφαρμοσμένο.

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

Θα σας δώσω και πάλι ένα παράδειγμα:

Θα μπορούσαμε εύκολα να το καθαρίσουμε. Ας πούμε στον Laravel να κάνει ένεση ResponseFactoryκαι να μας περάσει το τρέχον αίτημα:

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

Άκουσα ότι μερικοί άνθρωποι παρέχουν «πάρα πολλές παραμέτρους κατασκευαστή» ως επιχείρημα κατά της έγχυσης όλων. Αλλά δεν συμφωνώ με αυτό. Κρύβει μόνο τις εξαρτήσεις και συνεπώς την πολυπλοκότητα. Εάν δεν θέλετε να έχετε 10 έως 20 επιχειρήματα στον κατασκευαστή σας, έχετε δίκιο.

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

Διασκεδαστικό γεγονός: υπάρχει ένα πραγματικό σχέδιο σχεδίασης που ονομάζεται "μοτίβο πρόσοψης", που εισήχθη στο βιβλίο του Gang of Four Αλλά έχει μια εντελώς διαφορετική έννοια. Οι προσόψεις του Laravel είναι ουσιαστικά στατικοί εντοπιστές υπηρεσιών . Η ονομασία δεν το μεταφέρει. Η ίδια ονομασία για διαφορετικά πράγματα δυσχεραίνει επίσης τις συζητήσεις σχετικά με την αρχιτεκτονική σε έργα, επειδή το άλλο μέρος μπορεί να περιμένει κάτι εντελώς διαφορετικό πίσω από αυτό το όνομα.

συμπέρασμα

Ας τελειώσουμε. Θα μπορούσα να γράψω μια συνέχεια σύντομα για τις τεχνολογίες που προτιμώ να χρησιμοποιώ σήμερα. Αλλά προς το παρόν, επιτρέψτε μου να συνοψίσω όσα έχουμε μάθει:

Η προσέγγιση του Laravel να κάνει τα πάντα όσο πιο εύκολα γίνεται είναι καλή. Αλλά είναι δύσκολο να ταιριάξετε όταν οι εφαρμογές σας γίνονται πιο προηγμένες. Προτιμώ καταπληκτική υποστήριξη IDE, ισχυρότερη πληκτρολόγηση, πραγματικά αντικείμενα και καλή μηχανική. Ίσως ακόμη και να επιστρέψω στο Laravel όταν θέλω να γράψω μια μικρότερη εφαρμογή.

Πολλά από τα σημεία μου δεν είναι μόνο λάθος του Laravel. Θα μπορούσα να ανταλλάξω τα μέρη που δεν μου αρέσουν, για παράδειγμα το ORM. Αλλά αντ 'αυτού, θα αλλάξω απλώς την εργαλειοθήκη, όπου οι προεπιλογές ταιριάζουν καλύτερα στις ανάγκες μου. Δεν βλέπω κανένα νόημα να χρησιμοποιήσω ένα πλαίσιο όπου πρέπει να αφιερώσω περισσότερο χρόνο για να αποφύγω τις παγίδες που θέτει για κακή μηχανική παρά για την ανάπτυξη της εφαρμογής μου. Άλλα πλαίσια και εργαλεία έρχονται με καλύτερα σχεδιασμένες προεπιλογές και λιγότερη μαγεία.

Έτσι, προς το παρόν, θα αποχαιρετήσω τον Laravel.

Σας ευχαριστώ για το χρόνο σας. Θα εκτιμούσα μια ωραία συζήτηση στα σχόλια και είμαι φυσικά ανοιχτός για τις ερωτήσεις και τις προτάσεις σας.

PS: Ιδιαίτερες ευχαριστίες στον Marco Pivetta για την απόδειξη ανάγνωσης και την πρόσθετη εισαγωγή

Επεξεργασία 1η Μαρτίου 2019:

Δεδομένου ότι το άρθρο μου δημοσιεύτηκε στο Reddit, έχω δημιουργήσει έναν λογαριασμό Reddit για να απαντήσω σε μερικά σχόλια. Ο λογαριασμός μου δεν είναι αυτός από τον οποίο δημοσιεύτηκε το άρθρο, αλλά αυτός: //reddit.com/u/nschoellhorn

Επεξεργασία 13 Μαρτίου 2019:

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