Λοιπόν, στο μεγαλύτερο μέρος της η συζήτηση δεν ασχολείται με επιλογή αρχιτεκτονικής αλλά επιστρέφει συνέχεια στην επιλογή ... data access mechanism! Τα datasets, τα ORM, τα DataObjects (που δεν είναι ORM), όλα αυτά είναι μηχανισμοί data access, όχι αρχιτεκτονικές. Στο σύνολο της εφαρμογής είναι ένα μόνο από τα πράγματα που πρέπει να κοιτάξει κανείς. Τί ανάγκες performance έχω? Τί ανάγκες scalability? Ασφάλειας? Διαθεσιμότητας? Αξιοπιστίας? Προσαρμογής σε αλλαγές των απαιτήσεων? Φιλικότητα και ευχρηστία? Δυνατότητα διαχείρισης? Ποιό από όλα αυτά έχει προτεραιότητα? Πως θα τις καλύψω τις απαιτήσεις? Μήπως το .NET Framework παρέχει ήδη λύσεις για κάποια από αυτά τα θέματα? Υπάρχουν διαθέσιμα έτοιμα components που θα καλύψουν τις ανάγκες μου? Θα πρέπει να φτιάξω κάποια από το μηδέν? Επικοινωνεί η εφαρμογή μου με άλλα συστήματα? Θα έχω μία μόνο εφαρμογή ή φτιάχνω ολόκληρο σύστημα?
Πόσο επηρεάζονται όλα αυτά από το μηχανισμό data acces? Για να μην πω, είναι δυνατόν να καλυφθούν όλες αυτές οι διαφορετικές παράμετροι με ένα και μόνο μηχανισμό data access? Τέλος πάντων, τί με νοιάζει? Εδώ μιλάμε για αρχιτεκτονική ολόκληρης της εφαρμογής, όχι μόνο για το data access!
Και πως επιλέγω τώρα τα διάφορα στοιχεία της αρχιτεκτονικής? Πρώτα απ' όλα θα πρέπει να μπορώ να διακρίνω ότι η εφαρμογή έχει διαφορετικά τμήματα, για το καθένα από τα οποία έχω διαφορετικές επιλογές. Άλλες οι επιλογές που έχω για το UI, άλλες για το data access, άλλες για το busines logic. Επίσης, έχω πράγματα που υπάρχουν σε όλα τα επίπεδα της εφαρμογής. Χρειάζομαι κάποιους μηχανισμούς για logging, για security, για configuration της εφαρμογής.
Στο κάθε τμήμα μετά θα πρέπει να κοιτάξω τί χρειάζομαι και τί επιλογές έχω. Για παράδειγμα στο UI, αν με ενδιαφέρει η ταχύτητα ανάπτυξης και το business logic της εφαρμογής είναι απλό και δεν χρειάζεται να τροποποιείται εύκολα, μπορώ να φτιάξω μια εφαρμογή χρησιμοποιώντας φόρμες και controls. Αν όμως έχω πολλές φόρμες, το business logic είναι στοιχειωδώς περίπλοκο, αν υπάρχουν πολλοί κανόνες για input validation, αν θέλω να εμφανίζω κάποια controls μόνο στους χρήστες που έχουν δικαίωμα, αν δεν θέλω να αλλάζω τις μισές φόρμες αν π.χ. αποφασίσω ότι θέλω ο κωδικός πελάτη να δέχεται μόνο κεφαλαία, θα χρησιμοποιήσω μία αρχιτεκτονική UI όπως το Model View Controller ή το Model View Presenter. Αν το UI μου απαιτεί περίπλοκη λογική, θα χρειαστώ και ένα UI workflow. Από τη στιγμή που αποφασίζω να χρησιμοποιήσω κάποια αρχιτεκτονική, κοιτάζω τί υπάρχει διαθέσιμο. Για παράδειγμα, το Composite UI Application Block υλοποιεί και το MVC και το MVP pattern, ενώ το Smart Client Software Factory περιέχει wizards που δημιουργούν τον περισσότερο κώδικα που χρειάζεται να γράψει κανείς όταν χρησιμοποιεί το CAB.
Μετά? Που πάει το business logic? Αν είναι ελάχιστο, μπορεί να μπει στις φόρμες. Στην συντριπτική πλειοψηφία των περιπτώσεων όμως, το business logic θα πρέπει να υπάρχει κάπου ξεχωριστά. Η απλούστερη λύση είναι ίσως το Transaction Script pattern. Για κάθε σημαντική λειτουργία, (π.χ. πραγματοποίηση κατάθεσης, δημιουργία δανείου ή ασφαλιστηρίου) υπάρχει μία μέθοδος ή μία κλάση που την υλοποιεί πλήρως. Το μειονέκτημα βέβαια, είναι ότι πολλές φορές οι λειτουργίες περιέχουν κοινά κομμάτια τα οποία αναγκαστικά θα αντιγράφονται σε κάθε λειτουργία. Η πιο ευέλικτη λύση είναι η δημιουργία ενός Domain Model. Αναθέτουμε σε κάθε domain object τις λειτουργίες που του αντιστοιχούν και μετά τις συνθέτουμε για να υλοποιήσουμε πιο περίπλοκες λειτουργίες. Η σύνθεση μπορεί να γίνει με κώδικα, σε script ή ακόμα και μέσω workflow. Άλλη μία αρχιτεκτονική επιλογή είναι το Table Module, όπου έχω μία κλάση η οποία αντιστοιχεί σε ένα πίνακα της βάσης και περιέχει και το σχετικό business logic. Το πρόβλημα βέβαια είναι ότι η σχεδίαση της βάσης επηρεάζει άμεσα τη σχεδίαση του κώδικα. Αν η βάση δεν έχει σχετικά απλή δομή, ο κώδικας θα καταλήξει ιδιαίτερα μπερδεμένος. Το πρόβλημα αυτό φαίνεται κυρίως σε περίπλοκες εφαρμογές, όπου την ίδια βάση χρησιμοποιούν διάφορα modules με διαφορετικό τρόπο ενώ το κάθε αντικείμενο θα πρέπει να καλύπτει όλα τα modules. Μία αλλαγή για να εξυπηρετηθεί ένα module μπορεί να προκαλέσει πρόβλημα στα υπόλοιπα.
Και μετά απ' όλα αυτά, φτάνουμε και στο Data Access. Εδώ πρέπει να ξεχωρίσουμε το data access που αφορά το business logic και αυτό που αφορά lookup data, παραμέτρους, reporting. Η επιλογή εδώ εξαρτάται σε πολύ μεγάλο βαθμό από την επιλογή μας για το business logic. Αν χρησιμοποιήσουμε Domain Model, ένα ORM θα είναι η ευκολότερη λύση, καθώς δεν επιβάλλει οι κλάσεις και το σχήμα της βάσης να συμβαδίζουν. Αν θέλουμε το Table Module, μπορούμε να χρησιμοποιήσουμε typed datasets με business μεθόδους στις partial κλάσεις ... αν και αυτό μοιάζει μάλλον με το data access του φτωχού. Καλύτερη λύση είναι οι διάφοροι code generators ή κάποια προϊόντα (που κακώς λέγονται ORM), τα οποία δημιουργούν αντικείμενα από τους πίνακες της βάσης. Το CSLA.NET ανήκει σε αυτή την κατηγορία.
Από την άλλη, όταν διαβάζουμε lookup data, ή δημιουργούμε reports, δεν υπάρχει λόγος να χρησιμοποιήσουμε τους ίδιους μηχανισμούς. Εδώ αρκεί η απευθείας κλήση κάποιων stored procedures ή η χρήση typed datasets για να κάνουμε τη δουλειά μας. Δεν σημαίνει ότι επειδή χρησιμοποιούμε ένα ORM για το domain model μας θα πρέπει να το χρησιμοποιήσουμε και για τα lookup data. Είπαμε, διαφορετικά πράγματα χρειάζονται διαφορετικές λύσεις.
Και μετά έρχεται η σύνδεση μεταξύ των υποσυστημάτων, το deployment σε διάφορους server, η ασφάλεια, κλπ, κλπ, κλπ. Και φυσικά, μπαίνουν και παράγοντες που δεν έχουν να κάνουν με τεχνικές, όπως η απόφαση χρήσης framework ή η δημιουργία νέου από το μηδέν. Μπορεί κάποια εταιρεία να θέλει να περιορίσει την εξάρτηση της από προμηθευτές, ή μπορεί να πάσχει από ανίατη μορφή του συνδρόμου Not-Invented-Here. Ή μπορεί το επίπεδο των προγραμματιστών σε μία εταιρεία να μην είναι πολύ καλό, με αποτέλεσμα να μην μπορεί να εκμεταλλευτεί τις πιο περίπλοκες λύσεις.
Μπορεί τέλος μία εταιρεία να προτιμάει την γρήγορη ανάπτυξη παρά τις ευέλικτες λύσεις. Κλασσικό παράδειγμα είναι οι εφαρμογές που ζητούνται από το IT τμήμα μιας εταιρείας. Είναι προτιμότερη μία κάπως πρόχειρη εφαρμογή που θα μπορεί να χρησιμοποιηθεί σε ένα μήνα, παρά μία καλύτερη που θα είναι έτοιμη σε τρεις ή έξι μήνες. Αντίθετα, σε ένα ISV ή μία εταιρεία που κάνει custom development, είναι προτιμότερο να γίνει σωστά μία εφαρμογή σε έξι μήνες παρά μία πρόχειρη δουλειά σε 2 μήνες, η οποία μετά θα χρειαστεί άλλους έξι μήνες μέχρι να γίνει αποδεκτή από τον πελάτη. (Το ότι πολλές εταιρείες ISV φέρονται σαν να είναι IT τμήματα, είναι άλλη κουβέντα).
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos