Βέλτιστες πρακτικές για μια καθαρή και αποτελεσματική γωνιακή εφαρμογή

Έχω εργαστεί σε μια μεγάλη κλίμακα γωνιακή εφαρμογή στο Trade Me, Νέα Ζηλανδία εδώ και δύο χρόνια. Τα τελευταία χρόνια, η ομάδα μας έχει βελτιώσει την εφαρμογή μας τόσο όσον αφορά τα πρότυπα κωδικοποίησης όσο και τις επιδόσεις, ώστε να είναι στην καλύτερη δυνατή κατάσταση.

Αυτό το άρθρο περιγράφει τις πρακτικές που χρησιμοποιούμε στην αίτησή μας και σχετίζεται με τα Γλώσσα, Τύπος, RxJ και @ ngrx / κατάστημα. Θα ακολουθήσουμε επίσης κάποιες γενικές κατευθυντήριες οδηγίες για την κωδικοποίηση για να βοηθήσουμε στην καθαριότητα της εφαρμογής.

1) trackBy

Όταν χρησιμοποιείτε το ngFor για να βγείτε πάνω σε έναν πίνακα σε πρότυπα, χρησιμοποιήστε το με μια λειτουργία trackBy, η οποία θα επιστρέψει ένα μοναδικό αναγνωριστικό για κάθε στοιχείο.

Γιατί;

Όταν αλλάζει ένας πίνακας, η γωνιακή μετασχηματίζει όλο το δέντρο DOM. Αλλά εάν χρησιμοποιείτε το trackBy, το Angular θα ξέρει ποιο στοιχείο έχει αλλάξει και θα κάνει μόνο αλλαγές στο DOM για το συγκεκριμένο στοιχείο.

Για μια λεπτομερή εξήγηση σχετικά, ανατρέξτε σε αυτό το άρθρο του Netanel Basal.

