portaldacalheta.pt
  • Κύριος
  • Επιστήμη Δεδομένων Και Βάσεις Δεδομένων
  • Κατανεμημένες Ομάδες
  • Ευκίνητο Ταλέντο
  • Κερδοφορία & Αποδοτικότητα
Πίσω Μέρος

Δηλωτικός προγραμματισμός: Είναι πραγματικό πράγμα;



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

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



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



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



Εάν ο δηλωτικός προγραμματισμός λειτουργεί καλά για εσάς, Δεν είμαι σε θέση να σας πω διαφορετικά .

Μπορείτε να αγαπάτε ή να μισείτε τον δηλωτικό προγραμματισμό, αλλά δεν μπορείτε να το αγνοήσετε. Τιτίβισμα

Τα πλεονεκτήματα του δηλωτικού προγραμματισμού

Προτού διερευνήσουμε τα όρια του δηλωτικού προγραμματισμού, είναι απαραίτητο να κατανοήσουμε τα πλεονεκτήματά του.



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

  • Γλώσσα για συγκεκριμένους τομείς (DSL) : η καθολική διεπαφή για σχεσιακές βάσεις δεδομένων ονομάζεται DSL Γλώσσα δομημένων ερωτημάτων , πιο γνωστό ως SQL.
  • Το DSL κρύβει το επίπεδο χαμηλότερου επιπέδου από το χρήστη : από τότε Πρωτότυπο έγγραφο του Edgar F. Codd για RDBs , είναι σαφές ότι η ισχύς αυτού του μοντέλου είναι να αποσυνδέσει τα επιθυμητά ερωτήματα από τους υποκείμενους βρόχους, ευρετήρια και διαδρομές πρόσβασης που τα εφαρμόζουν.

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

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

Ποια είναι τα κοινά πλεονεκτήματα του δηλωτικού προγραμματισμού;

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

Οι υποστηρικτές του δηλωτικού προγραμματισμού επισημαίνουν γρήγορα τα πλεονεκτήματα. Ωστόσο, ακόμη και παραδέχονται ότι έρχεται με συμβιβασμούς. Τιτίβισμα
  1. Αναγνωσιμότητα / χρηστικότητα : ένα DSL είναι συνήθως πιο κοντά σε μια φυσική γλώσσα (όπως στα Αγγλικά) παρά στον ψευδοκώδικα, ως εκ τούτου πιο ευανάγνωστο και επίσης πιο εύκολο να μάθει από μη προγραμματιστές.
  2. Περιεκτικότητα : μεγάλο μέρος του boilerplate αφαιρείται από το DSL, αφήνοντας λιγότερες γραμμές για να κάνουν την ίδια δουλειά.
  3. Επαναχρησιμοποίηση : είναι πιο εύκολο να δημιουργήσετε κώδικα που μπορεί να χρησιμοποιηθεί για διαφορετικούς σκοπούς. κάτι που είναι εξαιρετικά δύσκολο όταν χρησιμοποιείτε επιτακτικές κατασκευές.
  4. Αδυναμία : μπορείτε να εργαστείτε με τελικές καταστάσεις και αφήστε το πρόγραμμα να το καταλάβει. Για παράδειγμα, μέσω μιας λειτουργίας upsert, μπορείτε είτε να εισαγάγετε μια σειρά εάν δεν υπάρχει, είτε να την τροποποιήσετε εάν είναι ήδη εκεί, αντί να γράψετε κώδικα για να αντιμετωπίσετε και τις δύο περιπτώσεις.
  5. Ανάκτηση σφάλματος : είναι εύκολο να καθορίσετε μια κατασκευή που θα σταματήσει στο πρώτο σφάλμα αντί να χρειάζεται να προσθέσετε ακροατές για κάθε πιθανό σφάλμα. (Εάν έχετε γράψει ποτέ τρεις ένθετες επιστροφές στο node.js, ξέρετε τι εννοώ.)
  6. Αναφορά διαφάνειας : Αν και αυτό το πλεονέκτημα συνδέεται συνήθως με τον λειτουργικό προγραμματισμό, ισχύει στην πραγματικότητα για οποιαδήποτε προσέγγιση που ελαχιστοποιεί τον χειροκίνητο χειρισμό της κατάστασης και βασίζεται σε παρενέργειες.
  7. Ανταλλακτικότητα : τη δυνατότητα έκφρασης μιας κατάληξης χωρίς να χρειάζεται να προσδιορίσετε την πραγματική σειρά με την οποία θα εφαρμοστεί.

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

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

Δύο προβλήματα με τον δηλωτικό προγραμματισμό

Στις ακόλουθες δύο ενότητες, θα παρουσιάσω τα δύο κύρια προβλήματα του δηλωτικού προγραμματισμού: χωριστό και έλλειψη ξεδιπλώματος . Κάθε κριτική χρειάζεται το bogeyman της, οπότε θα χρησιμοποιήσω συστήματα templating HTML ως συγκεκριμένο παράδειγμα των αδυναμιών του δηλωτικού προγραμματισμού.

Το πρόβλημα με τα DSL: Χωριστότητα

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

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

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

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

Η δεύτερη πηγή τριβής είναι ότι το DSL έχει τη δική του σύνταξη, διαφορετική από αυτήν της γλώσσας προγραμματισμού. Ως εκ τούτου, η τροποποίηση του DSL (πόσο μάλλον η σύνταξη της δικής σας) είναι πολύ πιο δύσκολη. Για να πάτε κάτω από την κουκούλα και να αλλάξετε το εργαλείο, πρέπει να μάθετε για το tokenizing και την ανάλυση, κάτι που είναι ενδιαφέρον και προκλητικό, αλλά δύσκολο. Τυχαία το βλέπω ως μειονέκτημα.

Μπορείτε να ρωτήσετε, 'Γιατί στη γη θα θέλατε να τροποποιήσετε το εργαλείο σας; Εάν κάνετε ένα τυπικό έργο, ένα καλογραμμένο τυπικό εργαλείο θα πρέπει να ταιριάζει στο λογαριασμό. ' Ισως ναι ίσως όχι.

Ένα DSL δεν έχει ποτέ την πλήρη δύναμη μιας γλώσσας προγραμματισμού. Αν το έκανε, δεν θα ήταν πια DSL, αλλά μάλλον μια πλήρης γλώσσα προγραμματισμού.

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

  • Αντικαταστήστε το κείμενο μέσα σε ένα πρότυπο : μεταβλητή υποκατάσταση.
  • Επανάληψη προτύπου : βρόχους.
  • Αποφύγετε την εκτύπωση προτύπου εάν δεν πληρούται μια συνθήκη : υποθετικοί.
  • Μερικά : υπορουτίνες.
  • Βοηθοί : υπορουτίνες (η μόνη διαφορά με μερική είναι ότι οι βοηθοί μπορούν να έχουν πρόσβαση στην υποκείμενη γλώσσα προγραμματισμού και να σας αφήσουν έξω από το straightjacket DSL).

Αυτό το επιχείρημα, ότι ένα DSL είναι περιορισμένο επειδή ταυτόχρονα επιθυμεί και απορρίπτει τη δύναμη μιας γλώσσας προγραμματισμού, είναι άμεσα ανάλογη στο βαθμό που τα χαρακτηριστικά του DSL μπορούν να αντιστοιχιστούν άμεσα με τα χαρακτηριστικά μιας γλώσσας προγραμματισμού . Στην περίπτωση της SQL, το επιχείρημα είναι αδύναμο επειδή τα περισσότερα από τα πράγματα που προσφέρει η SQL δεν μοιάζουν με αυτό που βρίσκετε σε μια κανονική γλώσσα προγραμματισμού. Στο άλλο άκρο του φάσματος, βρίσκουμε συστήματα προτύπων όπου σχεδόν κάθε λειτουργία κάνει το DSL να συγκλίνει προς ΒΑΣΙΚΟΣ .

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

Η χωριστότητα είναι εγγενές πρόβλημα οποιουδήποτε DSL, ανεξάρτητα από το πόσο καλά σχεδιασμένο.

Τώρα στραφούμε σε ένα δεύτερο πρόβλημα δηλωτικών εργαλείων, το οποίο είναι διαδεδομένο αλλά δεν είναι εγγενές.

Ένα άλλο πρόβλημα: Η έλλειψη ξεδιπλώματος οδηγεί στην πολυπλοκότητα

Εάν είχα γράψει αυτό το άρθρο πριν από μερικούς μήνες, αυτή η ενότητα θα είχε το όνομα Τα περισσότερα εργαλεία δήλωσης είναι # @! $ # @! Πολύπλοκο αλλά δεν ξέρω γιατί . Κατά τη διαδικασία σύνταξης αυτού του άρθρου βρήκα έναν καλύτερο τρόπο να το θέσω: Τα περισσότερα εργαλεία δήλωσης είναι πολύ πιο περίπλοκα από ό, τι πρέπει να είναι . Θα περάσω το υπόλοιπο αυτής της ενότητας εξηγώντας γιατί. Για να αναλύσω την πολυπλοκότητα ενός εργαλείου, προτείνω ένα μέτρο που ονομάζεται χάσμα πολυπλοκότητας . Το κενό πολυπλοκότητας είναι η διαφορά μεταξύ της επίλυσης ενός δεδομένου προβλήματος με ένα εργαλείο έναντι της επίλυσης στο χαμηλότερο επίπεδο (πιθανώς, απλός επιτακτικός κωδικός) που το εργαλείο σκοπεύει να αντικαταστήσει. Όταν η προηγούμενη λύση είναι πιο περίπλοκη από την τελευταία, είμαστε παρόντες στο κενό πολυπλοκότητας. Με πιο πολύπλοκο , Εννοώ περισσότερες γραμμές κώδικα, κώδικα που είναι πιο δύσκολο να διαβαστεί, πιο δύσκολο να τροποποιηθεί και πιο δύσκολο να διατηρηθεί, αλλά όχι απαραίτητα όλα αυτά ταυτόχρονα.

