5 παραδείγματα της καλύτερης χρήσης της Ruby
Αναρωτηθήκατε ποτέ τι μπορούμε να κάνουμε με τη Ruby; Λοιπόν, ο ουρανός είναι μάλλον το όριο, αλλά είμαστε στην ευχάριστη θέση να μιλήσουμε για μερικές περισσότερο ή λιγότερο γνωστές περιπτώσεις...

Πριν ξεκινήσουμε τη δημιουργία μιας μεθόδου bang, ας μάθουμε τι ακριβώς είναι αυτός ο τύπος μεθόδου και ποια είναι τα χαρακτηριστικά του. Ας ξεκινήσουμε με το γεγονός ότι δεν υπάρχει σαφής ορισμός για αυτούς τους τύπους μεθόδων. Με απλά λόγια, μια μέθοδος bang είναι μια μέθοδος με ένα θαυμαστικό στο τέλος.
Συχνά μπορεί να συναντήσουμε μια δήλωση ότι η μέθοδος bang είναι, κατά μία έννοια, μια επικίνδυνη μέθοδος και το θαυμαστικό στο τέλος του ορισμού της μας λέει να είμαστε προσεκτικοί όταν χρησιμοποιούμε αυτή τη μέθοδο. Ας δούμε: τι ακριβώς είναι αυτή η απειλή όταν πρόκειται για αυτές τις μεθόδους και ποια είναι τα χαρακτηριστικά τους;
Ένα από τα πιο δημοφιλή χαρακτηριστικά αυτών των τύπων μεθόδων είναι ότι συνήθως αλλάζουν το κοινό τους. Ας ρίξουμε μια ματιά στη μέθοδο map! ως παράδειγμα. Σύμφωνα με την τεκμηρίωση, η μέθοδος map! καλεί το δοσμένο μπλοκ μία φορά για κάθε στοιχείο της self, αντικαθιστώντας το στοιχείο με την τιμή που επιστρέφει το μπλοκ και αν δεν δοθεί μπλοκ, επιστρέφεται αντί αυτού ένας απαριθμητής.
arry = [1, 2, 3, 4, 5]
arry.object_id => 280
arry.map! {|num| num**num } => [1, 4, 27, 256, 3125]
arry.map! => #
arry.map! {|n| n } => [1, 4, 27, 256, 3125]
arry.object_id => 280
Όπως βλέπουμε, το object_id παραμένει αμετάβλητο. Έτσι, ο κίνδυνος από τη χρήση μιας τέτοιας μεθόδου φαίνεται προφανής. Αν στο δικό μας κωδικός χρησιμοποιήσαμε τη μεταβλητή arry οπουδήποτε αλλού, τότε ο χάρτης! θα την αλλάξει. Αυτό μπορεί να οδηγήσει το πρόγραμμά μας να λειτουργεί με ανεπιθύμητο τρόπο ή ακόμα και να καταρρεύσει.
Υπάρχουν αντικείμενα στο Ruby που δεν μπορούν να αλλάξουν, όπως οι περιπτώσεις των κλάσεων Integer, Float και Symbol. Ενώ εργάζεστε σε μια έργο, θα μπορούσατε επίσης να συναντήσετε το λεγόμενο μαγικό σχόλιο που έχει ως εξής:
frozenstringliteral: true
Η προσπάθεια αλλαγής του παραλήπτη της συμβολοσειράς στον κώδικα όπου χρησιμοποιήθηκε ένα τέτοιο σχόλιο θα οδηγούσε σε ένα σφάλμα όπως αυτό:
'abc'.upcase!
FrozenError (δεν μπορεί να τροποποιηθεί το παγωμένο String)
Είναι ενδιαφέρον ότι υπήρχαν σχέδια για την εισαγωγή αμετάβλητης συμβολοσειράς στο Ruby 3.0, αλλά αποφασίστηκε να μην γίνει αυτή η αλλαγή. Ωστόσο, θα πρέπει να θυμόμαστε ότι δεν αλλάζουν όλες οι μέθοδοι bang τον παραλήπτη, οπότε θα πρέπει πάντα να ελέγχετε στην τεκμηρίωση τι είδους κίνδυνο θα πρέπει να περιμένετε στην περίπτωση μιας συγκεκριμένης μεθόδου.
Ένα άλλο ιδιαίτερο χαρακτηριστικό αυτών των μεθόδων είναι ότι, για πολλές από αυτές, δημιουργείται μια εξαίρεση. Ένα παράδειγμα μιας τέτοιας μεθόδου είναι η μέθοδος ActiveRecord::FinderMethods#first! Σύμφωνα με την τεκμηρίωση, η μέθοδος first! είναι ίδια με την πρώτη, αλλά εγείρει την εντολή ActiveRecord::RecordNotFound αν δεν βρεθεί καμία εγγραφή. Σημειώστε ότι η first! δεν δέχεται ορίσματα.
Αρχείο activerecord/lib/activerecord/relation/findermethods.rb, γραμμή 128
def first!
first || raiserecordnotfoundexception!
end
Ωστόσο, η μέθοδος ActiveRecord::FinderMethods#first που χρησιμοποιείται παραπάνω έχει την εξής μορφή:
Αρχείο activerecord/lib/activerecord/relation/findermethods.rb, γραμμή 116
def first(limit = nil)
checkreorderdeprecation unless loaded?
if limit
findnthwithlimit(0, limit)
else
findnth 0
end
end
Χάρη στα παραπάνω παραδείγματα, βλέπουμε τον κίνδυνο της χρήσης του πρώτου. Αν χρησιμοποιήσουμε το ActiveRecord::FinderMethods#find! και δεν βρει κατάλληλη εγγραφή στη βάση δεδομένων, τότε θα επιστρέψει το ActiveRecord::RecordNotFound, το οποίο μπορεί να προκαλέσει τη διακοπή της λειτουργίας του προγράμματός μας.
Ωστόσο, πρέπει να θυμόμαστε ότι αυτό δεν σημαίνει ότι αν μια μέθοδος δεν έχει θαυμαστικό στο τέλος, είναι ασφαλής και δεν θα προκαλέσει την εξαίρεση ή θα αλλάξει τον παραλήπτη.
Ένα νέο ζεύγος μεθόδων εισήχθη στο Ruby on Rails 6.0: ActiveRecord::Persistence::ClassMethods#insert_all
και ActiveRecord::Persistence::ClassMethods#insert_all!
Η πρώτη από αυτές τις μεθόδους παρουσιάζει ήδη έναν ορισμένο βαθμό επικινδυνότητας. Λοιπόν, σύμφωνα με την τεκμηρίωση, η εισαγωγήόλα εισάγουν πολλαπλές εγγραφές στη βάση δεδομένων με μία μόνο εντολή INSERT της SQL. Δεν ενσαρκώνει κανένα μοντέλο ούτε ενεργοποιεί ανακλήσεις ή επικυρώσεις της ActiveRecord. Ωστόσο, η εισαγωγήall! επιπρόσθετα προκαλεί το σφάλμα ActiveRecord::RecordNotUnique εάν κάποιες γραμμές παραβιάζουν ένα μοναδικό ευρετήριο στον πίνακα. Σε αυτή την περίπτωση, δεν εισάγονται γραμμές. Αυτό σημαίνει ότι η πρώτη από αυτές τις μεθόδους θα αποθηκεύσει όλες τις εγγραφές εκτός από εκείνες που παραβιάζουν το μοναδικό ευρετήριο, ενώ η δεύτερη (πιο επικίνδυνη) μέθοδος θα προκαλέσει μια εξαίρεση και δεν θα αποθηκεύσει καμία από τις εγγραφές στη βάση δεδομένων.
Πολλές μέθοδοι, ακόμη και αν δεν έχουν θαυμαστικό στο τέλος, είναι επικίνδυνες για χρήση. Για παράδειγμα, η ActiveRecord::FinderMethods#find. Σύμφωνα με την τεκμηρίωση Εάν δεν μπορούν να βρεθούν μία ή περισσότερες εγγραφές για τα ζητούμενα ids, τότε θα προκύψει η εντολή ActiveRecord::RecordNotFound.
Βλέπουμε ότι, παρόλο που αυτή η μέθοδος έχει τον ίδιο βαθμό επικινδυνότητας με την ActiveRecord::FinderMethods#first!, δεν έχει θαυμαστικό.
Το ίδιο ισχύει και για την τροποποίηση του παραλήπτη. Για παράδειγμα, η Array.delete (όπως τεκμηριώνεται) διαγράφει όλα τα στοιχεία από το self που είναι ίσα με το object και επιστρέφει το τελευταίο διαγραμμένο στοιχείο ή το nil αν δεν βρεθεί κανένα αντίστοιχο στοιχείο.
a = [1, 2, 3, 4, 5]
a.object_id #=> 320
a.delete(2) #=> 2
a #=> [1, 3, 4, 5]
a.delete(6) #=> nil
a.object_id #=> 320
Μπορείτε να δείτε καθαρά ότι το αντικείμενο έχει τροποποιηθεί. Αυτό που έχουν κοινό οι δύο μέθοδοι είναι ότι δεν έχουν ισοδύναμο θαυμαστικό. Επομένως, αν η μέθοδος που θέλουμε να δημιουργήσουμε θα έχει το είδος των κινδύνων που ανέφερα παραπάνω, δεν χρειάζεται να έχει αμέσως ένα θαυμαστικό στο τέλος. Επιπλέον, είναι σκόπιμο να δημιουργήσετε μια μέθοδο bang αν υπάρχει ήδη μια μέθοδος με το ίδιο όνομα που είναι λιγότερο επικίνδυνη από τη μέθοδο που θέλετε να δημιουργήσετε.
Μπορείτε να αναρωτηθείτε γιατί να χρησιμοποιείτε αυτές τις επικίνδυνες μεθόδους, ειδικά αφού συνήθως έχουμε λιγότερο επικίνδυνες αντίστοιχες μεθόδους. Ένα από τα πλεονεκτήματα μπορεί να είναι, για παράδειγμα, η βελτίωση της απόδοσης του κώδικα χάρη στη μείωση του αριθμού των αντικειμένων που δημιουργούνται. Εδώ μπορείτε να διαβάσετε περισσότερα για την αύξηση της απόδοσης του Rails.
Όσον αφορά την εμφάνιση εξαιρέσεων, η χρήση της μεθόδου create αντί της επικίνδυνης create! μπορεί να οδηγήσει σε μια κατάσταση όπου ένα σφάλμα στην εφαρμογή μας είναι δύσκολο να εντοπιστεί, επειδή οι εγγραφές δεν θα εγγραφούν στη βάση δεδομένων. Έτσι, αν είμαστε σίγουροι ότι οι παράμετροι που περνάμε σε αυτή τη μέθοδο είναι σωστές, θα πρέπει να χρησιμοποιήσουμε τη μέθοδο create!, η οποία θα προκαλέσει μια εξαίρεση αν, για κάποιο λόγο, η εγγραφή δεν αποθηκευτεί στη βάση δεδομένων.
Το συμπέρασμα είναι απλό και έχει ως εξής: η συνετή χρήση τέτοιων μεθόδων μπορεί να βελτιώσει την απόδοση και την ποιότητα του κώδικά μας. Ωστόσο, πρέπει πάντα να θυμόμαστε ότι η ακατάλληλη χρήση τους μπορεί να εμποδίσει τη σωστή εκτέλεση του κώδικα.
Αν θέλετε να δημιουργήσετε τη δική σας επικίνδυνη μέθοδο, πρέπει να περάσετε από μια συγκεκριμένη διαδικασία λήψης αποφάσεων. Πρώτον, το ερώτημα είναι αν υπάρχει ήδη μια μέθοδος με το ίδιο όνομα με αυτή που θέλετε να δημιουργήσετε, αλλά λιγότερο επικίνδυνη. Μπορείτε επίσης να εξετάσετε το ενδεχόμενο να δημιουργήσετε ένα ζεύγος μεθόδων στο οποίο η μία είναι ισοδύναμη με την άλλη, μόνο πιο επικίνδυνη.
Δεν έχει νόημα να δημιουργήσετε μια μέθοδο bang αν δεν υπάρχει η αντίστοιχη μέθοδος χωρίς θαυμαστικό. Υπάρχουν μέθοδοι που είναι επικίνδυνες επειδή αλλάζουν το αντικείμενο ή προκαλούν μια εξαίρεση, κι όμως δεν έχουν θαυμαστικό στο τέλος του ονόματος. Η δημιουργία μιας μεθόδου bang χωρίς ισοδύναμο θα προκαλούσε σύγχυση σε έναν προγραμματιστή που θα χρησιμοποιούσε τον κώδικά σας. Αυτό το άτομο δεν θα ήταν σε θέση να πει ποια είναι η επικινδυνότητα αυτής της μεθόδου και γιατί αξίζει ένα θαυμαστικό στο τέλος του ονόματός της.
Δεύτερον, θα πρέπει να εξετάσουμε για τι είδους κινδύνους μιλάμε. Από τα παραπάνω παραδείγματα, μπορούμε να συμπεράνουμε ότι ο πιο συνηθισμένος τύπος κινδύνου είναι η αλλαγή του ίδιου του αντικειμένου (αντί της δημιουργίας αντιγράφου του) ή η εμφάνιση μιας εξαίρεσης. Φυσικά, αυτό δεν αποτελεί κανόνα αλλά μάλλον αποτέλεσμα της ανάλυσης των μεθόδων που έχουν οριστεί στη Ruby και στο Ruby on Rails. Για παράδειγμα, θα μπορούσαμε να εξετάσουμε την υλοποίηση ενός ζεύγους μεθόδων στο οποίο η μέθοδος χωρίς το θαυμαστικό θα αποθήκευε την εγγραφή στη βάση δεδομένων, ενώ η μέθοδος με το θαυμαστικό θα παρέλειπε την επικύρωση αυτής της εγγραφής. Σε αυτή την περίπτωση, είναι σαφές πού βρίσκεται ο δυνητικός κίνδυνος από τη χρήση τέτοιων μεθόδων.
Μια σύνοψη της γνώσης των μεθόδων κρότου-λάμψης οδηγεί στα εξής συμπεράσματα: η 1η μέθοδος με το θαυμαστικό έχει μια λιγότερο απειλητικό
η αντίστοιχη χωρίς θαυμαστικό, δεύτερον, η μέθοδος με το θαυμαστικό εκτελεί μια επικίνδυνη ενέργεια, π.χ. τροποποιεί τον παραλήπτη ή δημιουργεί μια εξαίρεση.
Εν κατακλείδι, η κατανόηση της έννοιας της μέθοδοι bang στο Ruby ανάπτυξη λογισμικού μπορεί να βελτιώσει σημαντικά τις δεξιότητές σας στον προγραμματισμό και να δώσει μεγαλύτερη σαφήνεια στην κωδικοποιημένη βάση σας. Μέθοδοι Bang, που συμβολίζονται με ένα θαυμαστικό στο τέλος των ονομάτων τους, υποδηλώνουν μια καταστροφική ή δυνητικά επικίνδυνη έκδοση μιας μεθόδου. Κατά σύμβαση, η bang αντίστοιχο μιας μεθόδου πρέπει να χρησιμοποιείται με προσοχή, καθώς μπορεί να τροποποιήσει αντικείμενα απευθείας, χωρίς να δημιουργήσει ένα ξεχωριστό αντίγραφο. Αυτό μπορεί να είναι ιδιαίτερα χρήσιμο όταν έχετε να κάνετε με μεταβλητά αντικείμενα ή όταν η βελτιστοποίηση της απόδοσης αποτελεί πρόβλημα. Ωστόσο, είναι σημαντικό να είστε προσεκτικοί όταν χρησιμοποιείτε μεθόδους bang, καθώς μπορεί να έχουν απρόβλεπτες συνέπειες αν δεν τις χειριστείτε σωστά. Αξίζει επίσης να σημειωθεί ότι δεν έχουν όλες οι μέθοδοι ένα έκδοση bang, και η παρουσία τους πρέπει να αξιολογείται κατά περίπτωση. Με τη γνώση του πότε και πώς να δημιουργείτε μεθόδους bang, μπορείτε να χρησιμοποιήσετε αυτό το ισχυρό εργαλείο αποτελεσματικά και να γράψετε καθαρό, αποτελεσματικό κώδικα που να ανταποκρίνεται στις συγκεκριμένες απαιτήσεις σας.