Πριν

  • {{item}}
  • Μετά

    // στο πρότυπο
  • {{item}}
  • // στο στοιχείο
    trackByFn (ευρετήριο, στοιχείο) {
       επιστροφή στοιχείου. // unique id που αντιστοιχεί στο στοιχείο
    }}

    2) const vs let

    Όταν δηλώνετε μεταβλητές, χρησιμοποιήστε το const όταν η τιμή δεν πρόκειται να ανατεθεί.

    Γιατί;

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

    Πριν

    αφήστε το αυτοκίνητο = 'γελοίο αυτοκίνητο'.
    ας myCar = `My $ {car} ';
    ας σας car = `σας $ {αυτοκίνητο}?
    αν (iHaveMoreThanOneCar) {
       myCar = `$ {myCar} s`;
    }}
    αν (youHaveMoreThanOneCar) {
       yourCar = `$ {youCar} s`;
    }}

    Μετά

    // η αξία του αυτοκινήτου δεν ανακατανέμεται, οπότε μπορούμε να το καταστήσουμε σταθερό
    const αυτοκίνητο = 'γελοίο αυτοκίνητο'?
    ας myCar = `My $ {car} ';
    ας σας car = `σας $ {αυτοκίνητο}?
    αν (iHaveMoreThanOneCar) {
       myCar = `$ {myCar} s`;
    }}
    αν (youHaveMoreThanOneCar) {
       yourCar = `$ {youCar} s`;
    }}

    3) Κινητήρες χειριστές

    Χρησιμοποιήστε χειριστές με δυνατότητα σύνδεσης όταν χρησιμοποιείτε χειριστές RxJs.

    Γιατί;

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

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

    Σημείωση: Αυτό χρειάζεται γωνιακή έκδοση 5.5+.

    Πριν

    εισαγωγή 'rxjs / add / operator / map'.
    εισαγωγή 'rxjs / add / operator / take'.
    iAmAnObservable
        .map (τιμή => value.item)
        .take (1);

    Μετά

    εισαγωγή {map, take} από "rxjs / operators";
    iAmAnObservable
        .σωλήνας(
           χάρτη (value => value.item),
           πάρτε (1)
         ) ·

    4) Απομονώστε τα hacks της API

    Δεν είναι όλα τα APIs proof bullet - μερικές φορές πρέπει να προσθέσουμε κάποια λογική στον κώδικα για να αναπληρώσουμε τα σφάλματα στα API. Αντί να έχετε τα hacks σε εξαρτήματα όπου χρειάζονται, είναι καλύτερο να τα απομονώσετε σε ένα μέρος - όπως σε μια υπηρεσία και να χρησιμοποιήσετε την υπηρεσία από το στοιχείο.

    Γιατί;

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

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

    5) Εγγραφείτε στο πρότυπο

    Αποφύγετε την εγγραφή σε παρατηρητές από τα εξαρτήματα και αντ 'αυτού εγγραφείτε στα παρατηρήσιμα από το πρότυπο.

    Γιατί;

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

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

    Πριν

    // πρότυπο

    {{textToDisplay}}

    // συστατικό
    iAmAnObservable
        .σωλήνας(
           χάρτη (value => value.item),
           takeUntil (this._destroyed $)
         )
        .subscribe (στοιχείο => this.textToDisplay = στοιχείο);

    Μετά

    // πρότυπο

    {{textToDisplay $ | async}}

    // συστατικό
    this.textToDisplay $ = iAmAnObservable
        .σωλήνας(
           χάρτη (τιμή => value.item)
         ) ·

    6) Καθαρίστε συνδρομές

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

    Γιατί;

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

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

    Πριν

    iAmAnObservable
        .σωλήνας(
           χάρτη (τιμή => value.item)
         )
        .subscribe (στοιχείο => this.textToDisplay = στοιχείο);

    Μετά

    Χρησιμοποιώντας το takeUntil όταν θέλετε να ακούσετε τις αλλαγές έως ότου ένα άλλο παρατηρήσιμο εκπέμψει μια τιμή:

    private _destroyed $ = νέο θέμα ();
    δημόσιο ngOnInit (): void {
        iAmAnObservable
        .σωλήνας(
           χάρτη (τιμή => value.item)
          // Θέλουμε να ακούσουμε το iAmAnObservable μέχρι να καταστραφεί το στοιχείο,
           takeUntil (this._destroyed $)
         )
        .subscribe (στοιχείο => this.textToDisplay = στοιχείο);
    }}
    δημόσια ngOnDestroy (): void {
        this._destroyed $ .next ();
        this.distroyed $ .complete ();
    }}

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

    Χρησιμοποιώντας τη λήψη όταν θέλετε μόνο την πρώτη τιμή που εκπέμπεται από το παρατηρήσιμο:

    iAmAnObservable
        .σωλήνας(
           χάρτη (value => value.item),
           πάρτε (1),
           takeUntil (this._destroyed $)
        )
        .subscribe (στοιχείο => this.textToDisplay = στοιχείο);

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

    7) Χρησιμοποιήστε κατάλληλους χειριστές

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

    switchMap: όταν θέλετε να αγνοήσετε τις προηγούμενες εκπομπές όταν υπάρχει νέα εκπομπή

    mergeMap: όταν θέλετε να χειριστείτε ταυτόχρονα όλες τις εκπομπές

    concatMap: όταν θέλετε να χειρίζεστε τις εκπομπές το ένα μετά το άλλο καθώς εκπέμπονται

    exhaustMap: όταν θέλετε να ακυρώσετε όλες τις νέες εκπομπές ενώ επεξεργάζεστε μια προηγούμενη εκπομπή

    Για μια πιο λεπτομερή εξήγηση σχετικά με αυτό, ανατρέξτε σε αυτό το άρθρο του Nicholas Jamieson.

    Γιατί;

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

    8) Λιγότερο φορτίο

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

    Γιατί;

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

    Πριν

    // app.routing.ts
    {path: 'όχι-τεμπέλης-φορτωμένο', συστατικό: NotLazyLoadedComponent}

    Μετά

    // app.routing.ts
    {
      διαδρομή: «τεμπέλης»,
      loadChildren: 'Lazy-load.module # LazyLoadModule'
    }}
    // lazy-load.module.ts
    εισαγωγή {NgModule} από '@ γωνιακό / πυρήνα'.
    εισαγωγή {CommonModule} από '@ γωνιακό / κοινό'.
    εισαγωγή {RouterModule} από το '@ γωνιακό / δρομολογητή'.
    εισαγάγετε {LazyLoadComponent} από το "./lazy-load.component".
    @NgModule ({
      εισαγωγές: [
        CommonModule,
        RouterModule.forChild ([
             {
                 διαδρομή: '',
                 συστατικό στοιχείο: LazyLoadComponent
             }}
        ])
      ],
      δηλώσεις: [
        LazyLoadComponent
      ]
    })
    εξαγωγική κλάση LazyModule {}

    9) Αποφύγετε να έχετε συνδρομές εντός συνδρομών

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

    Πριν

    πρώτοςΕξαιρετικός $ .pipe (
       πάρτε (1)
    )
    .subscribe (firstValue => {
        δευτερόλεπτα
            πάρτε (1)
        )
        .subscribe (secondValue => {
            console.log (`Οι συνδυασμένες τιμές είναι: $ {firstValue} & $ {secondValue} ');
        });
    });

    Μετά

    πρώτοςΕξαιρετικός $ .pipe (
        μεLatestFrom (secondObservible $),
        πρώτα()
    )
    .subscribe ((([firstValue, secondValue]) => {
        console.log (`Οι συνδυασμένες τιμές είναι: $ {firstValue} & $ {secondValue} ');
    });

    Γιατί;

    Κώδικας οσμή / αναγνώσιμη / πολυπλοκότητα: Δεν χρησιμοποιεί RxJs στο πλήρες μέγεθός της, υποδηλώνει ότι ο προγραμματιστής δεν είναι εξοικειωμένος με την περιοχή επιφάνειας API RxJs.

    Απόδοση: Εάν τα παρατηρητικά είναι κρύα, θα εγγραφεί στο firstObservable, περιμένετε να ολοκληρωθεί, ΑΚΟΜΑ ξεκινήσει το έργο του δεύτερου παρατηρητή. Εάν αυτές ήταν αιτήσεις δικτύου, θα εμφανίζονταν ως σύγχρονοι / καταρράκτες.

    10) Αποφύγετε οποιοδήποτε. πληκτρολογήστε τα πάντα.

    Πάντα να δηλώνετε μεταβλητές ή σταθερές με έναν τύπο διαφορετικό από οποιοδήποτε.

    Γιατί;

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

    const x = 1.
    const y = 'a';
    const z = x + y;
    console.log (`Η τιμή του z είναι: $ {z} '
    // Έξοδος
    Η τιμή του z είναι 1α

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

    const x: αριθμός = 1;
    const y: αριθμός = 'a';
    const z: αριθμός = x + y;
    // Αυτό θα δώσει ένα σφάλμα compile λέγοντας:
    Πληκτρολογήστε '' a '' δεν είναι δυνατόν να πληκτρολογήσετε τον αριθμό '.
    const y: αριθμός

    Με αυτόν τον τρόπο, μπορούμε να αποφύγουμε τα σφάλματα που προκαλούνται από τους τύπους που λείπουν.

    Ένα άλλο πλεονέκτημα του να έχετε καλές πληκτρολογήσεις στην αίτησή σας είναι ότι κάνει το refactoring ευκολότερο και ασφαλέστερο.

    Εξετάστε αυτό το παράδειγμα:

    δημόσιο ngOnInit (): void {
        let myFlashObject = {
            όνομα: "Το δροσερό μου όνομα",
            ηλικία: "Η ψυχή μου",
            loc: 'Η δροσερή μου θέση'
        }}
        αυτό.processObject (myFlashObject);
    }}
    δημόσια διαδικασίαObject (myObject: any): void {
        console.log (`Όνομα: $ {myObject.name} ');
        console.log (`Ηλικία: $ {myObject.age} ');
        console.log (`Τοποθεσία: $ {myObject.loc}`);
    }}
    // Έξοδος
    Όνομα: Το δροσερό μου όνομα
    Ηλικία: Η καλή μου ηλικία
    Τοποθεσία: Η δροσερή μου θέση

    Ας πούμε, θέλουμε να μετονομάσουμε τον τόπο ιδιότητας σε τοποθεσία στο myFlashObject:

    δημόσιο ngOnInit (): void {
        let myFlashObject = {
            όνομα: "Το δροσερό μου όνομα",
            ηλικία: "Η ψυχή μου",
            τοποθεσία: 'Η δροσερή τοποθεσία μου'
        }}
        αυτό.processObject (myFlashObject);
    }}
    δημόσια διαδικασίαObject (myObject: any): void {
        console.log (`Όνομα: $ {myObject.name} ');
        console.log (`Ηλικία: $ {myObject.age} ');
        console.log (`Τοποθεσία: $ {myObject.loc}`);
    }}
    // Έξοδος
    Όνομα: Το δροσερό μου όνομα
    Ηλικία: Η καλή μου ηλικία
    Τοποθεσία: απροσδιόριστο

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

    Εάν είχαμε μια πληκτρολόγηση για το myFlashObject, θα λάβαμε ένα ωραίο σφάλμα χρόνου μεταγλώττισης όπως φαίνεται παρακάτω:

    πληκτρολογήστε FlashObject = {
        όνομα: συμβολοσειρά,
        ηλικία: συμβολοσειρά,
        τοποθεσία: συμβολοσειρά
    }}
    δημόσιο ngOnInit (): void {
        ας myFlashObject: FlashObject = {
            όνομα: "Το δροσερό μου όνομα",
            ηλικία: "Η ψυχή μου",
            // Σφάλμα σύνταξης
            Πληκτρολογήστε '{name: string; ηλικία: συμβολοσειρά; τόπος: συμβολοσειρά. } 'δεν είναι δυνατό να πληκτρολογήσετε' FlashObjectType '.
            Το αντικειμενικό γράμμα μπορεί να καθορίζει μόνο γνωστές ιδιότητες και το 'loc' δεν υπάρχει στον τύπο 'FlashObjectType'.
            loc: 'Η δροσερή μου θέση'
        }}
        αυτό.processObject (myFlashObject);
    }}
    δημόσια διαδικασίαObject (myObject: FlashObject): void {
        console.log (`Όνομα: $ {myObject.name} ');
        console.log (`Ηλικία: $ {myObject.age} ')
        // Σφάλμα σύνταξης
        Η ιδιότητα 'loc' δεν υπάρχει στον τύπο 'FlashObjectType'.
        console.log (`Τοποθεσία: $ {myObject.loc}`);
    }}

    Αν ξεκινάτε ένα νέο έργο, αξίζει να ορίσετε αυστηρό: true στο αρχείο tsconfig.json για να ενεργοποιήσετε όλες τις αυστηρές επιλογές ελέγχου τύπου.

    11) Χρησιμοποιήστε τους κανόνες των χνούδι

    Το tslint έχει ενσωματωμένες διάφορες επιλογές, όπως οι αριθμοί, οι αριθμοί μαγείας, οι αριθ-κονσόλες κ.λπ. που μπορείτε να διαμορφώσετε στο tslint.json για να επιβάλλετε ορισμένους κανόνες στη βάση του κώδικα.

    Γιατί;

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

    Ορισμένοι κανόνες χνούδι έρχονται ακόμη και με διορθώσεις για την επίλυση του σφάλματος χνούδι. Αν θέλετε να διαμορφώσετε τον δικό σας κανόνα προσαρμοσμένου χνούδι, μπορείτε να το κάνετε και αυτό. Ανατρέξτε σε αυτό το άρθρο του Craig Spence σχετικά με τον τρόπο σύνταξης των δικών σας προσαρμοσμένων κανόνων χνούδις χρησιμοποιώντας το TSQuery.

    Πριν

    δημόσιο ngOnInit (): void {
        console.log ('Είμαι ένα άτακτο μήνυμα καταγραφής κονσόλας');
        console.warn ('Είμαι ένα άσχημο μήνυμα προειδοποίησης κονσόλας');
        console.error ('Είμαι ένα άσχημο μήνυμα σφάλματος κονσόλας');
    }}
    // Έξοδος
    Δεν υπάρχουν σφάλματα, εκτυπώνει τα παρακάτω στο παράθυρο της κονσόλας:
    Είμαι ένα άτακτο μήνυμα κονσόλας
    Είμαι ένα άτακτο μήνυμα προειδοποίησης κονσόλας
    Είμαι άτακτος μήνυμα σφάλματος κονσόλας

    Μετά

    // tslint.json
    {
        "κανόνες": {
            .......
            "χωρίς κονσόλα": [
                 αληθής,
                 "log", // δεν επιτρέπεται η χρήση console.log
                 "προειδοποίηση" // δεν επιτρέπεται η χρήση console.warn
            ]
       }}
    }}
    // ..component.ts
    δημόσιο ngOnInit (): void {
        console.log ('Είμαι ένα άτακτο μήνυμα καταγραφής κονσόλας');
        console.warn ('Είμαι ένα άσχημο μήνυμα προειδοποίησης κονσόλας');
        console.error ('Είμαι ένα άσχημο μήνυμα σφάλματος κονσόλας');
    }}
    // Έξοδος
    Σφάλματα Lint για τις εντολές console.log και console.warn και κανένα λάθος για το console.error καθώς δεν αναφέρεται στο config
    Οι κλήσεις στο 'console.log' δεν επιτρέπονται.
    Οι κλήσεις στο 'console.warn' δεν επιτρέπονται.

    12) Μικρά επαναχρησιμοποιήσιμα εξαρτήματα

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

    Κατά γενικό κανόνα, το τελευταίο παιδί στο δομικό στοιχείο θα είναι ο πιο χαζός από όλους.

    Γιατί;

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

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

    13) Τα στοιχεία θα πρέπει να ασχολούνται μόνο με τη λογική της οθόνης

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

    Γιατί;

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

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

    14) Αποφύγετε μεγάλες μεθόδους

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

    Γιατί;

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

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

    15) ΞΗΡΑ

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

    Γιατί;

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

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

    16) Προσθέστε μηχανισμούς προσωρινής αποθήκευσης

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

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

    Γιατί;

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

    17) Αποφύγετε τη λογική στα πρότυπα

    Αν έχετε κάποια λογική στα πρότυπά σας, ακόμα κι αν είναι μια απλή && ρήτρα, είναι καλό να το εξαγάγετε στη συνιστώσα του.

    Γιατί;

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

    Πριν

    // πρότυπο
    

    Κατάσταση: Προγραμματιστής

    // συστατικό
    δημόσιο ngOnInit (): void {
        this.role = 'προγραμματιστής';
    }}

    Μετά

    // πρότυπο
    

    Κατάσταση: προγραμματιστής

    // συστατικό
    δημόσιο ngOnInit (): void {
        this.role = 'προγραμματιστής';
        this.showDeveloperStatus = true;
    }}

    18) Οι χορδές πρέπει να είναι ασφαλείς

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

    Γιατί;

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

    Πριν

    ιδιωτική myStringValue: συμβολοσειρά;
    αν (itShouldHaveFirstValue) {
       myStringValue = 'Πρώτη';
    } else {
       myStringValue = 'Δεύτερο'
    }}

    Μετά

    ιδιωτική myStringValue: 'Πρώτη' | 'Δεύτερος';
    αν (itShouldHaveFirstValue) {
       myStringValue = 'Πρώτη';
    } else {
       myStringValue = 'Άλλο'
    }}
    // Αυτό θα δώσει το παρακάτω σφάλμα
    Πληκτρολογήστε "Άλλο" "δεν είναι δυνατόν να πληκτρολογήσετε" First "| "Δεύτερος"'
    (ιδιοκτησία) AppComponent.myValue: "Πρώτη" "Δεύτερος"

    Μεγαλύτερη εικόνα

    Κρατική διαχείριση

    Εξετάστε τη χρήση του @ ngrx / store για τη διατήρηση της κατάστασης της εφαρμογής σας και των @ ngrx / effects ως μοντέλου παρενέργειας για αποθήκευση. Οι κρατικές αλλαγές περιγράφονται από τις ενέργειες και οι αλλαγές γίνονται με καθαρές λειτουργίες που ονομάζονται μειωτήρες.

    Γιατί;

    @ ngrx / store απομονώνει όλη τη λογική που σχετίζεται με το κράτος σε ένα μέρος και την καθιστά συνεπή σε όλη την εφαρμογή. Διαθέτει επίσης μηχανισμό απομνημόνευσης κατά την πρόσβαση στις πληροφορίες του καταστήματος, γεγονός που οδηγεί σε πιο αποτελεσματική εφαρμογή. @ ngrx / store σε συνδυασμό με τη στρατηγική ανίχνευσης αλλαγών του Angular οδηγεί σε ταχύτερη εφαρμογή.

    Μεταβλητή κατάσταση

    Όταν χρησιμοποιείτε το @ ngrx / store, μπορείτε να χρησιμοποιήσετε το ngrx-store-freeze για να κάνετε την κατάσταση αμετάβλητη. Το ngrx-store-freeze εμποδίζει την κατάσταση να μεταλλαχθεί με ρίχνοντας μια εξαίρεση. Αυτό αποτρέπει την τυχαία μετάλλαξη του κράτους που οδηγεί σε ανεπιθύμητες συνέπειες.

    Γιατί;

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

    Αστείο

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

    Θα μπορούσατε να χρησιμοποιήσετε μια προκαθορισμένη ρύθμιση για το Jest που θα κάνει το μεγαλύτερο μέρος της βαριάς ανύψωσης για εσάς κατά την εγκατάσταση του Jest στο έργο σας.

    Κάρμα

    Το Karma είναι δοκιμαστής που αναπτύχθηκε από την ομάδα του AngularJS. Απαιτεί ένα πραγματικό πρόγραμμα περιήγησης / DOM για να εκτελέσει τις δοκιμές. Μπορεί επίσης να εκτελείται σε διαφορετικά προγράμματα περιήγησης. Το Jest δεν χρειάζεται χρώμιο χωρίς κεφαλή / phantomjs για να εκτελέσει τις δοκιμές και τρέχει σε καθαρό Κόμβο.

    Παγκόσμιος

    Εάν δεν έχετε κάνει την εφαρμογή σας μια εφαρμογή Universal, τώρα είναι μια καλή στιγμή για να το κάνετε. Το Angular Universal σας επιτρέπει να εκτελείτε τη γωνιακή εφαρμογή σας στο διακομιστή και εκτελεί rendering από την πλευρά του διακομιστή (SSR), η οποία εξυπηρετεί στατικές προκατασκευασμένες σελίδες html. Αυτό καθιστά την εφαρμογή εξαιρετικά γρήγορη, καθώς εμφανίζει το περιεχόμενο στην οθόνη σχεδόν στιγμιαία, χωρίς να χρειάζεται να περιμένετε να φορτωθούν και να αναλυθούν οι δέσμες JS ή για το γωνιακό για εκκίνηση.

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

    Γιατί;

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

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

    συμπέρασμα

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

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