Λάβετε υπόψη ότι δεν συγκρίνουμε τη λύση χαμηλότερου επιπέδου με το καλύτερο δυνατό εργαλείο, αλλά αντίθετα όχι εργαλείο. Αυτό αντανακλά την ιατρική αρχή του «Πρώτα, μην βλάπτεις» .

Τα σημάδια ενός εργαλείου με μεγάλο χάσμα πολυπλοκότητας είναι:

  • Κάτι που χρειάζεται λίγα λεπτά για να περιγραφεί με πλούσια λεπτομέρεια σε επιτακτικούς όρους, θα χρειαστούν ώρες για να κωδικοποιηθεί χρησιμοποιώντας το εργαλείο, ακόμη και όταν γνωρίζετε πώς να χρησιμοποιήσετε το εργαλείο.
  • Πιστεύετε ότι εργάζεστε συνεχώς γύρω από το εργαλείο και όχι με το εργαλείο.
  • Προσπαθείτε να λύσετε ένα απλό πρόβλημα που ανήκει ακριβώς στον τομέα του εργαλείου που χρησιμοποιείτε, αλλά η καλύτερη απάντηση Stack Overflow που βρείτε περιγράφει λύση .
  • Όταν αυτό το πολύ απλό πρόβλημα θα μπορούσε να επιλυθεί με μια συγκεκριμένη δυνατότητα (η οποία δεν υπάρχει στο εργαλείο) και βλέπετε ένα ζήτημα Github στη βιβλιοθήκη που περιλαμβάνει μια μακρά συζήτηση του εν λόγω χαρακτηριστικού με +1 είναι διάσπαρτα.
  • Μια χρόνια, κνησμός, λαχτάρα να βγάλετε το εργαλείο και να κάνετε όλο το πράγμα μόνοι σας μέσα σε ένα _ for-loop_.

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

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

Το ερώτημα είναι, γιατί ορισμένα εργαλεία δήλωσης είναι πολύ πιο περίπλοκα από ό, τι χρειάζονται; Νομίζω ότι θα ήταν λάθος να το κατηγορήσουμε για κακή σχεδίαση. Μια τέτοια γενική εξήγηση, μια γενική επίθεση ad-hominem στους συγγραφείς αυτών των εργαλείων, δεν είναι δίκαιη. Πρέπει να υπάρχει μια πιο ακριβής και διαφωτιστική εξήγηση.

Ο ισχυρισμός μου είναι ότι κάθε εργαλείο που προσφέρει μια διεπαφή υψηλού επιπέδου για την αφαίρεση ενός κατώτερου επιπέδου πρέπει ξεδιπλωθεί αυτό το υψηλότερο επίπεδο από το χαμηλότερο. Η εννοια του ξεδιπλώνεται προέρχεται από το magnum opus του Christopher Alexander, Η φύση της τάξης - ιδίως τον τόμο II. Είναι (απελπιστικά) πέρα ​​από το πεδίο αυτού του άρθρου (για να μην αναφέρω την κατανόησή μου) να συνοψίσω τις επιπτώσεις αυτού του μνημειακού έργου για το σχεδιασμό λογισμικού. Πιστεύω ότι ο αντίκτυπός του θα είναι τεράστιος στα επόμενα χρόνια. Είναι πέραν αυτού του άρθρου να παρέχει έναν αυστηρό ορισμό των διαδικασιών που ξεδιπλώνονται. Θα χρησιμοποιήσω εδώ την ιδέα σε ένα ευρετικός τρόπος .

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

Αρκετά ενδιαφέρον, Unix είναι ένα εξαιρετικό παράδειγμα για το ξετύλιγμα ενός υψηλότερου επιπέδου από ένα χαμηλότερο. Στο Unix, δύο σύνθετα χαρακτηριστικά του λειτουργικού συστήματος, οι εργασίες δέσμης και οι κορουτίνες (σωλήνες), είναι απλώς επεκτάσεις βασικών εντολών. Λόγω ορισμένων θεμελιωδών αποφάσεων σχεδιασμού, όπως το να κάνουμε τα πάντα σε ροή byte, με το κέλυφος να είναι πρόγραμμα χρηστών και τυπικά αρχεία εισόδου / εξόδου Το Unix είναι σε θέση να παρέχει αυτά τα εξελιγμένα χαρακτηριστικά με ελάχιστη πολυπλοκότητα.

Για να υπογραμμίσω γιατί αυτά είναι εξαιρετικά παραδείγματα ξεδιπλώματος, θα ήθελα να αναφέρω μερικά αποσπάσματα του Έγγραφο του 1979 από τον Dennis Ritchie, έναν από τους συγγραφείς του Unix:

Σε παρτίδες :

… Το νέο σύστημα ελέγχου διεργασιών κατέστησε αμέσως μερικά πολύτιμα χαρακτηριστικά ασήμαντα για εφαρμογή. για παράδειγμα αποσυνδεδεμένες διεργασίες (με &) και αναδρομική χρήση του κελύφους ως εντολή. Τα περισσότερα συστήματα πρέπει να παρέχουν κάποιο είδος ειδικού batch job submission εγκατάσταση και ειδικός διερμηνέας εντολών για αρχεία διαφορετικά από αυτά που χρησιμοποιούνται διαδραστικά.

Στις κορουτίνες :

Η ιδιοφυΐα του αγωγού Unix είναι ακριβώς ότι κατασκευάζεται από τις ίδιες εντολές που χρησιμοποιούνται συνεχώς με απλό τρόπο.

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

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

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

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

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

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

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

πώς να λάβετε στοιχεία πιστωτικής κάρτας στο διαδίκτυο

Εν κατακλείδι; τα δηλωτικά εργαλεία templating υποφέρουν επειδή:

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

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

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

Η δίδυμη προσέγγιση

Για να ξεπεραστούν τα δύο προβλήματα του δηλωτικού προγραμματισμού, τα οποία έχω παρουσιάσει εδώ, προτείνω μια διπλή προσέγγιση:

  • Χρησιμοποιήστε μια γλώσσα συγκεκριμένης περιοχής δομής δεδομένων (dsDSL), για να ξεπεράσετε την χωριστότητα.
  • Δημιουργήστε ένα υψηλό επίπεδο που ξεδιπλώνεται από το χαμηλότερο επίπεδο, για να ξεπεράσετε το κενό πολυπλοκότητας.

dsDSL

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

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

Αν με ρωτούσατε πριν από ένα χρόνο, θα πίστευα ότι η ιδέα του dsDSL ήταν νέα, τότε μια μέρα κατάλαβα ότι JSON το ίδιο ήταν ένα τέλειο παράδειγμα αυτής της προσέγγισης! Ένα αντικείμενο ανάλυσης JSON αποτελείται από δομές δεδομένων που αντιπροσωπεύουν δηλωτικά τις καταχωρίσεις δεδομένων προκειμένου να αποκτήσουν τα πλεονεκτήματα του DSL, ενώ ταυτόχρονα διευκολύνουν την ανάλυση και τον χειρισμό μέσα από μια γλώσσα προγραμματισμού. (Μπορεί να υπάρχουν και άλλα dsDSL εκεί έξω, αλλά μέχρι στιγμής δεν έχω συναντήσει κανένα. Εάν γνωρίζετε ένα, θα εκτιμούσα πραγματικά την αναφορά σας στην ενότητα σχολίων.)

Όπως το JSON, ένα dsDSL έχει τα ακόλουθα χαρακτηριστικά:

  1. Αποτελείται από ένα πολύ μικρό σύνολο λειτουργιών: Το JSON έχει δύο κύριες λειτουργίες, parse και stringify.
  2. Οι λειτουργίες του λαμβάνουν συνήθως πολύπλοκα και αναδρομικά ορίσματα: ένα αναλυμένο JSON είναι ένας πίνακας ή αντικείμενο, το οποίο συνήθως περιέχει περαιτέρω πίνακες και αντικείμενα μέσα.
  3. Οι είσοδοι σε αυτές τις λειτουργίες συμμορφώνονται με πολύ συγκεκριμένες φόρμες: Το JSON έχει ένα ρητό και αυστηρά εφαρμοσμένο σχήμα επικύρωσης για να πει ότι ισχύει από μη έγκυρες δομές.
  4. Τόσο οι είσοδοι όσο και οι έξοδοι αυτών των συναρτήσεων μπορούν να περιέχονται και να δημιουργούνται από μια γλώσσα προγραμματισμού χωρίς ξεχωριστή σύνταξη.

Αλλά τα dsDSL υπερβαίνουν το JSON με πολλούς τρόπους. Ας δημιουργήσουμε ένα dsDSL για τη δημιουργία HTML χρησιμοποιώντας Javascript. Αργότερα θα θίξω το ζήτημα αν αυτή η προσέγγιση μπορεί να επεκταθεί και σε άλλες γλώσσες (spoiler: Μπορεί σίγουρα να γίνει σε Ruby και Python, αλλά πιθανώς όχι σε C).

Το HTML είναι μια γλώσσα σήμανσης που αποτελείται από tags οριοθετείται από αγκύλες γωνίας (< και >). Αυτές οι ετικέτες ενδέχεται να έχουν προαιρετικά χαρακτηριστικά και περιεχόμενο. Τα χαρακτηριστικά είναι απλώς μια λίστα χαρακτηριστικών κλειδιού / τιμής και το περιεχόμενο μπορεί να είναι κείμενο ή άλλες ετικέτες. Τόσο τα χαρακτηριστικά όσο και τα περιεχόμενα είναι προαιρετικά για οποιαδήποτε δεδομένη ετικέτα. Απλοποιώ κάπως, αλλά είναι ακριβές.

