[Μαθαίνοντας Design Patterns] Model – View – ViewModel

Συνεχίζοντας τη σειρά με τα design patterns, σε αυτό το post γίνεται μία αναφορά στο MVVM, μέσα από μία αρκετά απλοϊκή προσέγγιση. Θα περιγραφεί το pattern, θα δωθούν μερικές base classes, ένα utility για το πώς γίνεται type-safely raise ένα event για ανανέωση UI, καθώς και ένα μικρό παράδειγμα, με Bing Maps σε μία Silverlight εφαρμογή.

Τί είναι το MVVM;

Το Model – View – ViewModel είναι ένα πρότυπο σχεδίασης για το σχεδιασμό διεπαφών χρήστη, το οποίο έχει επηρροές τόσο από το Model View Presenter, όσο και από το Model View Controller. Είναι γνωστό  και ως Presentation Model (σχεδόν ίδιο)(PM στο εξής), όπως το έχει καταγράψει ο Martin Fowler. To Model – View – ViewModel (MVVM στο εξής) είναι επίσης ένας καθιερωμένος τρόπος, για τη δημιουργία εφαρμογών που βασίζονται και σε XAML και επιλέχθηκε για την ευελιξία που παρέχει στον προγραμματιστή κατά την ανάπτυξη (decoupling View-Model). Το design pattern που περιγράφεται στη συνέχεια με τη βοήθεια του παραδείγματος σε silverlight, παρουσιάζεται έχοντας κατα νου το ισχυρό πλαίσιο databinding του silverlight (η αντιστοιχία στοιχείου οθόνης με κανονικό Property ενός object).

Ξεκινώντας την περιγραφή του MVVM, αναφέρουμε ότι παρέχει (όπως και το PM) ένα επίπεδο αφαίρεσης του View (της εικόνας δηλαδή που φαίνεται στον χρήστη / XAML) στο οποίο ορίζεται τόσο η κατάστασή του, όσο και η συμπεριφορά του. Έστω ότι έχουμε την οθόνη διαχείρισης καταστημάτων μίας εταιρίας πώλησης παπουτσιών. Υπάρχουν δύο εκδόσεις για την εν λόγω οθόνη, μία που παρουσιάζει όλα τα καταστήματα (datagrid με μία λίστα) και μία που ενεργοποιείται όταν αλλάζουμε ιδιότητες από κάποιο κατάστημα (αρκετά controls, όπως textboxes κτλ με τα οποία μπορούμε να καταχωρούμε πληροφορίες για ένα selected store από την προηγούμενη σελίδα). Οι δύο οθόνες λέγονται αντίστοιχα Master και Detail σελίδες. Έστω ότι έχουμε την Detail σελίδα να αναπτύξουμε. Στη συνέχεια περιγράφεται πώς το MVVM μπορεί να διαχωρίσει τις αρμοδιότητες, για διαφορετικές ενέργειες που λαμβάνουν χώρα πίσω από την οθόνη.

Τα τρία στοιχεία που περιγράφονται είναι τρία διαφορετικά αντικείμενα στη μνήμη και έχουν πεδία και μεθόδους. Έτσι λοιπόν έχουμε το View (τονίζω πάλι ότι αναφερόμαστε σε XAML αρχείο) το οποίο περιέχει διάφορα controls με τα οποία μπορεί να αλληλεπιδράσει ο χρήστης. Κάθε control που περιέχεται, μπορεί να εμφανίσει πληροφορία είτε σε μορφή κειμένου είτε σε κάτι πιο πολυμεσικό.

Έστω ότι έχουμε ένα πεδίο κειμένου (textboxes) και έναν επιλογέα με μία μοναδική επιλογή κάθε φορά (combobox). Τα δύο αυτά controls, δένουν τις τιμές τους με ιδιότητες (properties) του ViewModel μέσω μηχανισμού databinding. Προγραμματιστικά το databinding ανάμεσα στο View και στο ViewModel (που περιέχει όλη την πληροφορία που δείχνει/ανανεώνει/… το View) γίνεται πάρα πολύ εύκολα, μιας και θέτουμε το ViewModel αντικείμενο, ως το πλαίσιο δεδομένων (datacontext) του View (βλ. παράδειγμα). Αν κάποια τιμή, σε κάποιο property αλλάξει, τότε η ίδια ιδιότητα ενεργοποιεί ένα γεγονός (κάνει raise ένα event propertychanged) που υποδηλώνει ότι άλλαξε τιμή και έτσι ενημερώνει το View ότι άλλαξε η τιμή για το συγκριμένο user control (για παράδειγμα ένα textbox – πεδίο εισαγωγής κειμένου). Κάθε πληροφορία δηλαδή, που είναι databound με ένα control όταν αλλάξει, ενημερώνει το UI ότι άλλαξε και ότι θα πρέπει να ανανεωθεί. Για να μπορεί ένα αντικείμενο (το ViewModel στην περίπτωσή μας) να αλληλεπιδρά με αυτόν τον τρόπο θα πρέπει να υλοποιεί το INotifyPropertyChanged interface. Έτσι λοιπόν ανανεώνεται και η αντίστοιχη πληροφορία στον χρήστη. Σε αντίθετη περίπτωση, όταν ένας χρήστης πατήσει ένα κουμπί, μία εντολή (Commanding) θα εκτελεστεί στο ViewModel και θα πραγματοποιήσει όλες τις αλλαγές στα δεδομένα του μοντέλου (τα οποία περιέχονται στο ίδιο το αντικείμενο του ViewModel).

To Model είναι το αντικείμενο το οποίο καλείται από το ViewModel για λειτουργίες πρόσβασης στα δεδομένα. Στην περίπτωσή μας έχουμε δομικές μονάδες που περιγράφουν το πεδίο της εφαρμογής (customers, orders, κτλ). Αξίζει να κρατήσουμε τρία πράγματα: image

 

  • To View ΔΕΝ γνωρίζει το Model (γιατί δεν απαιτείται κάτι τέτοιο εννοιολογικά)
  • To ViewModel ΔΕΝ γνωρίζει τίποτα για View (εξαρτάται, ίσως είναι θέμα προθέσεων του προγραμματιστή)
  • To Model ΔΕΝ γνωρίζει τίποτα για View

Στις XAML εφαρμογές, το View είναι η οθόνη που σχεδιάζουμε στο Expression Blend (την εφαρμογή της Microsoft για σχεδιασμό σελίδων), το ViewModel αναπτύσσεται στο Visual Studio και το Model είναι στην ουσία οι κλάσεις που χρησιμοποιούμε για το πεδίο της εφαρμογής μας οι οποίες περιέχουν όλες τις ιδιότητες οι οποίες υπάρχουν στο αντικείμενο. Στις RIA εφαρμογές το κανονικό μοντέλο υπάρχει στον server και μία πιο μινιμαλιστική έκδοση στον client, για να μπορεί να διαχειρίζεται τα αντικείμενα. Για παράδειγμα στην σελίδα με την επεξεργασία ενός στιγμιότυπου της οντότητας Shoe (π.χ. για rowId = 5) το ViewModel έχει ως ένα από τα πεδία του, ένα αντικείμενο τύπου shoe, το οποίο δηλώνεται στο Model. To Model, έχει στον server την κανονική έκδοση της οντότητας Shoe, ορίζοντας πρόσθετες ιδιότητες αν είναι απαραίτητο (που δεν εμφανίζονται στον client).

Στις ακόλουθες ιεραρχίες μπορούμε να δούμε την κλάση ViewControl που είναι στην ουσία η οθόνη μας, που γνωρίζει το ViewModel και το έχει θέσει ως το Data Context της. Υπάρχει ένα κάπως well defined API μέσα από generic type constraints.

 

Base Classes

Έστω η περίπτωση που έχω controls που στέλνουν εντολές, buttons, κλπ κλπ. Θα πρέπει να υπάρχει μία δομή στο XAML, που θα δηλώνει το πια εντολή είναι αυτή που θα πρέπει να εκτελεστεί όταν πατηθεί το κουμπί. Στην περίπτωση του code behind μπορούμε να παίξουμε με handlers αλλά με MVVM μπορώ να έχω μία διαφορετική προσέγγιση. Γιατί να μη εκμεταλλευτώ το μοντέλο του MVVM και να “βρωμίσω” το code behind μου με κώδικα hard-wired με το View? Έτσι λοιπόν ένα σημείο κλειδί είναι να χρησιμοποιήσουμε Commands. Στο WPF υπάρχουν πραγματικά commands που σε συνδυασμό με τα routed events δημιουργούν την έννοια του routed command, αλλά δεν θα μιλήσουμε εδώ γι’ αυτό. Στο Silverlight (3) υπάρχει το ICommand interface το οποίο είναι στην ουσία το εξής, και θα αναλύσουμε σε κάποια άλλη συζήτηση για το commanding σε MVVM:

 

Bing Maps MVVM

