Προγραμματισμός

Κωδικοποιήστε σε JavaScript τον έξυπνο, αρθρωτό τρόπο

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

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

Σχέδιο ενότητας

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

(λειτουργία(){

// «ιδιωτική» μεταβλητή

var orderId = 123;

// εκθέστε μεθόδους και μεταβλητές επισυνάπτοντάς τις

// στο καθολικό αντικείμενο

window.orderModule = {

getOrderId: function () {

// σας έφερε από κλεισίματα

επιστροφή παραγγελίας;

}

};

})()

Ένας ανώνυμοςλειτουργία Η έκφραση, ενεργώντας ως εργοστάσιο σε αυτήν την περίπτωση, γράφεται και καλείται αμέσως. Για ταχύτητα, μπορείτε να περάσετε ρητά σε μεταβλητές στολειτουργία καλέστε, επαναφέροντας αποτελεσματικά αυτές τις μεταβλητές σε τοπικό εύρος. Θα το δείτε επίσης μερικές φορές ως αμυντικό ελιγμό σε βιβλιοθήκες που υποστηρίζουν παλιά προγράμματα περιήγησης όπου ορισμένες τιμές (όπωςαπροσδιόριστος) είναι εγγράψιμες ιδιότητες.

(συνάρτηση (καθολική, απροσδιόριστη) {

// ο κωδικός εδώ μπορεί να αποκτήσει γρήγορη πρόσβαση στο καθολικό αντικείμενο,

// και το "undefined" είναι σίγουρο ότι είναι "undefined"

// ΣΗΜΕΙΩΣΗ: Στα σύγχρονα προγράμματα περιήγησης το "undefined" δεν είναι εγγράψιμο,

// αλλά αξίζει να το έχουμε κατά νου

// κατά τη σύνταξη κώδικα για παλιά προγράμματα περιήγησης.

})(Αυτό)

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

Εάν γράφετε μια εφαρμογή, ωστόσο, υπάρχουν μερικά μειονεκτήματα σε αυτήν την προσέγγιση. Ας υποθέσουμε ότι δημιουργείτε μια ενότητα που θέτει μερικές μεθόδουςwindow.order. Εάν θέλετε να χρησιμοποιήσετε αυτές τις μεθόδους σε άλλα μέρη της εφαρμογής σας, πρέπει να βεβαιωθείτε ότι η ενότητα περιλαμβάνεται πριν τις καλέσετε. Στη συνέχεια, στον κωδικό όπου καλείτεwindow.orders.getOrderId, γράφετε τον κωδικό και ελπίζετε ότι το άλλο σενάριο έχει φορτωθεί.

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

AMD (ορισμός ασύγχρονης ενότητας)

Το AMD γεννήθηκε λόγω της ανάγκης καθορισμού ρητών εξαρτήσεων, αποφεύγοντας ταυτόχρονα τη σύγχρονη φόρτωση όλων των σεναρίων. Είναι εύκολο στη χρήση σε ένα πρόγραμμα περιήγησης αλλά δεν είναι εγγενές, οπότε πρέπει να συμπεριλάβετε μια βιβλιοθήκη που κάνει φόρτωση σεναρίων, όπως RequireJS ή curl.js. Εδώ είναι πώς φαίνεται να ορίζετε μια ενότητα χρησιμοποιώντας AMD:

// libs / order-module.js