Ένας απλός τρόπος αναπαραγωγής μιας ετικέτας HTML σε ένα dsDSL είναι χρησιμοποιώντας έναν πίνακα με τρία στοιχεία: - Ετικέτα: μια συμβολοσειρά. - Χαρακτηριστικά: ένα αντικείμενο (τύπου απλού, κλειδιού / τιμής) ή undefined (εάν δεν είναι απαραίτητα χαρακτηριστικά). - Περιεχόμενα: μια συμβολοσειρά (κείμενο), ένας πίνακας (άλλη ετικέτα) ή undefined (αν δεν υπάρχει περιεχόμενο).

Για παράδειγμα, Index μπορεί να γραφτεί ως ['a', {href: 'views'}, 'Index'].

Εάν θέλουμε να ενσωματώσουμε αυτό το στοιχείο αγκύρωσης σε ένα div με την τάξη links, μπορούμε να γράψουμε: ['div', {class: 'links'}, ['a', {href: 'views'}, 'Index']].

Για να παραθέσουμε πολλές ετικέτες html στο ίδιο επίπεδο, μπορούμε να τις τυλίξουμε σε έναν πίνακα:

[ ['h1', 'Hello!'], ['a', {href: 'views'}, 'Index'] ]

Η ίδια αρχή μπορεί να εφαρμοστεί στη δημιουργία πολλαπλών ετικετών σε μια ετικέτα:

['body', [ ['h1', 'Hello!'], ['a', {href: 'views'}, 'Index'] ]]

Φυσικά, αυτό το dsDSL δεν θα μας φτάσει πολύ αν δεν δημιουργήσουμε HTML από αυτό. Χρειαζόμαστε ένα generate συνάρτηση που θα πάρει το dsDSL μας και θα δώσει μια συμβολοσειρά με HTML. Αν λοιπόν τρέξουμε generate (['a', {href: 'views'}, 'Index']), θα πάρουμε τη συμβολοσειρά Index .

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

Τώρα, ποια είναι τα πλεονεκτήματα ενός dsDSL σε αντίθεση με ένα DSL;

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

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

var DATA = [ {id: 1, description: 'Product 1', price: 20, onSale: true, categories: ['a']}, {id: 2, description: 'Product 2', price: 60, onSale: false, categories: ['b']}, {id: 3, description: 'Product 3', price: 120, onSale: false, categories: ['a', 'c']}, {id: 4, description: 'Product 4', price: 45, onSale: true, categories: ['a', 'b']} ]

Σε πραγματική εφαρμογή, DATA θα δημιουργηθεί δυναμικά από ένα ερώτημα βάσης δεδομένων.

Επιπλέον, έχουμε ένα FILTER μεταβλητή η οποία, όταν αρχικοποιηθεί, θα είναι ένας πίνακας με τις κατηγορίες που θέλουμε να εμφανίσουμε.

Θέλουμε το τραπέζι μας να:

  • Εμφάνιση κεφαλίδων πίνακα.
  • Για κάθε προϊόν, εμφανίστε τα πεδία: περιγραφή, τιμή και κατηγορίες.
  • Μην εκτυπώσετε το id πεδίο, αλλά προσθέστε το ως id χαρακτηριστικό για κάθε σειρά. ΕΝΑΛΛΑΚΤΙΚΗ ΕΚΔΟΣΗ: Προσθέστε ένα id χαρακτηριστικό σε κάθε tr στοιχείο.
  • Τοποθετήστε μια τάξη onSale εάν το προϊόν είναι προς πώληση.
  • Ταξινόμηση προϊόντων με φθίνουσα τιμή.
  • Φιλτράρετε ορισμένα προϊόντα ανά κατηγορία. Εάν FILTER είναι ένας κενός πίνακας, θα εμφανίσουμε όλα τα προϊόντα. Διαφορετικά, θα εμφανίσουμε τα προϊόντα μόνο όπου η κατηγορία του προϊόντος περιλαμβάνεται στο FILTER.

Μπορούμε να δημιουργήσουμε τη λογική παρουσίασης που ταιριάζει με αυτήν την απαίτηση σε ~ 20 γραμμές κώδικα:

function drawTable (DATA, FILTER) { var printableFields = ['description', 'price', 'categories']; DATA.sort (function (a, b) {return a.price - b.price}); return ['table', [ ['tr', dale.do (printableFields, function (field) { return ['th', field]; })], dale.do (DATA, function (product) { var matches = (! FILTER || FILTER.length === 0) || dale.stop (product.categories, true, function (category) { return FILTER.indexOf (category) !== -1; }); return matches === false ? [] : ['tr', { id: product.id, class: product.onSale ? 'onsale' : undefined }, dale.do (printableFields, function (field) { return ['td', product [field]]; })]; }) ]]; }

Παραδέχομαι ότι αυτό δεν είναι ένα απλό παράδειγμα, ωστόσο, αντιπροσωπεύει μια αρκετά απλή άποψη των τεσσάρων βασικών λειτουργιών της μόνιμης αποθήκευσης, επίσης γνωστή ως ΣΚΛΗΡΟΣ . Κάθε μη-ασήμαντη εφαρμογή ιστού θα έχει πιο περίπλοκες προβολές από αυτό.