Στο συγκεκριμένο παράδειγμα παραθέτω το ViewModel μίας οθόνης που έχει ένα Bing Maps control. Θέλω σε αυτόν το χάρτη, να παρουσιάσω καταστήματα που έχουν χωρική πληροφορία και θα εμφανιστούν στον χάρτη μας. Τι χρειάζομαι ως business πληροφορία; Ένα collection από καταστήματα (τύπου ObservableCollection που μπορεί να ενημερώνει όταν επιδέχεται αλλαγές) και ίσως ένα SelectedStore για να γνωρίζω πιο store έχει επιλεγχθεί (για απεικόνιση περισσότερων πληροφοριών).

Αναφορικά με το όμορφο API για το raising των property changed events, προκειμένου να γράφουμε κάτι του στυλ Raise(“PropertyName”), θεωρώ πιο όμορφo να χρησιμοποιήσω έναν type safe τρόπο με lambda που na παρέχει το property name, αντί να γράφω κάτι error prone όπως το όνομα του property με το χέρι. (Credits to original author)

Bing Maps View

To View μας που περιέχει το bing maps control, είναι ένα μάθημα για databinding με XAML, templating κτλ από μόνο του, αλλά ήθελα να το δείξω εδώ για πληρότητα. Παρατηρήστε πόσο εύκολα και κατανοητά δηλώνω το που αντλώ πληροφορία για τα pushpins (Stores collection) και πιό member διαλέγω για να ανακτήσω την πληροφορία (LocationInformation).

 

Ελπίζω να έδωσα αρκετό food for thought. Enjoy Silverlight & MVVM!!!

Share/Bookmark

Closures στη C#

Τελικά τα closures είναι ένα απλό concept, που όταν το κατανοήσει κάποιος, το βλέπει τετριμμένο μετά. Αν μπορούσα να δανειστώ από κάπου, δυό λόγια για ορισμό, νομίζω η wikipedia το περιγράφει αρκετά καλά. Τα closures είναι μία ιδέα των γλωσσών προγραμματισμού, που επιτρέπει, σε συναρτήσεις που αντιμετωπίζονται ως first-class objects, τον συσχετισμό ελεύθερων μεταβλητών τους, με τον λεκτικό περιβάλλοντα χώρο της συνάρτησης. Στη συνέχεια θα ήθελα να διατυπώσω το εν λόγω concept όσο πιο σύντομα γίνεται, δανειζόμενος (μερικώς ή πλήρως) κώδικα από το βιβλίο C# in Depth του Jon Skeet και από το Reference της C#.

First – class functions στην C#

First class functions είναι συναρτήσεις που έχουν όλες τις ιδιότητες των αντικειμένων, μπορούν να δημιουργηθούν δυναμικά, μπορούν να συμμετέχουν σε δομές δεδομένων, να ανατεθούν ως παράμετροι, καθώς και να επιστραφούν από κλήσεις άλλων συναρτήσεων. Στην οικογένεια των γλωσσών προγραμματισμού, η C# ανήκει σε εκείνες που υποστηρίζουν first class functions, μέσω του τύπου δεδομένων Delegate και όλης της πραγματικότητας γύρω από αυτό (anonymous methods, lambdas, expression trees). Θυμίζω ότι σε γενικές γραμμές Delegate είναι ένας τύπος δεδομένων (reference type) όπου παρέχει έναν ασφαλή τρόπο για να ενθυλακώσουμε συναρτήσεις (είτε static είτε instance). Ένα Delegate μπορεί να αναφέρεται μόνο σε συναρτήσεις που είναι συμβατές με το signature που περιγράφει.

Η έννοια των πραγματικών closures, ήρθε στην C# με την έκδοση 2.0, υπό τη μορφή των anonymous delegates (και κατεπέκταση στα lambdas), που σε γενικές γραμμές επιτρέπουν την προσπέλαση (read & write) μεταβλητών που δηλώνονται έξω από το scope αυτών. Χωρίς true closure support, είναι π.χ., η Java και ότι πιο κοντινό έχει σε αυτό το concept, είναι τα anonymous inners classes. Ένα simplistic closure support υπολογίζεται ότι θα υποστηριχθεί με την έλευση της νέας έκδοσης 7, το Σεπτέμβρη 2010.

Περιβάλλον ενός lambda

Στο παρακάτω μπλοκ κώδικα θα δούμε διαφορετικούς τύπους μεταβλητών, αναφορικά, με την θέση τους σε σχέση με το lambda.

Outer/free Variables: Οι μεταβλητές που βρίσκονται στο λεκτικό περιβάλλον του delegate (δηλαδή το scope τους περιλαμβάνει το delegate) θεωρούνται ώς πιθανές μεταβλητές που μπορούν να χρησιμοποιηθούν από αυτό. Ελεύθερες μεταβλητές λοιπόν για ένα lambda, είναι όσες δεν δηλώνονται μέσα στο scope του και όσες δεν δηλώνονται στις παραμέτρους τους (τότε θα λέγονταν bound variables). Μαθηματικώς, για παράδειγμα στον Fourier, για κάποιο χ τα a0, a1, a2, .., bn είναι ελεύθερες μεταβλητές (μπορούν να πάρουν τιμές από τον περιβάλλοντα χώρο) :

image

Όταν ένα free variable δεσμευτεί στο περιβάλλον του lambda, λέγεται ότι είναι ένα από τα Captured Variables, τα οποία είναι εξωτερικές μεταβλητές που χρησιμοποιούνται μέσα στο lambda. Ότι δεν είναι free variable, λέγεται bound variable, όπως για παράδειγμα η μεταβλητή Anonymous Local που ανήκει στις μεταβλητές που δηλώνονται και χρησιμοποιούνται μέσα στο lambda.

Όταν μέσα σε ένα lambda γίνεται αναφορά σε μία εξωτερική μεταβλητή, λέμε ότι η μεταβλητή αυτή, έχει δεσμευτεί (captured) και η ίδια ζει, όσο ζει και το lambda (γίνεται όπως λέμε, επέκταση του χρόνου ζωής της). Τι συμβαίνει στην πραγματικότητα όταν γίνεται capture; Ας το δούμε μέσα από ένα παράδειγμα.

Έστω ότι έχουμε μία συνάρτηση χωρίς capturing μεταβλητών:

όπου:

το delegate.

O compiler αντιμετωπίζει το delegate type instantiation (με το lambda που βλέπετε εκεί), κάνοντας allocation μία πραγματική ενδιάμεση μέθοδο που έχει κάνει generate.

Έστω ότι το lambda κάνει capture μία τοπική μεταβλητή:

H C# σε αυτό το σημείο, προσδίδει σημασιολογία closure και λέει: Επειδή το αντικείμενο που γίνεται reference από το d (η μέθοδος που κάνει Writeline το y, δηλαδή),  (μπορεί) να ζήσει περισσότερο από το scope της F (π.χ., αν επιστραφεί από τη συνάρτηση), κρατά τη μεταβλητή y (όχι απλά την τιμή της), για να την χρησιμοποιήσει, όταν το d γίνει invoke και εκτελεστεί. Πριν δείξουμε όμως την περίπτωση όπου το d ζει περισσότερο από το y (προς το παρόν δεν ζει) ας δείξουμε τι γίνεται σε αυτό το παράδειγμα. O compiler under the hood κάνει το εξής:

Ταξιδεύοντας λίγο περισσότερο στο flow, τι γίνεται αν έχω μεταβλητές σε διαφορετικά statement blocks, όπως στο παρακάτω παράδειγμα; Τότε ο compiler λειτουργεί αναλόγως. Στην παρακάτω περίπτωση, έχουμε αναφορά σε μία εξωτερική μεταβλητή (this.x)

Στην παραπάνω μέθοδο F, το lambda κάνει capture μία μεταβλητή που δηλώνεται μία φορά στο this και δεν αλλάζει, μία τοπική μεταβλητή που δεν αλλάζει και μία τοπική μεταβλητή που αλλάζει συνεχώς, με κάθε iteration. O compiler θα κάνει generate δύο κλάσεις. Μία (Locals2) που θα περιέχει τη μέθοδο, την μεταβλητή Z, καθώς και αναφορά στην άλλη generated κλάση. Η δεύτερη generated κλάση (Locals1) θα έχει τη μεταβλητή y και ένα reference σε object τύπου Top οπότε η συνάρτηση F θα μετασχηματιστεί ως εξής:

Όπως παρατηρούμε, οι μεταβλητές που έχουν γίνει capture, ζουν τώρα πια στο heap καθώς έχουν γίνει dynamic allocated μέσα σε κλάση.

Ας δούμε όμως, μία χρήση των anonymous delegates σαν κανονικά first order functions που είναι. Διαβάστε προσεκτικά τον παρακάτω κώδικα. Έστω ότι θέλω να ορίσω ThreadStart delegates. Φτιάχνω ένα array από δύο anonymous delegates μέσα στο for και αναθέτω σε κάθε ένα από τα δύο κελιά του array, από ένα anonymous delegate. Τα anonymous delegates έχουν κάνει capture δύο free variables, τις outside και inside (και allocate στο heap με τις compiler generated κλάσεις που είδαμε).

