Μερικές φορές, οι πελάτες μας δίνουν αιτήματα λειτουργιών που πραγματικά δεν μας αρέσουν. Δεν είναι ότι δεν μας αρέσουν οι πελάτες μας - αγαπάμε τους πελάτες μας. Δεν μας αρέσει η λειτουργία - οι περισσότερες λειτουργίες που ζητούνται από τον πελάτη ευθυγραμμίζονται τέλεια με τους επιχειρηματικούς τους στόχους και το εισόδημά τους.
Μερικές φορές, δεν μας αρέσει ένα αίτημα λειτουργίας, επειδή ο ευκολότερος τρόπος για να το λύσουμε είναι να γράψουμε κακό κώδικα και δεν έχουμε μια κομψή λύση στην κορυφή. Αυτό θα στείλει πολλούς από εμάς Προγραμματιστές σιδηροτροχιών σε άκαρπες αναζητήσεις RubyToolbox , GitHub , ιστολόγια προγραμματιστών και Υπερχείλιση στοίβας ψάχνοντας για ένα στολίδι ή ένα πρόσθετο ή έναν κωδικό κώδικα που θα μας κάνει να νιώθουμε καλύτερα για τον εαυτό μας.
Λοιπόν, είμαι εδώ για να σας πω: είναι εντάξει να γράφετε κακό κώδικα. Μερικές φορές, ο κώδικας Bad Rails είναι πιο εύκολο να αναπαράγεται σε έναν όμορφο κώδικα από μια κακώς μελετημένη λύση που εφαρμόζεται κάτω από μια χρονική κρίση.
Αυτή είναι η διαδικασία αναπαράστασης Rails που θέλω να ακολουθήσω όταν τρίβω προβλήματα από τις φρικτές λύσεις μου:
Για μια εναλλακτική προοπτική, εδώ είναι το Git comm log για μια λειτουργία που έχει αναδιαμορφωθεί βήμα προς βήμα:
Και εδώ είναι ένα άλλο ενδιαφέρον άρθρο ανακατασκευή μεγάλης κλίμακας από έναν συνάδελφο στο δίκτυο ApeeScape.
Ας δούμε πώς γίνεται.
Βήμα 1. Ξεκινήστε στο Views
Ας πούμε ότι ξεκινάμε ένα εισιτήριο για μια νέα δυνατότητα. Ο πελάτης μας λέει: 'Οι επισκέπτες θα πρέπει να μπορούν να δουν μια λίστα ενεργών έργων στη σελίδα καλωσορίσματος.'
Αυτό το εισιτήριο απαιτεί μια ορατή αλλαγή, οπότε ένα λογικό μέρος για να ξεκινήσετε τη δουλειά θα ήταν στις Προβολές. Το πρόβλημα είναι απλό και ένα πρόβλημα που έχουμε όλοι εκπαιδευτεί να επιλύουμε πολλές φορές. Θα το λύσω Ο ΛΑΘΟΣ ΔΡΟΜΟΣ και να δείξω πώς να επαναπροσδιορίσω τη λύση μου στους κατάλληλους τομείς. Επίλυση προβλήματος Ο ΛΑΘΟΣ ΔΡΟΜΟΣ μπορεί να μας βοηθήσει να ξεπεράσουμε το να μην γνωρίζουμε τη σωστή λύση.
Αρχικά, ας υποθέσουμε ότι έχουμε ένα μοντέλο που ονομάζεται Project
με ένα δυαδικό χαρακτηριστικό που ονομάζεται active
. Θέλουμε να λάβουμε μια λίστα με όλα τα Projects
όπου active
είναι ίσο με true
, ώστε να μπορούμε να χρησιμοποιήσουμε το Project.where(active: true)
και να το βρούμε με ένα each
ΟΙΚΟΔΟΜΙΚΟ ΤΕΤΡΑΓΩΝΟ.
app/views/pages/welcome.haml: %ul.projects - Project.where(active: true).each do |project| %li.project= link_to project_path(project), project.name
Ξέρω τι λέτε: 'Αυτό δεν θα περάσει ποτέ μια κριτική κώδικα' ή 'Ο πελάτης μου θα με απολύσει σίγουρα για αυτό'. Ναι, αυτή η λύση σπάει τον διαχωρισμό των ανησυχιών του Model-View-Controller, μπορεί να οδηγήσει σε αδέσμευτες κλήσεις βάσης δεδομένων που είναι δύσκολο να εντοπιστούν και μπορεί να γίνει δύσκολο να διατηρηθεί στο μέλλον. Αλλά σκεφτείτε την αξία του να το κάνετε Ο ΛΑΘΟΣ ΔΡΟΜΟΣ :
Βήμα 2. Μερικά
Αφού το κάνετε Ο ΛΑΘΟΣ ΔΡΟΜΟΣ Νιώθω άσχημα για τον εαυτό μου και θέλω να απομονώσω τον κακό κώδικα μου. Εάν αυτή η αλλαγή ήταν σαφώς μόνο μια ανησυχία για το επίπεδο προβολής, θα μπορούσα να επαναπροσδιορίσω την ντροπή μου σε μερική.
app/views/pages/welcome.haml: = render :partial => 'shared/projects_list' app/views/shared/projects_list.haml: %ul.projects - Project.where(active: true).each do |project| %li.project= link_to project_path(project), project.name
Αυτό είναι λίγο καλύτερο. Είναι σαφές ότι εξακολουθούμε να κάνουμε το λάθος ενός ερωτήματος Μοντέλου σε μια Προβολή, αλλά τουλάχιστον όταν ένας συντηρητής μπαίνει αργότερα και βλέπει το φρικτό μερικό μου, θα έχουν έναν απλό τρόπο αντιμετώπισης του συγκεκριμένου προβλήματος κώδικα Rails. Η επιδιόρθωση κάτι προφανώς χαζή είναι πάντα πιο εύκολο από το να διορθώνεις μια αφαιρετική αφαίρεση με λάθη.
Η επιδιόρθωση κάτι προφανώς χαζή είναι πάντα πιο εύκολο από το να διορθώνεις μια αφαιρετική αφαίρεση με λάθη. ΤιτίβισμαΒήμα 3. Βοηθοί
Οι βοηθοί στο Rails είναι ένας τρόπος δημιουργίας ενός DSL (Ειδική γλώσσα τομέα) για μια ενότητα των προβολών σας. Πρέπει να ξαναγράψετε τον κωδικό σας χρησιμοποιώντας το content_tag's αντί χαμλ ή HTML, αλλά έχετε το πλεονέκτημα ότι επιτρέπετε να χειρίζεστε δομές δεδομένων χωρίς να σας βλέπουν άλλοι προγραμματιστές για 15 γραμμές μη εκτυπώσιμου κώδικα προβολής.
Αν επρόκειτο να χρησιμοποιήσω βοηθούς εδώ, πιθανότατα να αναπαράγω το li
ετικέτα.
app/views/shared/projects_list.haml: %ul.projects - Project.where(active: true).each do |project| = project_list_item(project) app/helpers/projects_helper.rb: def project_list_item(project) content_tag(:li, :class => 'project') do link_to project_path(project), project.name end end
Βήμα 4. Μετακινήστε το στους Ελεγκτές
Ίσως ο απαίσιος κώδικάς σας δεν είναι απλώς μια ανησυχία προβολής. Εάν ο κωδικός σας μυρίζει ακόμα, αναζητήστε ερωτήματα που μπορείτε να πραγματοποιήσετε μετάβαση από τις Προβολές στους Ελεγκτές.
app/views/shared/projects_list.haml: %ul.projects - @projects_list.each do |project| = project_list_item(project) app/controllers/pages_controller.rb: def welcome @projects = Project.where(active: true) end
Βήμα 5. Φίλτρα ελεγκτή
Ο πιο προφανής λόγος για τη μεταφορά κώδικα σε έναν ελεγκτή before_filter
ή after_filter
είναι για κώδικα που έχετε αντιγράψει σε πολλές ενέργειες ελεγκτή. Μπορείτε επίσης να μετακινήσετε τον κωδικό σε ένα Φίλτρο ελεγκτή εάν θέλετε να διαχωρίσετε τον σκοπό της ενέργειας Ελεγκτή από τις απαιτήσεις των απόψεών σας.
app/controllers/pages_controller.rb: before_filter :projects_list def welcome end def projects_list @projects = Project.where(active:true) end
Βήμα 6. Ελεγκτής εφαρμογών
Ας υποθέσουμε ότι χρειάζεστε τον κωδικό σας για να εμφανίζεται σε κάθε σελίδα ή εάν θέλετε να κάνετε τις λειτουργίες βοηθού ελεγκτή διαθέσιμες σε όλους τους ελεγκτές, μπορείτε να μετακινήσετε τη λειτουργία σας στο ApplicationController. Εάν οι αλλαγές είναι καθολικές, ίσως θελήσετε να τροποποιήσετε τη διάταξη της εφαρμογής σας.
app/controllers/pages_controller.rb: def welcome end app/views/layouts/application.haml: %ul.projects - projects_list.each do |project| = project_list_item(project) app/controllers/application_controller.rb: before_filter :projects_list def projects_list @projects = Project.where(active: true) end
Βήμα 7. Επαναπροσδιορισμός στο μοντέλο
Καθώς το σύνθημα MVC πηγαίνει: Fat Model, Skinny Controllers και Dumb Views . Αναμένεται να επαναπροσδιορίσουμε ό, τι μπορούμε στο Μοντέλο και είναι αλήθεια ότι η πιο πολύπλοκη λειτουργικότητα θα γίνει τελικά συσχετισμοί μοντέλων και μέθοδοι μοντέλου. Πρέπει πάντα να αποφεύγουμε τη μορφοποίηση / προβολή πραγμάτων στο Μοντέλο, αλλά η μετατροπή δεδομένων σε άλλους τύπους δεδομένων επιτρέπεται. Σε αυτήν την περίπτωση, το καλύτερο πράγμα που πρέπει να αναπαράγεται στο Μοντέλο είναι το where(active: true)
ρήτρα, την οποία μπορούμε να μετατρέψουμε σε πεδίο εφαρμογής. Η χρήση ενός πεδίου είναι πολύτιμη όχι μόνο επειδή κάνει την κλήση να φαίνεται πιο όμορφη, αλλά αν αποφασίσαμε ποτέ να προσθέσουμε ένα χαρακτηριστικό όπως delete
ή outdated
, μπορούμε να τροποποιήσουμε αυτό το πεδίο αντί να κυνηγήσουμε όλα τα where
ρήτρες.
app/controllers/application_controller.rb: before_filter :projects_list def projects_list @projects = Project.active end app/models/project.rb: scope :active, where(active: true)
Βήμα 8. Φίλτρα μοντέλου
Δεν έχουμε συγκεκριμένη χρήση για ένα μοντέλο του before_save
ή after_save filters
σε αυτήν την περίπτωση, αλλά το επόμενο βήμα που συνήθως κάνω είναι να μεταφέρω τη λειτουργικότητα από τους ελεγκτές και τις μεθόδους μοντέλου σε φίλτρα μοντέλου.
Ας πούμε ότι είχαμε ένα άλλο χαρακτηριστικό, num_views
. Εάν num_views > 50
, το Έργο καθίσταται ανενεργό. Θα μπορούσαμε να λύσουμε αυτό το πρόβλημα στην Προβολή, αλλά η πραγματοποίηση αλλαγών στη βάση δεδομένων σε μια Προβολή δεν είναι κατάλληλη. Θα μπορούσαμε να το λύσουμε στον Ελεγκτή, αλλά οι Ελεγκτές μας θα πρέπει να είναι όσο το δυνατόν πιο λεπτοί! Μπορούμε να το λύσουμε εύκολα στο Μοντέλο.
app/models/project.rb: before_save :deactivate_if_over_num_views def deactivate_if_over_num_views if num_views > 50 self.active = false fi end
Σημείωση: θα πρέπει να αποφύγετε την κλήση self.save
σε ένα φίλτρο Μοντέλου, καθώς αυτό προκαλεί επαναλαμβανόμενα συμβάντα αποθήκευσης και το επίπεδο χειρισμού της βάσης δεδομένων της εφαρμογής σας θα πρέπει οπωσδήποτε να είναι ο Ελεγκτής.
Βήμα 9. Βιβλιοθήκες
Περιστασιακά, η λειτουργία σας είναι αρκετά μεγάλη ώστε να δικαιολογεί τη δική της βιβλιοθήκη. Ίσως θελήσετε να το μετακινήσετε σε ένα αρχείο βιβλιοθήκης επειδή χρησιμοποιείται ξανά σε πολλά μέρη ή είναι αρκετά μεγάλο ώστε να θέλετε να το αναπτύξετε ξεχωριστά.
Είναι ωραίο να αποθηκεύετε αρχεία βιβλιοθήκης στο lib / κατάλογο, αλλά καθώς μεγαλώνουν, μπορείτε να τα μεταφέρετε σε πραγματικό RubyGem ! Ένα σημαντικό πλεονέκτημα της μετακίνησης του κωδικού σας σε μια βιβλιοθήκη είναι ότι μπορείτε να δοκιμάσετε τη βιβλιοθήκη ξεχωριστά από το μοντέλο σας.
Τέλος πάντων, στην περίπτωση μιας λίστας έργων, θα μπορούσαμε να δικαιολογήσουμε τη μετακίνηση του scope :active
κλήση από το Project
μοντέλο σε ένα αρχείο βιβλιοθήκης και επαναφορά του στο Ruby:
llc c or s corp
app/models/project.rb: class Project 50 self.active = false end end end
Σημείωση: το self.included
Η μέθοδος καλείται όταν φορτώνεται μια κλάση Rails Model και περνά στο πεδίο της κλάσης ως μεταβλητή k
.
Σε αυτό το σεμινάριο επαναπροσδιορισμού Ruby on Rails, έχουμε πάρει λιγότερο από 15 λεπτά και εφαρμόσαμε μια λύση και την θέσαμε σε στάση για δοκιμές χρηστών, έτοιμες να γίνουν δεκτές στο σύνολο λειτουργιών ή να καταργηθούν. Μέχρι το τέλος της διαδικασίας αναδιαμόρφωσης, έχουμε ένα κομμάτι κώδικα που καθορίζει ένα πλαίσιο για την εφαρμογή στοιχείων με δυνατότητα λίστας, ενεργοποίησης σε πολλά Μοντέλα που θα περάσουν ακόμη και την πιο αυστηρή διαδικασία ελέγχου.
Στη δική σας διαδικασία αναδιαμόρφωσης Rails, μη διστάσετε να παραλείψετε μερικά βήματα κάτω από τον αγωγό εάν είστε βέβαιοι να το κάνετε (π.χ., μεταβείτε από το View to Controller ή Controller to Model). Απλώς λάβετε υπόψη ότι η ροή κώδικα είναι από το View στο Model.
Μην φοβάστε να φαίνετε ανόητοι. Αυτό που διαχωρίζει τις σύγχρονες γλώσσες από τις παλιές εφαρμογές απόδοσης προτύπου CGI δεν είναι ότι κάνουμε τα πάντα Ο σωστός τρόπος κάθε φορά - αφιερώνουμε χρόνο για να αναπαράγουμε, να επαναχρησιμοποιούμε και να μοιραζόμαστε τις προσπάθειές μας.
Σχετίζεται με: Timestamp Truncation: A Ruby on Rails ActiveRecord Tale