Ας δούμε τώρα τι κάνει αυτός ο κώδικας. Αρχικά, ορίζει μια συνάρτηση, drawTable, που περιέχει τη λογική παρουσίασης του σχεδιασμού του πίνακα προϊόντων. Αυτή η συνάρτηση λαμβάνει DATA και FILTER ως παράμετροι, ώστε να μπορεί να χρησιμοποιηθεί για διαφορετικά σύνολα δεδομένων και φίλτρα. drawTable εκπληρώνει τον διπλό ρόλο του μερικού και βοηθού.

var drawTable = function (DATA, FILTER) {

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

var printableFields = ['description', 'price', 'categories'];

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

DATA.sort (function (a, b) {return a.price - b.price});

Εδώ επιστρέφουμε ένα κυριολεκτικό αντικείμενο. ένας πίνακας που περιέχει table ως το πρώτο του στοιχείο και το περιεχόμενό του ως το δεύτερο. Αυτή είναι η αναπαράσταση dsDSL του

θέλουμε να δημιουργήσουμε.

return ['table', [

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

['tr', dale.do (printableFields, function (field) { return ['th', field]; })],

Παρατηρήστε ότι μόλις εφαρμόσαμε την επανάληψη, το άλογο εργασίας της δημιουργίας HTML και δεν χρειαζόμασταν κατασκευές DSL. χρειαζόμασταν μόνο μια συνάρτηση για να επαναλάβουμε μια δομή δεδομένων και να επιστρέψουμε dsDSLs. Μια παρόμοια εγγενής, ή λειτουργία που εφαρμόζεται από τον χρήστη, θα έκανε και το τέχνασμα.

Τώρα επαναλάβετε τα προϊόντα που περιέχονται στο DATA.

dale.do (DATA, function (product) {

Ελέγχουμε εάν αυτό το προϊόν έχει παραλειφθεί από FILTER. Εάν FILTER είναι άδειο, θα εκτυπώσουμε το προϊόν. Εάν FILTER δεν είναι κενό, θα επαναλάβουμε τις κατηγορίες του προϊόντος μέχρι να βρούμε ένα που περιέχεται στο FILTER. Το κάνουμε αυτό χρησιμοποιώντας dale.stop .

var matches = (! FILTER || FILTER.length === 0) || dale.stop (product.categories, true, function (category) { return FILTER.indexOf (category) !== -1; });

Παρατηρήστε την πολυπλοκότητα του υπό όρους? είναι ακριβώς προσαρμοσμένο στις απαιτήσεις μας και έχουμε απόλυτη ελευθερία να το εκφράζουμε γιατί είμαστε σε γλώσσα προγραμματισμού και όχι σε DSL.

Εάν matches είναι false, επιστρέφουμε έναν κενό πίνακα (έτσι δεν εκτυπώνουμε αυτό το προϊόν). Διαφορετικά, επιστρέφουμε ένα

με το κατάλληλο αναγνωριστικό και τάξη και επαναλαμβάνουμε μέσω printableFields για να εκτυπώσετε καλά τα πεδία.

return matches === false ? [] : ['tr', { id: product.id, class: product.onSale ? 'onsale' : undefined }, dale.do (printableFields, function (field) { return ['td', product [field]];

Φυσικά κλείνουμε όλα όσα ανοίξαμε. Δεν είναι διασκεδαστικό η σύνταξη;

})]; }) ]]; }

Τώρα, πώς ενσωματώνουμε αυτόν τον πίνακα σε ένα ευρύτερο πλαίσιο; Γράφουμε μια συνάρτηση με την ονομασία drawAll που θα επικαλεστεί όλες τις λειτουργίες που δημιουργούν τις προβολές. Εκτός από το drawTable, ενδέχεται επίσης να έχουμε drawHeader, drawFooter και άλλες συγκρίσιμες λειτουργίες, όλες θα επιστρέψει dsDSLs .

var drawAll = function () { return generate ([ drawHeader (), drawTable (DATA, FILTER), drawFooter () ]); }

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

Για όσους εξακολουθούν να είναι μαζί μου, θα ήθελα να επιστρέψω στον κύριο ισχυρισμό αυτής της ενότητας, δηλαδή ένα dsDSL έχει τα πλεονεκτήματα τόσο του υψηλού όσο και του χαμηλού επιπέδου :

  • ο πλεονέκτημα του χαμηλού επιπέδου διαμένει στον κώδικα γραφής όποτε θέλουμε, βγαίνοντας από το straightjacket του DSL.
  • ο πλεονέκτημα του υψηλού επιπέδου έγκειται στη χρήση γραμματοσειρών που αντιπροσωπεύουν αυτό που θέλουμε να δηλώσουμε και αφήνοντας τις λειτουργίες του εργαλείου να το μετατρέψουν στην επιθυμητή τελική κατάσταση (σε αυτήν την περίπτωση, μια συμβολοσειρά με HTML).

Αλλά πώς είναι αυτό πραγματικά διαφορετικό από τον καθαρά επιτακτικό κώδικα; Νομίζω ότι τελικά η κομψότητα της προσέγγισης dsDSL οφείλεται στο γεγονός ότι Ο κώδικας που γράφεται με αυτόν τον τρόπο αποτελείται κυρίως από εκφράσεις, αντί για δηλώσεις . Πιο συγκεκριμένα, ο κώδικας που χρησιμοποιεί dsDSL αποτελείται σχεδόν εξ ολοκλήρου από:

  • Λογοτεχνίες που αντιστοιχούν σε δομές χαμηλότερου επιπέδου.
  • Λειτουργίες επίκλησης ή λάμδα εντός αυτών των κυριολεκτικών δομών που επιστρέφουν δομές του ίδιου είδους.

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

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

Μπορεί να είναι δυνατή η δημιουργία dsDSL πέραν του Javascript, της One True Language; Νομίζω ότι είναι όντως εφικτό, αρκεί η γλώσσα να υποστηρίζει:

  • Κυριολεκτικά για: πίνακες, αντικείμενα (συσχετιστικοί πίνακες), επίκληση συναρτήσεων και λάμδα.
  • Ανίχνευση τύπου χρόνου εκτέλεσης
  • Πολυμορφισμός και δυναμικοί τύποι επιστροφής

Νομίζω ότι αυτό σημαίνει ότι τα dsDSL μπορούν να χρησιμοποιηθούν σε οποιαδήποτε σύγχρονη δυναμική γλώσσα (δηλαδή: Ruby, Python, Perl, PHP), αλλά πιθανώς όχι σε C ή Java.

Περπατήστε, μετά διαφάνεια: Πώς να ξεδιπλώσετε το υψηλό από το χαμηλό

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

  1. Πάρτε δύο έως τέσσερα προβλήματα που είναι αντιπροσωπευτικές παρουσίες ενός προβληματικού τομέα. Αυτά τα προβλήματα πρέπει να είναι πραγματικά. Το ξετύλιγμα του υψηλού επιπέδου από το χαμηλό είναι ένα πρόβλημα επαγωγής, επομένως χρειάζεστε πραγματικά δεδομένα για να βρείτε αντιπροσωπευτικές λύσεις.
  2. Λύστε τα προβλήματα με κανένα εργαλείο με τον πιο απλό τρόπο.
  3. Σταθείτε πίσω, ρίξτε μια ματιά στις λύσεις σας και παρατηρήστε τα κοινά πρότυπα μεταξύ τους.
  4. Βρείτε τα μοτίβα αναπαράστασης (υψηλό επίπεδο).
  5. Βρείτε τα πρότυπα παραγωγής (χαμηλό επίπεδο).
  6. Λύστε τα ίδια προβλήματα με το επίπεδο υψηλού επιπέδου σας και βεβαιωθείτε ότι οι λύσεις είναι πράγματι σωστές.
  7. Εάν πιστεύετε ότι μπορείτε εύκολα να αντιπροσωπεύσετε όλα τα προβλήματα με τα μοτίβα εκπροσώπησής σας και τα μοτίβα δημιουργίας για καθεμία από αυτές τις περιπτώσεις παράγουν σωστές υλοποιήσεις, τελειώσατε. Διαφορετικά, επιστρέψτε στον πίνακα σχεδίασης.
  8. Εάν εμφανιστούν νέα προβλήματα, επιλύστε τα με το εργαλείο και τροποποιήστε το ανάλογα.
  9. Το εργαλείο θα πρέπει να συγκλίνει ασυμπτωματικά σε τελική κατάσταση, ανεξάρτητα από το πόσα προβλήματα επιλύει. Με άλλα λόγια, η πολυπλοκότητα του εργαλείου θα πρέπει να παραμένει σταθερή, αντί να αυξάνεται με τον αριθμό των προβλημάτων που επιλύει.

Τώρα, τι στο διάολο πρότυπα αναπαράστασης και πρότυπα γενιάς ; Χαίρομαι που ρωτήσατε. Τα μοτίβα αναπαράστασης είναι τα μοτίβα στα οποία θα πρέπει να μπορείτε να εκφράσετε ένα πρόβλημα που ανήκει στον τομέα που αφορά το εργαλείο σας. Είναι ένα αλφάβητο δομών που σας επιτρέπει να γράψετε οποιοδήποτε μοτίβο θέλετε να εκφράσετε εντός του πεδίου εφαρμογής του. Σε ένα DSL, αυτοί θα ήταν οι κανόνες παραγωγής. Ας επιστρέψουμε στο dsDSL μας για τη δημιουργία HTML.

Αναλύοντας ένα απόσπασμα HTML. Η γραμμή

Η ταπεινή ετικέτα HTML είναι ένα καλό παράδειγμα μοτίβων αναπαράστασης. Ας ρίξουμε μια πιο προσεκτική ματιά σε αυτά τα βασικά μοτίβα. Τιτίβισμα

