Να 'μαι κι εγώ! Ετοιμαστείτε, για το μακρυνάρι.
Καταρχήν, να βάλουμε τα πράγματα στη θέση τους. Είναι λάθος να πεις ότι η Microsoft ή ο οποιοσδήποτε προτείνει να φτιάξεις μία κλάση στο DAL για κάθε οντότητα, ή το αντίθετο. Πως θα φτιάξεις το DAL, πως θα το παραμετροποιήσεις και πως θα το χρησιμοποιήσεις έχουν να κάνουν κάθε φορά με την εφαρμογή σου. Το ζήτημα έχει δύο (τουλάχιστον) διαστάσεις.
Η μία διάσταση έχει να κάνει με το πως ορίζεις τις κλάσεις σου, και έχει άμεση σχέση με το domain model της εφαρμογής σου. Αν η εφαρμογή είναι αρκετά απλή, μπορεί να μην υπάρχουν καν κλάσεις που να αντιστοιχούν στις οντότητες του domain model. Για παράδειγμα, αν θέλεις να φτιάξεις ένα απλό calculator, δεν υπάρχει λόγος να δημιουργήσεις κλάσεις για πράξεις, συναρτήσεις κλπ.
Σε πιο περίπλοκες εφαρμογές, είναι απαραίτητο να υπάρχουν κλάσεις στο business layer οι οποίες αντιστοιχούν στις οντότητες του domain model. Αν αυτό είναι απλό και αλλάζει σπάνια, η πιο απλή λύση είναι να φτιάξεις μια κλάση στο data layer για κάθε οντότητα. Αυτή είναι και η περίπτωση του Pet shop, όπου το domain model είναι σχετικά απλό (πελάτες, προϊόντα, παραγγελίες κλπ).
Όσο πιο περίπλοκο ή ευμετάβλητο είναι το domain model, τόσο περισσότερο θα πρέπει να ψάξεις για λύσεις που θα επιτρέπουν την παραμετροποίηση. Όσο πιο ευέλικτη είναι όμως η λύση που θα επιλεξεις, τόσο δυσκολότερη θα είναι στην υλοποίηση.
Μία λύση είναι να χρησιμοποιήσεις code generators για να φορτώσεις τα δεδομένα των κλάσεων του business layer από τη βάση. Κάποιοι generators βασίζονται σε απλές παραμέτρους ή attributes, κάποιοι άλλοι μπορούν να δεχτούν το ίδιο το domain model σαν είσοδο και να δημιουργήσουν τον κώδικα που θα συνδέσει τις business κλάσεις με τη βάση, είτε μέσω dynamic sql ή με stored procedures. Κάποιοι μάλιστα μπορούν να δημιουργήσουν τα κατάλληλα stored procedures από το domain model. Το πλεονέκτημα των code generators είναι ότι μπορούν να παράγουν πολύ γρήγορο κώδικα. Το μειονέκτημα είναι ότι όταν αλλάζει το domain model οι generators πρέπει να εκτελεστούν ξανά.
Άλλη λύση είναι οι OR mappers. Στην πιο απλή περίπτωση, ο mapper αντιστοιχεί πεδία της βάσης ή ενός stored procedure σε πεδία μιας business class ή ενός data object. Πιό προχωρημένοι mappers μπορούν να χρησιμοποιήσουν το ίδιο το domain model ή views του domain model. Η διαφορά με τον code generator είναι ότι ο mapper διαβάζει το domain model κάθε φορά που εκτελείται η εφαρμογή. Το αποτέλεσμα είναι ότι είναι πολύ ευκολότερο να τροποποιήσει κανείς το domain model. Το μειονέκτημα είναι ότι πρέπει να εκτελεστεί κώδικας για διαβαστεί το domain model κάθε φορά.
Μπορεί να πετύχει κανείς ακόμα μεγαλύτερη ευελιξία όταν και τα business objects δημιουργούνται δυναμικά, διαβάζοντας μια περιγραφή του domain model. Το κύριο μειονέκτημα αυτής της λύσης είναι ότι είναι πιο αργή από τις άλλες, αλλά έχει ένα πολύ σημαντικό πλεονέκτημα. Η ανάπτυξη νέων εφαρμογών είναι πολύ ευκολότερη, κάτι που γίνεται πιο σημαντικό όσο πιο περίπλοκο ή ευμετάβλητο είναι το domain model.
Η άλλη διάσταση έχει να κάνει με το πώς και πότε πρέπει να αλλάξει το domain model. Αν είναι απαραίτητο το domain model να αλλάζει χωρίς να σταματήσει το σύστημα, θα πρέπει να χρησιμοποιηθεί μια λύση όπου τα domain models θα δημιουργούνται δυναμικά. Αν οι αλλαγές θα πρέπει να γίνουν στο χώρο του πελάτη αλλά δεν είναι απαραίτητο να συνεχίσει να λειτουργεί το σύστημα, μπορεί να χρησιμοποιηθεί OR mapper που θα διαβάζει το domain model από κάποιο configuration file. Τέλος, η απλούστερη λύση είναι να γίνουν οι αλλαγές πριν ή κατά το compile Και να δημιουργηθεί ένα νέο binary που θα σταλεί στον πελάτη.
Φυσικά υπάρχουν και άλλες διαστάσεις. Τί γίνεται, για παράδειγμα, όταν το business layer βρίσκεται σε άλλο μηχάνημα και η επικοινωνία πρέπει να γίνει μέσω Remoting? Πως υλοποιούνται απαιτήσεις ασφαλείας? Caching?
Σε κάθε περίπτωση, όσο πιο ευέλικτη είναι η τεχνική, τόσο δυσκολότερη θα είναι και η ανάπτυξή της. Οι πιο γνωστοί code generators και mappers έχουν χρόνια ανάπτυξης από πίσω τους, ενώ έχουν και έτοιμα εργαλεία διαχείρισης. Γι αυτό και είναι προτιμότερο να χρησιμοποιήσεις έτοιμους code generators ή mappers, γιατί διαφορετικά θα ξοδέψεις πολύ σημαντικό χρόνο για να καταφέρεις να φτιάξεις ένα εφάμιλλο mapper. Αν βρεις ένα mapper που καλύπτει τις ανάγκες σου είναι προτιμότερο να τον χρησιμοποιήσεις παρά να προσπαθήσεις να δημιουργήσεις ένα νέο από το μηδέν. Μπορεί να φαίνεται εύκολο, αλλά ειδικά η δημιουργία των εργαλείων μπορεί να πάρει πολύ χρόνο.
Σαν συμπέρασμα, αν δεν θεωρείς ότι η δημιουργία ενός mapper θα σου δώσει ένα ισχυρό σε σχέση με ανταγωνιστικά προϊόντα, καλύτερα να χρησιμοποιήσεις ένα έτοιμο.
Προτείνω τέλος να διαβάσεις το "Patterns of Enterprise Application Architecture" του Martin Fowler (ISBN 0321127420) όπου περιγράφει τόσο τα θέματα domain modelling, mapping όσο και concurrency.
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos