Μοντέλο σχεδιασμού καταστημάτων σε Swift

Ένας καθαρός τρόπος αναζήτησης των μοντέλων σας

Τι πρόβλημα επιλύει;

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

Σχεδίαση της σκηνής.

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

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

Αυτό το κομμάτι του κώδικα κάνει

  1. Ένα αίτημα GET στον διακομιστή
  2. Χαρτώνει το επιστρεφόμενο JSON σε μια σειρά αντικειμένων του άρθρου
  3. Το κλείσιμο αποκτάται όταν ολοκληρωθεί όλη η εργασία.

Γιατί χρειαζόμαστε ένα αποθετήριο;

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

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

Δεν έγινε κακό, κανείς δεν πέθανε. Σωστά?

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

Γεια σου αποθήκη.

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

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

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

Χειριστείτε όλες τις αλληλεπιδράσεις αντικειμένων

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

Αυτό κάνει ένα ωραίο API να χρησιμοποιείται σε όλο τον κωδικό σας, χωρίς να χρειάζεται να επαναλαμβάνετε τον ίδιο κωδικό ξανά και ξανά.

Στην πράξη, η χρήση ενός αποθετηρίου θα μοιάζει με αυτό.

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

Ενεργοποίηση: πρωτόκολλα

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

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

Αυτό θα μπορούσε να μοιάζει με αυτό.

Ένα πρωτόκολλο λέει απλώς ότι «εάν συμμορφώνεστε με με, πρέπει να έχετε αυτές τις μεθόδους υπογραφές, αλλά δεν με νοιάζει για την πραγματική εφαρμογή!"

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

Ενεργοποίηση: Δοκιμή μονάδας

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

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

Ενα παράδειγμα

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

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

Ευτυχώς είναι πραγματικά πολύ απλό να το λύσουμε αυτό.

Γεια σας, ένεση εξάρτησης.

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

Αλλά ίσως σκέφτεσαι, τι γίνεται με τους τύπους; Ένα WebArticleRepository δεν είναι ένα MockArticleRepository, οπότε ο μεταγλωττιστής δεν διαμαρτύρεται; Λοιπόν, όχι αν χρησιμοποιείτε το πρωτόκολλο ως τύπο. Με αυτό τον τρόπο αφήσαμε τον μεταγλωττιστή να ξέρει, να επιτρέψει τα πάντα όσο συμμορφώνεται με το πρωτόκολλο ArticleRepository (το οποίο και το Web και το MockArticleRepository κάνουν).

Ο τελικός κώδικας θα μοιάζει με αυτό.

Και στη δοκιμή μονάδας σας θα μπορούσατε να το αλλάξετε έτσι.

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

Super power-up: γενικά

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

  1. πάρτε όλα τα πράγματα
  2. πάρτε μερικά από τα πράγματα
  3. εισάγετε μερικά πράγματα
  4. διαγράψτε το πράγμα
  5. ενημερώστε ένα πράγμα

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

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

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

1. Αποθήκη αρχείων

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

2. Χώρος αποθήκευσης χρηστών

Αυτό είναι.

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