Τα μοτίβα αναπαράστασης για HTML είναι τα ακόλουθα:

  • Μία ετικέτα: ['TAG']
  • Μια μεμονωμένη ετικέτα με χαρακτηριστικά: ['TAG', {attribute1: value1, attribute2: value2, ...}]
  • Μία ετικέτα με περιεχόμενο: ['TAG', 'CONTENTS']
  • Μία ετικέτα με χαρακτηριστικά και περιεχόμενο: ['TAG', {attribute1: value1, ...}, 'CONTENTS']
  • Μία ετικέτα με άλλη ετικέτα μέσα: ['TAG1', ['TAG2', ...]]
  • Μια ομάδα ετικετών (αυτόνομη ή εντός άλλης ετικέτας): [['TAG1', ...], ['TAG2', ...]]
  • Ανάλογα με μια συνθήκη, τοποθετήστε μια ετικέτα ή όχι ετικέτα: condition ? ['TAG', ...] : [] / Ανάλογα με μια συνθήκη, τοποθετήστε ένα χαρακτηριστικό ή κανένα χαρακτηριστικό: ['TAG', {class: condition ? 'someClass': undefined}, ...]

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

Εάν τα μοτίβα αναπαράστασης είναι οι δομές που χρησιμοποιείτε για να εκφράσετε αυτό που θέλετε, τα μοτίβα δημιουργίας είναι οι δομές που θα χρησιμοποιήσει το εργαλείο σας για να μετατρέψετε μοτίβα αναπαράστασης σε δομές χαμηλότερου επιπέδου. Για HTML, αυτά είναι τα εξής:

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

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

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

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

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

Ένα ξεδιπλωμένο εργαλείο δεν θα λύσει μόνο ένα πρόβλημα - αλλά θα σας διαφωτίσει για τη δομή του προβλήματος.

Μην ξεφύγετε λοιπόν από ένα άξιο πρόβλημα. Πρώτα περπατήστε γύρω του και μετά σύρετε το.

Σχετίζεται με:Εισαγωγή στον ταυτόχρονο προγραμματισμό: Ένας οδηγός για αρχάριους

Γράψτε κώδικα για να ξαναγράψετε τον κωδικό σας: jscodeshift

Πίσω Μέρος

Γράψτε κώδικα για να ξαναγράψετε τον κωδικό σας: jscodeshift
Μηχανικός λογισμικού σε δοκιμή, ομάδα διατήρησης πελατών

Μηχανικός λογισμικού σε δοκιμή, ομάδα διατήρησης πελατών

Αλλα

Δημοφιλείς Αναρτήσεις
Πώς να επιλέξετε το καλύτερο πλαίσιο Front-End
Πώς να επιλέξετε το καλύτερο πλαίσιο Front-End
Χρειάζεστε έναν ήρωα: Ο υπεύθυνος έργου
Χρειάζεστε έναν ήρωα: Ο υπεύθυνος έργου
Πώς να βελτιώσετε την απόδοση της εφαρμογής ASP.NET στο Web Farm με προσωρινή αποθήκευση
Πώς να βελτιώσετε την απόδοση της εφαρμογής ASP.NET στο Web Farm με προσωρινή αποθήκευση
Οι δοκιμασμένοι και αληθινοί νόμοι του UX (με Infographic)
Οι δοκιμασμένοι και αληθινοί νόμοι του UX (με Infographic)
Ανώτερος συνεργάτης πελάτη, υγειονομική περίθαλψη και βιοεπιστήμες
Ανώτερος συνεργάτης πελάτη, υγειονομική περίθαλψη και βιοεπιστήμες
 
Η άνοδος των αυτοματοποιημένων συναλλαγών: Μηχανές που εμπορεύονται το S&P 500
Η άνοδος των αυτοματοποιημένων συναλλαγών: Μηχανές που εμπορεύονται το S&P 500
10 πιο κοινές ευπάθειες ασφαλείας στον Ιστό
10 πιο κοινές ευπάθειες ασφαλείας στον Ιστό
Σκέψεις για τη συγκέντρωση του ιδιωτικού σας αμοιβαίου κεφαλαίου
Σκέψεις για τη συγκέντρωση του ιδιωτικού σας αμοιβαίου κεφαλαίου
Διευθυντής έργου και διαχείρισης προϊόντων
Διευθυντής έργου και διαχείρισης προϊόντων
Η σημασία της διατήρησης πελατών - μια εμπειρική μελέτη
Η σημασία της διατήρησης πελατών - μια εμπειρική μελέτη
Δημοφιλείς Αναρτήσεις
  • τι είναι ένας δέκτης sdr
  • πώς να εντοπίσετε διαρροή μνήμης
  • Ρύθμιση απόδοσης βάσης δεδομένων διακομιστή sql
  • πώς να δομήσετε ένα κέρδος
  • ιδιωτικό ταμείο επενδύσεων σε ακίνητα
Κατηγορίες
  • Επιστήμη Δεδομένων Και Βάσεις Δεδομένων
  • Κατανεμημένες Ομάδες
  • Ευκίνητο Ταλέντο
  • Κερδοφορία & Αποδοτικότητα
  • © 2022 | Ολα Τα Δικαιώματα Διατηρούνται

    portaldacalheta.pt