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

Σχεδιάστε μοτίβα που συχνά αποφεύγω: Πρότυπο αποθετηρίου

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

Το επίπεδο πρόσβασης δεδομένων περιέχει τυπικά κώδικα και μεθόδους για την αποθήκευση δεδομένων από και προς την αποθήκευση δεδομένων. Το επίπεδο πρόσβασης δεδομένων που αποσπά το αποθετήριο μπορεί να είναι ένα ORM (δηλαδή, Entity Framework ή NHibernate), αρχείο XML, μια υπηρεσία ιστού κ.λπ. Μπορεί ακόμη και να είναι μια συλλογή από δηλώσεις SQL.

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

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

Το γενικό αποθετήριο

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

Επιτρέψτε μου να το εξηγήσω με ένα παράδειγμα.

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

δημόσιο περιβάλλον εργασίας IRepository

   {

IEnumerable GetAll ();

T GetByID (int id);

άκυρο Προσθήκη (στοιχείο Τ);

άκυρη ενημέρωση (στοιχείο Τ)

άκυρο Διαγραφή (στοιχείο Τ);

   }

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

δημόσια τάξη AuthorRepository: IRepository

   {

// Εφαρμοσμένες μέθοδοι της διεπαφής IRepository

   }

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

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

δημόσια τάξη AuthorRepository: IRepository

   {

ιδιωτικό AuthorContext dbContext;

// Μέθοδοι της διεπαφής IRepository

   }

Όπως μπορείτε να δείτε στην λίστα κωδικών που δόθηκε νωρίτερα, το AuthorRepository χρειάζεται την παρουσία AuthorContext για να εκτελέσει τις λειτουργίες CRUD για τις οποίες προορίζεται. Λοιπόν, πού είναι λοιπόν η αποσύνδεση; Στην ιδανική περίπτωση, το επίπεδο τομέα δεν πρέπει να έχει γνώση της λογικής επιμονής.

Ένα επιπλέον στρώμα αφαίρεσης

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

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

Τώρα που έχετε αρκετές τεχνολογίες ώριμης διατήρησης δεδομένων (NHibernate, Entity Framework, κ.λπ.), γιατί χρειάζεστε αυτό το επιπλέον επίπεδο αφαίρεσης ούτως ή άλλως; Οι περισσότερες από τις ώριμες τεχνολογίες ORM που διατίθενται σήμερα έχουν τις ίδιες δυνατότητες. Προσπαθώντας να χρησιμοποιήσετε ένα αποθετήριο, απλώς προσθέτετε ένα επιπλέον επίπεδο αφαίρεσης χωρίς κανένα λόγο. Για παράδειγμα, μπορεί να χρειαστείτε μεθόδους όπως οι παρακάτω για το AuthorRepository.

FindAuthorById ()

FindAuthorByCountry ()

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