Σκεφτείτε ότι την ώρα που γίνεται η ανάθεση τιμής στο delegates[ i] γίνονται οι αναθέσεις, έχουν γίνει capture οι μεταβλητές και ο κώδικας εκτελείται παρακάτω. Γίνεται invoke το delegate της θέσης 0 και τυπώνει (0,0). Τη δεύτερη φορά και τα δύο αυξάνονται, όμοια και την τρίτη φορά και έχουμε (1,1) και (2,2). Τώρα εκτελείται το δεύτερο delegate. To outside είναι σε κατάσταση 3, οπότε με την αύξηση γίνεται 4, το inside όμως έχει ΞΑΝΑ-δηλωθεί (int inside = 0), οπότε το delegate έχει διαφορετικό instance της inside, αρχικοποιημένο στο 0. Οπότε η συνέχεια έπεται ως (3,0) και (4,1). Αν γράφατε τον παραπάνω κώδικα δείτε τι θα σας έδειχνε ο Resharper … ;) Πώς μπορώ να το διορθώσω αυτό, αν δεν το επιθυμώ (χωρίς να πατήσω την λάμπα αριστερά :P);

image

Γιατί είναι τόσο σημαντικά τα closure semantics;

Έστω ότι θέλουμε να φιλτράρουμε μία λίστα με βάση κάποια κριτήρια. Ας το υλοποιήσουμε απλά! Τι χρειαζόμαστε; Μία λίστα για να διαβάσουμε, έναν κανόνα που να δείχνει true αν κάνει pass το αντικείμενο και να θα το εισάγει σε μία νέα λίστα. Αφού διατρέξουμε όλη τη λίστα, θα έχουμε στα χέρια μας μία άλλη λίστα μόνο με όσα “πέρασαν”.


Όμορφα. Προχωράμε στο filtering. Έστω ότι θέλουμε να βρούμε όλους τους πελάτες ως 18 ετών.

Στη C# 3.0 (λόγω lambdas) μπορούμε να γράψουμε το εξής:

Αν όμως δεν θέλουμε hard coded το 18 και χρειαζόμαστε να το ρυθμίζουμε μέσα από μία μεταβλητή; Έστω ότι δεν έχουμε closures. Τι κάνουμε; Το αλλάζουμε απλά με μία μεταβλητή; Και αν η μεταβλητή είναι static και αλλάξει; Και αν θέλουμε thread safety; Αν αναφερόμαστε σε Threading και θέλουμε να περάσουμε παραμέτρους στο thread μας; H C# έχει την δυνατότητα capturing μεταβλητής και όχι τιμής και αυτό είναι ένα από τα δυνατά της σημεία.

Some food for thought

Τι θα τυπώσει ο παρακάτω κώδικας χωρίς Copy-Paste-F5; ;););)

Enjoy closures!!!

Για όσους ενδιαφέρονται να διαβάσουν μία ιδέα για το πώς μπορεί να επεκταθεί η IL για να υποστηρίζονται closures και άλλα όμορφα πράγματα σε επίπεδο IL, μπορούν να διαβάσουν μία σχετική δημοσίευση από MSR του Don Syme, δημιουργού της F#.

 

  1. D. Syme, “ILX: Extending the. NET Common IL for Functional Language Interoperability,” Electronic Notes in Theoretical Computer Science 59, no. 1 (2001): 53–72.
Share/Bookmark

Αντιγραφή αρχείου σε UNC Path προγραμματιστικά (ASP.NET or just code)

Η αντιγραφή αρχείου σε NAS, προγραμματιστικά (ή εν γένει σε κάποιο UNC location εκτός τοπικού μηχανήματος) είναι μία ανάλογη διαδικασία, όπως αν το κάνουμε μέσω του UI. Θα ανοίγαμε το Run, στην συνέχεια πληκτρολογούμε το unc path. Αν σε εκείνη την τοποθεσία έχουν τεθεί permissions για όλους, τότε το παράθυρο ανοίγει κατευθείαν. Σε αντίθετη περίπτωση θα πρέπει να εισαχθούν τα στοιχεία για να γίνει login ο χρήστης, είτε τοπικός, είτε domain (σε αυτήν την περίπτωση θα πρέπει να εισαχθεί και το domain με τον γνωστό τρόπο domain/username). Τι χρειάζεται όμως για να γίνει προγραμματιστικά η διεργασία και μάλιστα μέσα από κώδικα που εκτελείται στο περιβάλλον του IIS; Τότε αυτό που θέλουμε να κάνουμε λέγεται delegation και υπόκειται στο κεφάλαιο ASP.NET Delegation. Με βάση αυτό μπορεί η ASP.NET να προσπελάσει resources σε απομακρυσμένο σύστημα. Μία ειδική περίπτωση αυτού είναι το ASP.NET Impersonation με το οποίο το σύστημα είναι τοπικό. Mε αυτόν τον τρόπο οι ASP.NET εφαρμογές μπορούν να εκτελέσουν κώδικα κάτω από την ταυτότητα του χρήστη τον οποίο απαιτείται να χρησιμοποιήσουν για την πρόσβαση. Για να γίνει αυτό θα πρέπει τα δύο μηχανήματα να μελετηθούν ως προς το λειτουργικό τους, την ύπαρξη του δικαιώματος για delegation, κτλ. Επίσης θέλει προσοχή κατά το σχεδιασμό μιάς τέτοιας λύσης για λόγους ασφαλείας.

Έστω ότι έχω την περίπτωση που ο IIS τρέχει κάτω από το IUSR_machinename για ανώνυμη πρόσβαση. Αν γνωρίζω από πριν username και password τότε μπορώ ρυθμίζοντας το directive <processModel> να ελέγξω την παραπάνω διαδικασία (βλ. link για asp.net delegation). Στην περίπτωσή μου θέλω να ελέγχω την διαδικασία πλήρως χρησιμοποιώντας το LogonUser API. Θέλω λοιπόν να κάνω ένα συγκεκριμένο account login, όπως έδειξα και νωρίτερα όταν ήθελα να μεταφέρω ένα αρχείο από το ui. Δεν υπάρχει αντίστοιχη μέθοδος όμως (ως Login, αυτούσια), στο .ΝΕΤ και η μόνη μέθοδος που κάνει impersonate είναι η WindowsIdentity.Impersonate (IntPtr), από το System.Security.Principal. Τι είναι το IntPtr; Είναι ένα handle για τον χρήστη του συστήματος και ανακτάται από κλήση σε unmanaged κώδικα μέσω της LogonUser από το advapi32.dll.

Στον κώδικά μου ήθελα να μπορώ να τρέχω ένα File.Copy (ή οτιδήποτε) το οποίο θα εκτελείται με βάση συγκεκριμένα credentials.

 

 

Έτσι η Execute που έγραψα, χοντρικά ήταν η εξής

Αξίζει να σημειώσουμε ότι στο τέλος θα πρέπει οπωσδήποτε να επαναφέρεται το process identity στο προηγούμενο (μέσω τη undo), γιατί θα υπάρξει πρόβλημα στις περαιτέρω ενέργειες

Τέλος η παραπάνω διεργασία χρειάζεται full trust (PermissionSetAttribute)

Share/Bookmark
Posted by Aggelos Mpimpoudis | 2 comment(s)
Filed under: , ,

Παρουσίαση .NET και C# στο ΠΜΣ Πληροφοριακά Συστήματα ΟΠΑ – Τεχνολογία Λογισμικού

Παραθέτω το υλικό της σημερινής παρουσίασης για .NET, C# που είδαμε στο μάθημα Τεχνολογίας Λογισμικού (ευχαριστούμε τον καθηγητή Εμ. Γιακουμάκη που την πραγματοποιήσαμε επιτυχώς). Η παρουσίαση που διαδέχτηκε τη δική μου, από τον Μιχάλη Ζερβό, βρίσκεται εδώ. Και οι δύο, βρίσκονται στο e-class του μαθήματος.

Στην παρουσίασή μου, προσπάθησα να δώσω όσες περισσότερες ιδέες μπορούσα (στο σύντομο χρονικό διάστημα της μίας ώρας) αναδεικνύοντας την εκφραστικότητά της και τις δυνατότητες που έχει. Καλύφθηκαν αρκετά θέματα, ξεκινώντας από τις βασικές δομές και εξηγώντας στη συνέχεια μία πληθώρα από άλλες όπως, delegates, anonymous functions, anonymous types, iterators, lambdas, extension methods, LINQ καθώς επίσης τα βασικά από τη λειτουργία του ίδιου του περιβάλλοντος εκτέλεσης και της εσωτερικής οργάνωσης του .NET. H παρουσίαση, είχε στόχο να δώσει πολλές ιδέες και ερεθίσματα, καθώς δύσκολα μία έννοια μπορεί να διατυπωθεί μέσα από μερικά slides σε περιορισμένο χρόνο.

Τα Demos (WPF, F#) που παρουσίασα για τις ανάγκες περιήγησης στο Visual Studio βρίσκονται εδώ, καθώς και η παρουσίαση. Για να κατεβάσετε την Beta 2 του VS Studio 2010 Beta 2 θα ακολουθήσετε τον εν λόγω σύνδεσμο. Τέλος, για την σύντομη αναφορά στην F#, μπορείτε να δείτε μία επεξήγηση (στο ίδιο πρόγραμμα για τους πύργους του Ανόι) στο εξής blogpost.

 

Enjoy coding!!

Share/Bookmark
Posted by Aggelos Mpimpoudis | with no comments
Filed under: , , ,

Πύργοι του Ανόι σε F#

Θυμάστε πώς είχαμε υλοποιήσει τους πύργους του Ανόι σε C στη σχολή όταν πρωτοπήγαμε; Ορίστε πόσο απλή είναι η έκδοση του σε συναρτησιακό προγραμματισμό (με χρήση της F#).

Κατ’αρχάς μερικές νύξεις στο VS Studio 2010 που έχει ενσωματωμένα templates και debugging tools για αυτή τη νέα γλώσσα. Ανοίγουμε το VS Studio 2010 Beta 2 που μπορούμε να το κατεβάσουμε δωρεάν όσο διαρκεί η φάση Beta και διαλέγουμε να δημιουργήσουμε ένα Console Application σε F#.

image

Στην συνέχεια κάνουμε paste τον παρακάτω κώδικα (προσέξτε το indentation στον κώδικα καθώς έχει σημασία να είναι σωστά στοιχειοθετημένες οι εντολές. Δεν γίνεται compile αν δεν ακολουθηθούν οι αντίστοιχοι απλοί κανόνες) που ορίζει δύο συναρτήσεις, την move (μετακίνησε από στύλο σε στύλο, στην ουσία απλά κάνει print την κίνηση για να βλέπουμε την αλλαγή της κατάστασης) και την hanoi η οποία υλοποιεί την αναδρομική συνάρτηση. Όποτε δοκιμάζω να μάθω την F#, μου αρέσει να στέλνω ότι γράφω στο interactive environment της. Ότι γράφεται σε αυτό το παράθυρο μοιάζει να περνάει από interpreter, αλλά στην ουσία γίνεται δυναμικά compile on-the-fly βλέποντας την αποτίμηση κάποιας έκφρασης, εκείνη τη στιγμή στο παράθυρο.

Το παραπάνω κομμάτι κώδικα ορίζει μία απλή συνάρτηση και μία αναδρομική.

image

Μόλις γίνει η μεταφορά του κώδικα στο interactive παράθυρο, μας παρουσιάζονται δύο γραμμές:

val move : (char -> char -> unit)

//Η δήλωση της move που παίρνει δύο παραμέτρους τύπου char 

//Η παραπάνω δήλωση ερμηνεύεται ως εξής λόγω του currying: το move είναι μία συνάρτηση που παίρνει ένα argument και επιστρέφει μία συνάρτηση με τύπο (char->unit).


val hanoi : char -> char -> char -> int –> unit

//Η δήλωση της hanoi που παίρνει τρεις χαρακτήρες και ένας ακέραιο.

//Ομοιοτρόπως και σε αυτή τη δήλωση. To int σε αυτή τη περίπτωση είναι μία επίδραση του keyword function, το οποίο λόγω της ιδιότητάς του δημιουργεί μία έμμεση μεταβλητή.

Η δήλωση unit σημαίνει ότι δεν επιστρέφεται τίποτα από αυτή τη συνάρτηση. Το unit αποτελεί έναν primitive type που δεν περιέχει καμία απολύτως πληροφορία και η μόνη του τιμή είναι το ().

Πάμε στην αναδρομική συνάρτηση. Ξεκινάμε με το keyword let, με το οποίο δηλώνουμε πως ότι θα γράψουμε, θα δεθεί με το όνομα hanoi, γίνεται δηλαδή binding του ονόματος με την έκφραση της συνάρτησης. Στη συνέχεια, με το keyword rec αναφέρουμε πως το binding αυτό μπορεί να αναφερθεί στον εαυτό του ή πιο απλά, ότι έχουμε μία αναδρομική συνάρτηση. Ορίζονται το όνομα και οι μεταβλητές μας (χωρίς να ορίζουμε τύπο-γίνεται infer από την F#). Με την λέξη κλειδί function ανακοινώνουμε ότι έχουμε μία συνάρτηση η οποία μπορεί να αναγνωρίσει πρότυπα πάνω στα ορίσματά της (pattern matching), έτσι η F# καταλαβαίνει ότι στα ορίσματα υπεισέρχεται ακόμα ένας τύπος ακεραίου (o ακέραιος εκείνος που μας έδειξε το interactive window παραπάνω). Τι είναι pattern matching εν συντομία; Pattern matching είναι η δυνατότητα που προσφέρει η δομή function… και η δομή match…with… να εκτιμά το αποτέλεσμα μίας έκφρασης και να συγκρίνει αυτό το αποτέλεσμα με μία σειρά από κανόνες. Στην περίπτωσή μας, οι κανόνες πηγάζουν από την αναδρομική λύση του προβλήματος. Αν παρατηρήσουμε τη μαθηματική λύση και το παραπάνω κώδικα, θα δούμε ότι οι παραπάνω εκφράσεις είναι η μετάφραση της μαθηματικής λύσης αυτούσια από το συλλογισμό μας, στην F#. Παρατηρήστε την αναδρομική λύση του προβλήματος. Έχει τρία βήματα που λένε:

  • - Μετέφερε n-1 δίσκους από τον πρώτο στύλο στο δεύτερο (οπότε απομένει ο δίσκος με τον αριθμό n – ο μεγαλύτερος στον πρώτο στύλο)
    - Μετέφερε τον δίσκο n από τον πρώτο στύλο στον τρίτο
    - Μετέφερε n-1 δίσκους από τον δεύτερο στύλο στον τρίτο.
  • - Τι γίνεται όταν έχουμε τον δίσκο υπ’ αριθμόν 1 (τον μικρότερο δηλαδή); Μετέφερέ τον στον τρίτο στύλο!

Ακριβώς δηλαδή ότι είναι γραμμένο στο παραπάνω κομμάτι κώδικα!

Εκτελώντας τον κώδικα για διαφoρετικούς ακεραίους, μία για 2 δίσκους και μία για 4 δίσκους, βλέπουμε τη λύση στο interactive window.

image

Cheers!

Share/Bookmark

Εισαγωγή στα Expression Trees και στις δυναμικές μεθόδους (Visual Studio 2010)

Στο απόλυτο βιβλίο για compilers (καθιερωμένο ως Dragon Book εξαιτίας του concept art εξωφύλλου του στην πρώτη έκδοση) ως abtract syntax trees ή απλά syntax trees, ορίζονται οι ιεραρχικές συντακτικές δομές του πηγαίου κώδικα ενός προγράμματος. Όταν γράφουμε κώδικα, υπάρχει μία πάρα πολύ συγκεκριμένη διαδικασία η οποία μετατρέπει τις λέξεις και τα σύμβολα που γράφουμε, σε δομές που έχουν συγκεκριμένη σημασιολογία. Το πρώτο κομμάτι ενός μεταγλωττιστή ασχολείται με το “διάβασμα” του κώδικα που γράφουμε. Αυτή η διαδικασία αποτελείται από τρία στάδια. Στο πρώτο στάδιο υπάρχει ένας λεκτικός αναλυτής ο οποίος παίρνει ως είσοδο το αρχείο κειμένου που γράψαμε, και το σπάει σε τεμάχια ή αλλιώς tokens. Για παράδειγμα εμείς γράφουμε items + 1 και ο αναλυτής αναγνωρίζει ως token την λέξη item. Στην συνέχεια λαμβάνει χώρα η ανάλυση (parsing), που παίρνει τα tokens και σύμφωνα με τους κανόνες της γλώσσας, δημιουργεί συντακτικά δένδρα εκφράσεων. Στο τελευταίο βήμα λαμβάνονται οι εν λόγω δενδρικές δομές και παράγεται αυτό που λέμε ενδιάμεσος κώδικας. Υπάρχουν δύο ήδη συντακτικών δένδρων, τα αφηρημένα και τα μη (abstract και concrete). Σε ένα abstract syntax tree λοιπόν απεικονίζεται μία έκφραση, του οποίου ο εσωτερικός κόμβος είναι ένας operator και τα παιδιά είναι τα operands (τα οποία μπορούν με τη σειρά τους να είναι εκφράσεις). Η διαφορά με τα concrete syntax trees είναι ότι τα concrete έρχονται κατευθείαν από τον parser (αντικατοπτρίζοντας αποκλειστικά το συντακτικό της γλώσσας) ενώ τα abstract προσδίδουν με τη σειρά τους πρόσθετη πληροφορία (σχετικά με σημασιολογία π.χ.).

Πολύ όμορφα λοιπόν, γράφουμε λέξεις περιγράφοντας διαδικασίες οι οποίες μεταφράζονται σε εντολές. Στην γλώσσα C# τα expression trees αποτελούν έναν τύπο δεδομένων που αποθηκεύει κώδικα σε μορφή δεδομένων. Τα δεδομένα αποθηκεύονται υπό τη μορφή δένδρων, όπως ακριβώς τα δένδρα που περιέγραψα παραπάνω. Με το συγκεκριμένο τύπο δεδομένων μπορούμε να κάνουμε κάτι πάρα πολύ όμορφο και θεάρεστο :P: να αλλάξουμε ή να μετασχηματίσουμε κώδικα κατά το runtime execution, πριν τον εκτελέσουμε. Για παράδειγμα υπάρχει η δυνατότητα να μετατραπεί κώδικας C# (όπως κάνει η LINQ μέσω των query expressions) σε κώδικα που εκτελείται σε άλλο process, όπως είναι μία βάση δεδομένων.

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

Το παραπάνω μας βοηθάει να δηλώσουμε μία μεταβλητή συνάρτησης στην οποία αποθηκεύεται ένα lambda που υπολογίζει το άθροισμα δύο αριθμών (βλ. delegates και generic functions). Ακόμα και για κάποιον που δεν έχει κατανοήσει πολύ καλά τις δύο παραπάνω έννοιες, φαίνεται πολύ καθαρά από την παραπάνω γραμμή ότι κατά κάποιον τρόπο έχουμε αποθηκεύσει στη μεταβλητή function μία αναφορά προς εκτελέσιμο κώδικα. Τα expression trees δεν είναι εκτελέσιμος κώδικας, οπότε πώς μεταφράζουμε το παραπάνω expression σε expression tree;

Με την παραπάνω γραμμή κάναμε αυτό που θέλαμε! Δηλώσαμε μία μεταβλητή expression η οποία περιέχει σε μορφή δεδομένων το συντακτικό δένδρο που θέλαμε. Τι μπορούμε να κάνουμε με αυτό λοιπόν; Μπορούμε καταρχάς να πάρουμε το σώμα της συνάρτησης με το Property Body, τις παραμέτρους με το Property Parameter, τον τύπο του κόμβου που θέλουμε με το Property NodeType (η λίστα με τους τύπους expressions), ή απλά τον CLR τύπο με το Property Type. Για την καλύτερη κατανόηση της διαφοράς μεταξύ Node Type και Type παραθέτω το παράδειγμα από το msdn:

Έστω ότι έχουμε το expression που περιγράψαμε παραπάνω: Τα “δεδομένα” μπορούν να ανακτηθούν ως εξής:

Τι κάνουμε όμως αν έχουμε μία έκφραση σε μορφή δεδομένων και θέλουμε να την εκτελέσουμε; Ότι κάνουμε πάντα! Compile!

Μπορεί με πρώτη ματιά να φαίνεται ότι απλά προσθέσαμε overhead στην λειτουργικότητα των lambdas. Σκεφτείτε όμως μία χρήση που ήδη βλέπετε τριγύρω σας. Πόσα διαφορετικά είδη LINQ εκτός από LINQ to objects υπάρχουν; Πώς τα queries που γράφουμε, μπορούν να εκτελεστούν σε διαφορετικά processes που τρέχουν κάποια εφαρμογή; Μέχρι τώρα λοιπόν, αυτή είναι η αλήθεια για την κύρια χρήση των expression trees. Χρησιμοποιούνται σε LINQ providers καθώς επίσης και σε μετατροπές expression trees και compilation. Στο Visual Studio 2010 τα Expression Trees έχουν επεκταθεί και κάποιος προγραμματιστής μπορεί τώρα πια με τη χρήση τους, να παράγει και δυναμικές μεθόδους (χωρίς MSIL). Αυτή η νέα δυνατότητα δεν μπορεί να πραγματοποιηθεί με lambda expressions αλλά μόνο με το νεό Expression Trees APΙ (διαθέσιμο στο Visual Studio 2010 έχοντας διατηρήσει και το υπάρχον functionality) που το επιτρέπει αυτό. Ας ξεκινήσουμε με την Expression.Block που συμβάλει στις νέες δυνατότητες των Expression Trees και επιτρέπει σειριακή εκτέλεση expressions. Το παράδειγμα πηγάζει από εδώ:

Το αποτέλεσμα έχει ως εξής:

image

Στο ίδιο blog post μπορούμε να βρούμε ένα πιο δύσκολο παράδειγμα, παρουσιάζοντας πώς μπορούμε δυναμικά να φτιάξουμε μία μέθοδο που να παίρνει ως όρισμα έναν αριθμό (Expression.Parameter), να δηλώσουμε μία μεταβλητή (Expression.Assign) και ένα επαναληπτικό block (Expression.Loop), φτιάχνοντας την Factorial.

Share/Bookmark

1st Architecture Days post-event comments

Πριν μερικές ώρες γύρισα από το πολυαναμενόμενο event του dotnetzone.gr, για αρχιτεκτονική λογισμικού [link]. Θα ήθελα να συγχαρώ τους διοργανωτές για την οργάνωση και τη θεματολογία. Δυστυχώς έπρεπε να αποχωρήσω στο τελευταίο μέρος λόγω υποχρεώσεων αλλά θα ήθελα να σας μεταφέρω την εμπειρία από τα τρία πρώτα μέρη.

Locating and addressing performance issues: From software to hardware architecture - Διομήδης Σπινέλλης

22102009103 22102009104

Ο κύριος Διομήδης Σπινέλλης, μέσα σε μία ώρα έθιξε τα κύρια σημεία του code quality, και τρόπους και αρχές για ελέγχο του κώδικά μας, με στόχο την (ποιότητα)=>ταχύτητα, ασφάλεια, εξοικονόμηση. Οι πρακτικές και έννοιες πήγασαν από την δική του εμπειρία και μεθοδολογία, που εύκολα ένας συνειδητοποιημένος ακροατής, αν κρατήσει τις ιδέες και τις υλοποιήσει με τα δικά του εργαλεία και συστήματα, σίγουρα θα κάνει πολλά βήματα εμπρός σε οποιαδήποτε πλατφόρμα και αν εργάζεται. Η παρουσίαση πλούσια σε εικόνες, κώδικα, shell, profiling and more! Αριστούργημα.

Συνοπτικά ο δεκάλογος που μου έμεινε:

  1. Ανάλυση του προβλήματος σε επίπεδο απασχόλησης CPU-> user time vs system time vs idling vs clock time (procmonitor and more)
  2. Ανάλυση κώδικα με γραφήματα εξαρτήσεων στον κώδικα, flags στους compilers για πλήρες reporting μέχρι και σε επίπεδο γραμμής πηγαίου
  3. Βελτιστοποίηση αλγορίθμων με σύνεση. Εντοπισμός lower + upper bounds + reusability καλών βιβλιοθηκών + προσαρμογή στα δεδομένα μας
  4. Γνώση των εσωτερικών μηχανισμών με μετρητές απόδοσης σε επίπεδο cpu, με διαιρέσεις δεικτών με πλούσια σημασιολογία (Διαίρεση δείκτη 1/ δείκτη 2 := π.χ. utilization κάποιου πόρου χ => συμπέρασμα)
  5. Προσοχή στα ΙΟ  (μνήμη, ιεραρχίες, locality of reference)
  6. Αποφυγή ΛΣ και κλήσεων σε αυτό
  7. Background processing + thrashing => πρόβλημα με φυσική μνήμη
  8. Αλγόριθμοι με τοπικότητα αναφορών (εδώ δόθηκε ένα ακόμα οπτικό παράδειγμα με δύο αλγορίθμους για πράξη πινάκων)
  9. Γνωρίστε τα δεδομένα σας, το κόστος τους, το βάρος τους, το “σχήμα τους”
  10. Memory management, εντοπισμός bottlenecks

 

Modeling in the Enterprise with Microsoft "Oslo" – Νατάσα Μανουσοπούλου

22102009108 22102009109

Μία πραγματικά φοβερή τεχνική παρουσίαση από την Νατάσα, για το OSLO, την πλατφόρμα μοντελισμού της Microsoft που βρίσκεται σε εμβρυακό στάδιο ακόμα, επιτρέποντας σε ανθρώπους που προέρχονται από διαφορετικά περιβάλλοντα να επικοινωνούν μεταξύ τους, κατά τη διαδικασία του requirements engineering. Η έμφαση δίνεται κυρίως στους προγραμματιστές, εφοδιάζοντάς τους, με το επίπεδο γενίκευσης εκείνο, που θα τους βοηθήσει στην μετέπειτα διαδικασία. Η πλατφόρμα αποτελείται από τρία πράγματα: το εργαλείο, την “γλώσσα” για να μπορείς να ορίζεις ειδικές γλώσσες για το πρόβλημά σου και ένα κοινό σημείο αποθήκης μοντέλων, ώστε μετά να πέσουν όλοι πάνω για την παρουσίαση των εννοιών που μοντελοποιήθηκαν (είτε μέσω ενός Entity Framework Diagram, είτε μέσω ui και της πανίσχυρης XAML, είτε ακόμα μέσα από Sharepoint). Τρία πράγματα για αρχή, λοιπόν: Διαμοιρασμός πληροφορίας, ευκολία παραμετροποίησης, διαχείριση αλλαγών (στα requirements). Το πρώτο που πρέπει να καταλάβουμε είναι πως αποκτούμε μία formal γλώσσα για να περιγράψουμε την φυσική γλώσσα και μετα-δεδομένα για να περιγράψουμε κώδικα. Τι καλύτερο δηλαδή από το να έχουμε τον προγραμματιστή μας δίπλα, στην συνέντευξη για requirements document, και την ώρα που μαθαίνουμε το domain του πελάτη να γράφουμε δίπλα κάτι τόσο generic που μετά θα το κάνουμε, ui ή business object ή report ή ή ή… Η Νατάσα μας έδειξε ένα πολύ όμορφο παράδειγμα με μοντελοποίηση ερωτηματολογίου το οποίο το δόμησε με MGrammar και το παρουσίασε με Sharepoint. Παραθέτω ένα παράδειγμα μοντελοποίησης του πεδίου “Οικογένεια” που βρήκα εδώ. Interesting huh? :)

Και έτσι μπορώ να γράψω στον κώδικα, το δεδομένο μου το οποίο μπαίνει σε ένα πολύ όμορφο POCO. Πανέμορφο!

Reliability, Availability, and Scalability - Have your cake and eat it too - Udi Dahan

22102009110 

Πραγματική έμπνευση η παρουσίαση του διάσημου Udi Dahan… Μας παρουσίασε τις έννοιες reliability, availability και scalability στο enterprise service bus. Τι γίνεται όταν έχουμε έναν Application Server και έναν DB Server και κάποιος συνδυασμός τους ή ένας από τους δύο βρεθεί εκτός λειτουργίας προσωρινα; Πώς χτίζουμε υποδομή για να αποφύγουμε προβλήματα όπως μη διαθεσιμότητα, τα οποία θα επηρρεάσουν το business μας; Όμορφες ιδέες και απλές στην υλοποίηση, ξεκαθαρίζουν το τοπίο, όπως one way messaging ( request response / publish subscribe), handling messages, rolling back business operations που αποτελούνται από διάφορες πηγές (π.χ., ανεξάρτητα orchestrated Web Services) με τέτοιο τρόπο που θα είναι σαν πραγματικό πισωγύρισμα στο χρόνο. Ιδέες όπως οι παραπάνω γίνονται encapsulate στο open source project του Udi ονόματι NServicebus.

 

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

Share/Bookmark

Ασφαλής χρήση FileSystemWatcher

Υπάρχουν σενάρια που χρειάζεται να ξέρετε πότε ένα καινούριο αρχείο δημιουργείται σε έναν κατάλογο, ή πότε γίνεται rename, ή πότε αλλάζει το Last Changed timestamp για να κάνετε διάφορες εργασίες. Έστω το σενάριο, ότι έχετε ένα εξωτερικό εργαλείο που κάνει κάποια λειτουργία μετατροπής αρχείων. Για να μπορείτε να αντιληφθείτε πότε το αρχείο γράφτηκε στο folder που παρατηρείτε και να αντιγράψετε το αρχείο αυτό κάπου αλλού, ή να το επεξεργαστείτε, μπορείτε να χρησιμοποιήσετε το FileSystemWatcher του .NET. Παρόλα αυτά υπάρχει ένα θέμα εδώ. Ο FileSystemWatcher είναι καθαρά για reporting σκοπούς. Αν εσείς χρειάζεστε το αρχείο αυτούσιο, θα πρέπει να γνωρίζετε για το πότε το αρχείο είναι επιπλέον ελεύθερο από οποιοδήποτε άλλο process (π.χ., εκείνου που το αντιγράφει στο folder που κοιτάται). Ένα απλός και γρήγορος τρόπος, για να αποφύγουμε το IOException σε τέτοια περίπτωση είναι ο παρακάτω:

Δημιουργούμε μία συνάρτηση που ελέγχει για το αν το αρχείο είναι κλειδωμένο.

private static bool CheckFileLock(string filename)
{
    try
    {
        using (FileStream inputStream = File.Open(filename, 
                                    FileMode.Open,
                                    FileAccess.Read,
                                    FileShare.None))
        {
            return true;
        }
    }
    catch (IOException)
    {
      //Log maybe
        return false;
    }
}

Στη συνέχεια ο Watcher σας για να δουλέψει θα χρειαστεί τον event handler για το event Created. Ο Handler αυτός θα πρέπει να τσεκάρει ανά τακτά χρονικά διαστήματα (απλή λύση) για τη διαθεσιμότητα του αρχείου και that’s it.

private void onFileCreated(object sender, FileSystemEventArgs e)
{
    DateTime receivedTime = DateTime.Now;
    int delay = ...
    while (true)
    {
        if (CheckFileLock(e.FullPath))
        {
            //Do whatever you want safely
            break;
        }
        TimeSpan elapsedTime = DateTime.Now - receivedTime;
        if (elapsedTime.TotalMinutes > max)
        {
            //Logging definitely 
            break;
        }
        Thread.Sleep(delay);
    }
}

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

Share/Bookmark
Posted by Aggelos Mpimpoudis | 4 comment(s)
Filed under: ,

Tip of the day #2: Problem with your WCF hosting? Probably an ABC matter!

Today I faced a nice little issue. It wasn’t something mindblasting and the solution wasn’t somehow innovative, but rather a 5-minute issue to resolve (If I had said the ABC out loud first). Instead it was a 30 minutes work. I was asked to make a new WCF web service to provide some functionality for our business case. Some structural background on the project I was working on: It is a Silverlight application, with client-side data management UI, a server-side with (web) services supporting our business logic and a LOT of (disconnected) business objects flying around like crazy, between the web application and the client. This orchestration was ment to be disturbed until today, by me, creating two more WSs’, the first for a certain operation taking place server-side and a second, stand alone, little web service doing some stuff at a third tier in another machine (which is used by the former). I spent more than 30 minutes in the morning (before coffee) asking myself what have I done wrong, and the client (first WS) didn’t recognize my configuration elements. The same dialog between the debbuger again and again, under various tweakings…

 

-Visual Studio says: Sorry, I cannot find default endpoint element that references contract IService******* in the ServiceModel client configuration section.

-Aggelos says: I am going by the book, what is wrong?

-Visual Studio says: Hahahaha, lolz, think again, you happy programer!

What was going wrong? Go back to the beginning, and remember. All the server functionality is supported by a certain web application with it’s own web config. My web service (the client one) had it’s own project under a WCF service library project. The WCF was hosted by the Web Application so… yeah that’s the answer. The configuration resides in web.config of course, even if the WCF (library) is somewhere else…

ABC stands for Address, Binding, Contract…missing one of them, breaks all of them… what about missing all of them? :P:P:P:P:P

Share/Bookmark
Posted by Aggelos Mpimpoudis | with no comments
Filed under: ,

Tip of the day #1: Love and take care of your MSDTC connectivity

You have a nice day, but something is missing. Your first debug tryout, after some hours of refactoring and new feature coding. After the successful built, you get your first exception (the usual handled exception that is logging something). Usually the exception is self-explained, it gives you the right information and with a little bit of help from the call stack you pin-point the failure. So, let’s see the code…xmmmm…the error is somewhere on my tested-and-working-perfect-until-now part of my module… The exception is accompanied with a transaction lock. But why? You keep unlocking the database via the Activity Monitor of SQL Management Studio, you retest the code, step by step, but you can’t pinpoint the the problem. Why my thread does that to me, what have I done? Why does it lock my data during the business object save?

As a matter of fact, during the day, I have done 3 things in general:

  • I have been coding in a region, not even executed when the lockout occurs.
  • I have participated in updating the db server (another physical machine)
  • I have deployed several updates to my system, including SP3, during the previous night.

So after an hour of pair-debugging, my colleague concludes that there isn’t anything wrong with the code itself, so the first bullet is gone. The problem occurs when data switches transaction mode during persistence, to distributed transaction, so we have two machines, with “maybe” recently-damaged MSDTC settings. Either my machine or the db server. By restarting after checking the settings at the db server, the problem still exists. So, the 2nd bullet is gone too. What is wrong with my pc after all?

And then, after a couple of hours I hear a magic voice screaming to me: OMG!!! Check Immediately your firewall! And there it was, the filthy, stupid (not even a) bug… that had jumped from the code and settled somewhere else. The newly-during-the-night-updated system, had restored settings and rules at firewall, ending the communication of my Microsoft Distributed Transaction Coordinator with the outer world…

 

Tragic….but still funny :P

Share/Bookmark
Posted by Aggelos Mpimpoudis | with no comments
Filed under: , ,

Tip of the day #0: Admit your SLCM’s

How many of you, have experienced an embarrassing –at yourself- code bug situation? You know, that you were better than this one, but you don’t want to admit it. You go home at night, thinking about it. You dream of it, laughing in your face…it’s laugh jumps out, through the code blocks, haunting your existence… it isn’t a logical error in communication of the wireless sensor network you recently engineered, it is a bug, residing in your configuration file… it isn’t an algorithmic fault, in your genetic algorithm … your algorithm doesn’t execute well because of the non-printable character in this f%@#$@#$ string (or char* I still love you). Finally, your business object doesn’t lazy load… -why god…pls give me strength –[god]My child take some rest, you have a buggy old version of your ORMapper, go get some sleep.

Admit your stupid little code mistakes. They are part of your professionalism. I will post some worth-mentioning situations just for fun (and non profit at all - :P:P:P).

 

computer-bug[1]

Share/Bookmark
Posted by Aggelos Mpimpoudis | with no comments
Filed under:

Windows Sensor and Location platform

Τα Windows 7 περιέχουν ενσωματωμένη (native) υποστήριξη για διαχείριση αισθητήρων μαζί με μία προγραμματιστική πλατφόρμα που την συνοδεύει. Αφορά location sensors, temperature, accelerometer, ambient light, moisture, camera, RFID και πολλούς ακόμα τύπους αισθητήρων, που κοινώς φέρνουν τον enterprise developer πιο κοντά στις εφαρμογές διάχυτου υπολογισμού, από το να κάνουν μία απλή εφαρμογή mashup που θα χρησιμοποιεί δεδομένα από gps μέχρι μία sophisticated πλατφόρμα data fusion. H πλατφόρμα ονομάζεται Sensor and Location Platform και περιλαμβάνει τόσο managed API (C#) όσο και native (C++ με δικό μας memory management). Στην ουσία αποτελείται από 4 πράγματα όλη η πλατφόρμα:

  • To DDI (device driver interface) παρέχει μέσω των Windows έναν πρότυπο τρόπο για να συνδέονται οι αισθητήρες στο σύστημα και να μπορούν να παρέχουν σε αυτό πληροφορίες
  • Το Windows Sensor API για την διαχείριση των δεδομένων
  • To Windows Location API (χρησιμοποιεί το 2ο layer) για την διαχείριση χωρικών δεδομένων
  • Το Location and Other Sensors Control Panel για διαχειριστικά θέματα μέσα, συσχετίζοντας χρήστες με υποδομές αισθητήρων.

Και το software stack φαίνεται παρακάτω:

clip_image001[4]

 

Μία πρώτη γεύση μπορείτε να δείτε στο Windows 7 training kit που έχει μία απλή WPF εφαρμογή, που αλλάζει τη φωτεινότητα της προβαλλόμενης εικόνας με δεδομένα από sensors έντασης φωτός, με τη μισή μαγεία στο XAML (old news) και την άλλη μισή στο SensorHelper.cs αρχείο (Windows 7 platform). Στο View Model του sensor δε (στο SensorViewModel.cs) θα γλείφετε τα δάχτυλά σας, με κάτι δηλώσεις του τύπου που βλέπετε παρακάτω (constructor). Με την πρώτη ματιά βλέπετε ότι τα πράγματα έχουν προσαρμοστεί ακριβώς στο πεδίο των εφαρμογών επίγνωσης πλαισίου με όλο τον boilerplate κώδικα να έχει εισαχθεί μέσα στη πλατφόρμα με ενσωματωμένους τύπους δεδομένων, methods για data retrieval κτλ κτλ.

public SensorViewModel()
{
  _sensor = new SensorHelper<AmbientLightSensor, AmbientLightSensor.LuminousIntensity>();
  _sensor.Initialize();
  _acceleromaterSensor = new SensorHelper<Accelerometer3D, Accelerometer3D.Acceleration3D>();
  _acceleromaterSensor.Initialize();
}

Διαβάστε το αντίστοιχο συνοπτικό docx του lab να δείτε τι εννοώ!!! Επίσης μπορείτε να ανατρέξετε για πληροφορίες της πλατφόρμας στα παρακάτω:

 

Videos από channel 9:

http://channel9.msdn.com/tags/Sensor+and+Location+Platform/

 

Πηγές:

http://www.microsoft.com/whdc/device/sensors/default.mspx

Sensor Programming Guide (MSDN Library)

Location Programming Guide (MSDN Library)

Sensor and Location Platform Developer Resources

Share/Bookmark

NScanner: Port Scanner / Port Sweeper

 

Πρόσφατα ολοκληρώσαμε έναν ανιχνευτή κατάστασης θυρών, ο οποίος να παρουσιάζει διπλή λειτουργικότητα, να είναι και Port scanner αλλά και Port sweeper. Ο Port Scanner θα δέχεται ως είσοδο μια δ/νση ΙΡ (ή hostname) και range από πόρτες (TCP/UDP) που θα θέλαμε να ανιχνεύσουμε. Ο Port Sweeper θα δέχεται ως είσοδο μια πόρτα (TCP/UDP) που θα θέλαμε να ανιχνεύσουμε και λίστα από δ/νσεις ΙΡ (ή DNS name). Η εφαρμογή υλοποιεί TCP, UDP και SYN scan με επιλογές που να τα παραμετροποιούν.

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

TCP Scan

Στο TCP Scan αξιοποιείται η αναλυτική διαδικασία σύνδεσης με Berkeley sockets σε .NET (Socket Class (System.Net.Sockets)). O σκοπός που γίνεται αυτό είναι γιατί έτσι μπορούμε να έχουμε πλήρη έλεγχο κατά την δημιουργία των sockets. H γενική ιδέα είναι ότι, πραγματοποιείται ολόκληρη η διαδικασία του 3-way handshake, κατά την εγκαθίδρυση της σύνδεσης, το οποίο αποτυγχάνει κάτω από συγκεκριμένες συνθήκες, που αποκαλύπτουν την κατάσταση της θύρας. Στον παρόν port scanner που περιγράφεται, ανιχνεύονται θύρες σε τρεις διακριτές καταστάσεις σύμφωνα με την απόκριση τους: ανοικτές, κλειστές φιλτραρισμένες. Οι ανοικτές θύρες (πραγματοποιούν σύνδεση) αποκαλύπτουν ότι η port δεν υπόκειται σε έλεγχο firewall σχετικά με την κατάστασή της και επιτρέπει τις συνδέσεις (ανοικτή και ταυτόχρονα κάποια υπηρεσία την χρησιμοποιεί για να εξυπηρετεί προγράμματα «πελάτες»). Η δεύτερη κατηγορία (κλειστές) αναφέρεται στην κατάσταση όπου μία θύρα αποκρίνεται ότι δεν δέχεται συνδέσεις. Τέλος η κατηγορία στην οποία υπόκεινται οι φιλτραρισμένες θύρες, είναι όταν δεν δεχόμαστε απόκριση στην αποστολή αίτησης προς εκείνες.

UDP Scan

Στο UDP Scan χρησιμοποιείται μία παρόμοια μέθοδος (προγραμματιστικά), ορίζοντας μία περίοδο timeout που επηρεάζει το αποτέλεσμα. Το πρωτόκολλο UDP δεν έχει ανάγκη για SYN, FIN ή κάποια άλλη διαδικασία εγκαθίδρυσης σύνδεσης. Με το πρωτόκολλο UDP τα πακέτα αποστέλλονται και λαμβάνονται χωρίς κάποια προειδοποίηση, πράγμα που απλοποιεί την διαδικασία του port scanning (με περισσότερο αβέβαια αποτελέσματα βέβαια). Οι καταστάσεις που εντοπίζουμε είναι τρεις: Closed, Open/Filtered, Open.

SYN Scan

Στην μέθοδο SYN Scan συλλέγεται πληροφορία για την εμπλεκόμενη θύρα πριν ολοκληρωθεί η διαδικασία της εγκαθίδρυσης σύνδεσης. Όταν μία θύρα αναγνωρίζεται ως ανοικτή το TCP Handshake τερματίζεται με σήμα RST, πριν ακόμα ολοκληρωθεί η διαδικασία. Αυτή η τεχνική συνήθως αναφέρεται και ως half open scan. Σε περίπτωση που η εφαρμογή λάβει σήμα RST μετά από σήμα SYN, σημαίνει ότι η θύρα είναι κλειστή.

Για την παρούσα μέθοδο χρειάστηκε η κατασκευή των πακέτων με αναλυτικό τρόπο όπως επίσης και οι αποκρίσεις με σήματα RST σε περίπτωση που το άλλο άκρο αποκριθεί θετικά (SYN & ACK). Η αναγνώριση των στόχων, των gateway και πολλών στοιχείων που χρειάζονται για την κατασκευή των πακέτων, έχουν γίνει προγραμματιστικά στην συνάρτηση Connect που υπάρχει στην κλάση SynConnectCall.

Τα πλεονεκτήματα της συγκεκριμένης μεθόδου είναι ότι το γεγονός ποτέ δεν καταγράφεται από την εφαρμογή του στόχου, γιατί απλά δεν πραγματοποιείται σύνδεση TCP. Αυτό είναι ένα κατά πολύ πιο «αθόρυβο» scan από άλλα, τα οποία παρουσιάζουν μικρότερη ορατότητα από πλευράς του στόχου. Παρέχει πληροφορίες όπως open, closed και filtered θύρες.

Ανάπτυξη σε C#

Η εφαρμογή μας υλοποιήθηκε σε περιβάλλον .NET 3.5 και σε γλώσσα προγραμματισμού C Sharp (C#), ενώ για το γραφικό περιβάλλον της εφαρμογής χρησιμοποιήσαμε Winforms. Για την υλοποίηση της λειτουργικότητας SYN Scan χρησιμοποιήθηκε η βιβλιοθήκη libpcap[1]. Επίσης για της ανάγκες υλοποίησης σε C# χρησιμοποιήθηκε η υπό ανάπτυξη βιβλιοθήκη που ενθυλακώνει τις native κλήσης συστήματος της βιβλιοθήκης της libpcap ώστε να είναι δυνατή η χρησιμοποίησή της μέσα από περιβάλλον .NET. H εν λόγω βιβλιοθήκη ονομάζεται SharpPcap και διανείμετε δωρεάν, μέσα από το SourceForge.ΝΕΤ[2]. Αξίζει να σημειωθεί ότι έγιναν αλλαγές στον κώδικα του wrapper, όπως και διορθώθηκαν λάθη τα οποία αναφέρθηκαν στην ομάδα ανάπτυξης του, για να ληφθούν υπόψη στη περαιτέρω διαδικασία ανάπτυξής του [3] [4].

Οι μέθοδοι που υλοποιούνται ενθυλακώνονται στις αντίστοιχες κλάσεις <Protocol>ConnectCall (π.χ., το tcp scan υλοποιείται στην TcpConnectCall).

Screenshots

Port Sweeping
image

UDP Port Scanning
image

 

H εφαρμογή αναπτύχθηκε στα πλαίσια εργασίας για το μάθημα “Ασφάλεια υπολογιστών και Δικτύων”, Οικονομικό Πανεπιστήμιο Αθηνών, ΠΜΣ Πληροφοριακά Συστήματα 2008-2009, από τους Άγγελος Μπιμπούδη (εμένα) και Αναστάσιο Νεραντζίνη και καταχωρήθηκε στο codeplex από όπου θα εξελιχθεί/βελτιωθεί. Η άδεια χρήσης είναι GNU Library General Public License (LGPL).

http://nscanner.codeplex.com/

Share/Bookmark

Enterprise Architect CASE Tool για Ανάπτυξη Λογισμικού

Μετά από μία συζήτηση που είχα σήμερα στο MediaCamp2 με τον συνάδελφο Γιώργο Κασσελάκη σχετικά με το Enterprise Architect της Sparx Systems, ήθελα να μοιραστώ μαζί σας την χρήση αυτού του εργαλείου.

Το ανακάλυψα φέτος για μία εργασία Τεχνολογίας Λογισμικού στο αντίστοιχο πρόγραμμα του μεταπτυχιακού μου και μπορώ να πώ ότι ήταν πολύ καλή λύση για όσα θέλαμε να κάνουμε, ανακαλύπτωντας σε κάθε βήμα πόσες περισσότερες δυνατότητες έχει από όσες το θέλαμε για τις ανάγκες της εργασίας μας. To Enterprise Architect είναι μία ολοκληρωμένη σουιτα από CASE functionality. Case tools είναι κατά βάση τα εργαλεία που βοηθούν την διαδικασία ανάπτυξης λογισμικού καθόλες τις φάσεις ανάπτυξης, από Requirements Engineering μέχρι τελικό deployment modeling, εξοπλισμένο με πλήρες tracing από τα requirements μέχρι την υλοποίηση.

Είναι χτισμένο πάνω στο 2.1 specification της UML αλλά δεν περιορίζεται μέχρι εκεί. Περιέχει extensions για modeling domain όπως για παράδειγμα, modeling επιχειρησιακών διαδικασιών μέσω workflows κτλ.

Υποστηρίζει τα παρακάτω διαγράμματα:

Structural Diagrams:
• Class
• Object
• Composite
• Package
• Component
• Deployment
Behavioral Diagrams:
• Use Case
• Communication
• Sequence
• Interaction Overview
• Activity
• State
• Timing
Extended:
• Analysis (simple activity)
• Custom (for requirements, change, UI)

Επίσης έχει ένα αρκετά εύχρηστο κομμάτι για Versioning που πιστεύουμε ότι καλύπτει και τις πιο απαιτητικές ανάγκες. Στην εργασία μας, εμείς, είχαμε στήσει SVN version control (υποστηρίζει και SCC) όπου ενώ ο κάθε ένας μας είχε το βασικό αρχείο του project, υπήρχε εκ των έσω επικοινωνία με το server κομμάτι, πραγματοποιώντας τα commit και τα update under the hood. Το κομμάτι του versioning ήταν πολύ σημαντικό για εμάς και μας διευκόλυνε άπειρα. Το EA παράγει και αντιστρέφει (reverse engineer) κώδικα από τις γλώσσες: C++, C#, Java, Delphi, VB.Net, Visual Basic, ActionScript, PHP and Python. Η δική μας προσέγγιση ήταν με ASP.NET και C# και από την έρευνα που κάναμε, το αποτέλεσμα που είδαμε στο generation ήταν ότι ήταν το καλύτερο από πλευράς παραγωγής κώδικα (πράγμα που επιβεβαίωσαν και άλλοι, πιο έμπειροι από εμάς, στον χώρο). Βέβαια για να μπορέσει ο κώδικας να είναι όσο ποιο πλήρης γίνεται απαιτήται εξαντλητική συμπλήρωση απαραίτητων πεδίων (π.χ., παράμετροι, τιμές, τύποι δεδομένων, …)

Ένα πολύ σημαντικό addon (που εμείς δεν χρησιμοποιήσαμε, αλλά με την πρώτη ευκαιρία θα το αγοράσω για προσωπική χρήση) ήταν το MDG Integration, μία καταπληκτική δυνατότητα σύνδεσης του IDE (Visual Studio ή Eclipse) με το EA. Με αυτό, χωρίς να ξέρω πολλά, υπάρχουν δυνατότητες, για Model Driven Architectures, style transformations, Real Time execution με ταυτόχρονο reflection στα UML μοντέλα. Αλλαγές στον κώδικα ή στα σχήματα γίνονται αυτόματα sychronize και πάρα πολλά άλλα, που καλώ όποιον έχει πληροφορίες να τις μοιραστεί μαζί μας.

Το καλύτερο από όλα είναι ότι το Enterprise Architect Professional Edition κοστίζει 200$ και αν πάρετε το academic version (με έπίδειξη φοιτητικής ταυτότητας ή κάτι άλλο που να πιστοποιεί ότι είστε φοιτητής από Πανεπιστήμιο) η τιμή πέφτει στα 105$ που είναι πραγματικά απίστευτο για ένα τέτοιο εργαλείο.

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

Share/Bookmark

MediaCamp2 Day 1

Πάρα πολύ ωραία, σήμερα, η πρώτη μέρα στο MediaCamp2 (μία φοβερή πρωτοβουλία που φέρνει κοντά και ενώνει όσους ασχολούμαστε με τεχνολογία, από όποια φιλοσοφία και αν έχουμε υιοθετήσει). Ο χώρος είναι ένα από τα πιο ευχάριστα και φωτεινά μέρη που έχω δει (Microsoft Innovation Center), που ευγενικά παραχώρησε η MS Hellas. 14032009011

Μοιραστήκαμε ιδέες και ενδιαφέροντα τόσο μέσω ομιλιών όσο και στα μικρά πηγαδάκια που σχηματίζονταν ανά τους ορόφους. Προσωπικά παρακολούθησα ομιλίες σχετικά με Drupal όπου ακολούθησε και ωραία συζήτηση για διάφορα Web Frameworks, για code conventions, Windows Mobile Development, WPF, Expression Design, Expression Blend, ASP.NET και την εισαγωγή σε αυτή τη νέα στροφή στο development που “ακούει” στον όρο Cloud Computing, μέσω της νέας οικογένειας υπηρεσιών της Microsoft (Windows Azure realm ;) ).

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

 

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

Share/Bookmark
Posted by Aggelos Mpimpoudis | 3 comment(s)
Filed under:
More Posts Next page »