καθορισμός (συνάρτηση () {

// «ιδιωτική» μεταβλητή

var orderId = 123;

// εκθέστε μεθόδους και μεταβλητές επιστρέφοντάς τις

ΕΠΙΣΤΡΟΦΗ {

getOrderId: function () {

επιστροφή παραγγελίας;

}

});

Μοιάζει με αυτό που αντιμετωπίζαμε στο παρελθόν, εκτός από το ότι αντί να καλέσουμε άμεσα τη λειτουργία του εργοστασίου μας, περνάμε ως επιχείρημακαθορίζω. Η πραγματική μαγεία αρχίζει να συμβαίνει όταν θέλετε να χρησιμοποιήσετε την ενότητα αργότερα:

καθορισμός (['libs / order-module'], function (orderModule) {

orderModule.getOrderId (); // αξιολογείται σε 123

});

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

// src / utils.js

define (['libs / underscore'], συνάρτηση (_) {

ΕΠΙΣΤΡΟΦΗ {

moduleId: «foo»,

_ : _

});

// src / myapp.js

ορίσω ([

"libs / jquery",

"libs / τιμόνι",

"src / utils"

], λειτουργία ($, τιμόνι, εργαλεία) {

// Χρησιμοποιήστε κάθε μία από τις αναφερόμενες εξαρτήσεις χωρίς

// ανησυχεί αν είναι εκεί ή όχι.

$ ('div'). addClass ('bar');

// Έχουν επίσης ληφθεί μέριμνα για τις εξαρτήσεις

Utils ._. Πλήκτρα (παράθυρο);

});

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

Από την άλλη πλευρά, υπάρχουν μερικά πιθανά ζητήματα. Πρώτον, έχετε μια επιπλέον βιβλιοθήκη για να συμπεριλάβετε και να μάθετε να χρησιμοποιείτε. Δεν έχω εμπειρία με το curl.js, αλλά το RequireJS περιλαμβάνει την εκμάθηση του τρόπου ρύθμισης παραμέτρων για το έργο σας. Αυτό θα διαρκέσει μερικές ώρες για να εξοικειωθείτε με τις ρυθμίσεις, μετά τις οποίες η αρχική διαμόρφωση θα διαρκέσει λίγα λεπτά. Επίσης, οι ορισμοί των λειτουργικών μονάδων μπορούν να αυξηθούν μακροπρόθεσμα εάν οδηγούν σε έναν σωρό εξαρτήσεων. Ακολουθεί ένα παράδειγμα, που λαμβάνεται από την εξήγηση αυτού του προβλήματος στην τεκμηρίωση RequireJS:

// Από την τεκμηρίωση RequireJS:

// //requirejs.org/docs/whyamd.html#sugar

καθορισμός (["απαιτείται", "jquery", "blade / αντικείμενο", "blade / fn", "rdapi",

"oauth", "blade / jig", "blade / url", "αποστολή", "λογαριασμοί",

"αποθήκευση", "υπηρεσίες", "widgets / AccountPanel", "widgets / TabButton",

"widgets / AddAccount", "less", "osTheme", "jquery-ui-1.8.7.min",

"jquery.textOverflow"],

συνάρτηση (απαιτείται, $, αντικείμενο, fn, rdapi,

oauth, jig, url, αποστολή, λογαριασμοί,

αποθήκευση, υπηρεσίες, AccountPanel, TabButton,

Προσθήκη λογαριασμού, λιγότερο, osTheme) {

});

Ωχ! Το RequireJS παρέχει κάποια συντακτική ζάχαρη για να το αντιμετωπίσει, το οποίο μοιάζει κάπως με ένα άλλο δημοφιλές API για αρθρωτή ανάπτυξη, το CommonJS.

CJS (CommonJS)

Εάν έχετε γράψει ποτέ JavaScript από την πλευρά του διακομιστή χρησιμοποιώντας το Node.js, έχετε χρησιμοποιήσει λειτουργικές μονάδες CommonJS. Κάθε αρχείο που γράφετε δεν είναι τυλιγμένο σε κάτι φανταχτερό, αλλά έχει πρόσβαση σε μια μεταβλητή που ονομάζεταιεξαγωγές στην οποία μπορείτε να εκχωρήσετε οτιδήποτε θέλετε να εκτεθεί από τη μονάδα. Δείτε πώς φαίνεται:

// μια «ιδιωτική» μεταβλητή

var orderId = 123;

export.getOrderId = συνάρτηση () {

επιστροφή παραγγελίας;

};

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

// orderModule παίρνει την αξία των «εξαγωγών»

var orderModule = απαιτείται ('./ order-module');

orderModule.getOrderId (); // αξιολογείται σε 123

Συντακτικά, αυτό μου φαινόταν πάντα καλύτερο, κυρίως επειδή δεν περιλαμβάνει τη σπατάλη εσοχή που υπάρχει στις άλλες επιλογές που έχουμε συζητήσει. Από την άλλη πλευρά, διαφέρει πολύ από τα άλλα, καθώς έχει σχεδιαστεί για σύγχρονη φόρτωση εξαρτήσεων. Αυτό έχει πιο νόημα στον διακομιστή, αλλά δεν θα το κάνει στην πρώτη πλευρά. Η σύγχρονη φόρτωση εξάρτησης σημαίνει μεγαλύτερους χρόνους φόρτωσης σελίδας, κάτι που είναι απαράδεκτο για τον Ιστό. Ενώ το CJS είναι μακράν η αγαπημένη μου σύνταξη μονάδας, το χρησιμοποιώ μόνο στο διακομιστή (και ενώ γράφω εφαρμογές για κινητά με το Titanium Studio του Appcelerator).

Κάποιος να τους κυβερνήσει όλα

Το τρέχον προσχέδιο της έκτης έκδοσης του ECMAScript (ES6), η προδιαγραφή από την οποία εφαρμόζεται το JavaScript, προσθέτει εγγενή υποστήριξη για ενότητες. Η προδιαγραφή είναι ακόμη σε μορφή σχεδίου, αλλά αξίζει να ρίξετε μια ματιά στο πώς θα μπορούσε να μοιάζει το μέλλον για την αρθρωτή ανάπτυξη. Αρκετές νέες λέξεις-κλειδιά χρησιμοποιούνται στην προδιαγραφή ES6 (επίσης γνωστή ως Harmony), πολλές από τις οποίες χρησιμοποιούνται με λειτουργικές μονάδες:

// libs / order-module.js

var orderId = 123;

εξαγωγή var getOrderId = συνάρτηση () {

επιστροφή παραγγελίας;

};

Μπορείτε να το καλέσετε αργότερα με διάφορους τρόπους:

εισαγωγή {getOrderId} από το "libs / order-module";

getOrderId ();

Πάνω, επιλέγετε και επιλέγετε ποιες εξαγωγές σε μια ενότητα που θέλετε να συνδέσετε με τοπικές μεταβλητές. Εναλλακτικά, μπορείτε να εισαγάγετε ολόκληρη τη λειτουργική μονάδα σαν να ήταν αντικείμενο (παρόμοιο με τοεξαγωγές αντικείμενο σε μονάδες CJS):

εισαγωγή "libs / order-module" ως orderModule;

orderModule.getOrderId ();

Υπάρχουν πολλά περισσότερα για τις ενότητες ES6 (δείτε το blog 2ality του Dr. Axel Rauschmayer για περισσότερα), αλλά το παράδειγμα πρέπει να σας δείξει μερικά πράγματα. Πρώτον, έχουμε μια σύνταξη παρόμοια με τις μονάδες CJS, πράγμα που σημαίνει ότι δεν υπάρχει πουθενά επιπλέον εσοχή, αν και αυτό δεν συμβαίνει πάντα, όπως θα βρείτε στον παραπάνω σύνδεσμο 2ality. Αυτό που δεν είναι προφανές κοιτάζοντας το παράδειγμα, ειδικά επειδή μοιάζει πολύ με το CJS, είναι ότι οι ενότητες που αναφέρονται στη δήλωση εισαγωγής φορτώνονται ασύγχρονα.

Το τελικό αποτέλεσμα είναι η ευανάγνωστη σύνταξη του CJS αναμεμιγμένη με την ασύγχρονη φύση του AMD. Δυστυχώς, θα χρειαστεί λίγη ώρα πριν υποστηρίζονται πλήρως σε όλα τα προγράμματα περιήγησης που στοχεύονται συνήθως. Τούτου λεχθέντος, «λίγο καιρό» αυξάνεται όλο και πιο σύντομα καθώς οι προμηθευτές προγραμμάτων περιήγησης σφίγγουν τους κύκλους κυκλοφορίας τους.

Σήμερα, ένας συνδυασμός αυτών των εργαλείων είναι ο τρόπος που πρέπει να ακολουθήσετε όταν πρόκειται για αρθρωτή ανάπτυξη JavaScript. Όλα εξαρτώνται από το τι κάνεις. Εάν γράφετε βιβλιοθήκη, χρησιμοποιήστε το μοτίβο σχεδίασης της ενότητας Εάν δημιουργείτε εφαρμογές για το πρόγραμμα περιήγησης, χρησιμοποιήστε μονάδες AMD με ένα πρόγραμμα φόρτωσης σεναρίων. Εάν βρίσκεστε στο διακομιστή, εκμεταλλευτείτε τις μονάδες CJS. Τελικά, φυσικά, το ES6 θα υποστηρίζεται γενικά - σε ποιο σημείο μπορείτε να κάνετε τα πράγματα με τον τρόπο ES6 και να απορρίψετε τα υπόλοιπα!

Ερωτήσεις ή σκέψεις; Μη διστάσετε να αφήσετε ένα μήνυμα παρακάτω στην ενότητα σχολίων ή να επικοινωνήσετε μαζί μου στο Twitter, @ freethejazz.

$config[zx-auto] not found$config[zx-overlay] not found