Επαναχρησιμοποίηση
Διομήδης Σπινέλλης
Τμήμα Διοικητικής Επιστήμης και Τεχνολογίας
Οικονομικό Πανεπιστήμιο Αθηνών
dds@aueb.gr
Τρόποι επαναχρησιμοποίησης
Διακρίνουμε τις παρακάτω κατηγορίες επαναχρησιμοποίησης (reuse)
κατά την ανάπτυξη λογισμικού:
Πλεονεκτήματα επαναχρησιμοποίησης
- Αυξημένη αξιοπιστία
- Λιγότεροι κίνδυνοι στη διεργασία ανάπτυξης
- Αποτελεσματική εκμετάλλευση των ειδικών
- Συμβατότητα με πρότυπα
- Ταχύτητα ανάπτυξης
Προβλήματα επαναχρησιμοποίησης
Υποστήριξη από εργαλεία
Παράδειγμα λάθους που εμφανίζεται κατά τη μεταγλώττιση προγράμματος
C++ με τη χρήση της βιβλιοθήκης STL κάτω από GNU C++ compiler:
c:\gcc\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\..\..\..\..\include\g++-3\stl_
iterator.h: In method `class ostream_iterator<pair<const basic_string<char,strin
g_char_traits<char>,__default_alloc_template<false,0> >,int> > & ostream_iterato
r<pair<const basic_string<char,string_char_traits<char>,__default_alloc_template
<false,0> >,int> >::operator =(const pair<const basic_string<char,string_char_tr
aits<char>,__default_alloc_template<false,0> >,int> &)':
c:\gcc\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\..\..\..\..\include\g++-3\stl_
algobase.h:129: instantiated from `__copy<_Rb_tree_iterator<pair<const basic_s
tring<char,string_char_traits<char>,__default_alloc_template<false,0> >,int>,pai
r<const basic_string<char,string_char_traits<char>,__default_alloc_template<fals
e,0> >,int> &,pair<const basic_string<char,string_char_traits<char>,__default_al
loc_template<false,0> >,int> *>, ostream_iterator<pair<const basic_string<char,s
tring_char_traits<char>,__default_alloc_template<false,0> >,int> >, ptrdiff_t>(_
Rb_tree_iterator<pair<const basic_string<char,string_char_traits<char>,__default
_alloc_template<false,0> >,int>,pair<const basic_string<char,string_char_traits<
char>,__default_alloc_template<false,0> >,int> &,pair<const basic_string<char,st
ring_char_traits<char>,__default_alloc_template<false,0> >,int> *>, _Rb_tree_ite
rator<pair<const basic_string<char,string_char_traits<char>,__default_alloc_temp
late<false,0> >,int>,pair<const basic_string<char,string_char_traits<char>,__def
ault_alloc_template<false,0> >,int> &,pair<const basic_string<char,string_char_t
raits<char>,__default_alloc_template<false,0> >,int> *>, ostream_iterator<pair<c
onst basic_string<char,string_char_traits<char>,__default_alloc_template<false,0
> >,int> >, input_iterator_tag, ptrdiff_t *)'
c:\gcc\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\..\..\..\..\include\g++-3\stl_
algobase.h:161: instantiated from `__copy_dispatch<_Rb_tree_iterator<pair<cons
t basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> >
,int>,pair<const basic_string<char,string_char_traits<char>,__default_alloc_temp
late<false,0> >,int> &,pair<const basic_string<char,string_char_traits<char>,__d
efault_alloc_template<false,0> >,int> *>,ostream_iterator<pair<const basic_strin
g<char,string_char_traits<char>,__default_alloc_template<false,0> >,int> >,__fal
se_type>::copy(_Rb_tree_iterator<pair<const basic_string<char,string_char_traits
<char>,__default_alloc_template<false,0> >,int>,pair<const basic_string<char,str
ing_char_traits<char>,__default_alloc_template<false,0> >,int> &,pair<const basi
c_string<char,string_char_traits<char>,__default_alloc_template<false,0> >,int>
*>, _Rb_tree_iterator<pair<const basic_string<char,string_char_traits<char>,__de
fault_alloc_template<false,0> >,int>,pair<const basic_string<char,string_char_tr
aits<char>,__default_alloc_template<false,0> >,int> &,pair<const basic_string<ch
ar,string_char_traits<char>,__default_alloc_template<false,0> >,int> *>, ostream
_iterator<pair<const basic_string<char,string_char_traits<char>,__default_alloc_
template<false,0> >,int> >)'
c:\gcc\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\..\..\..\..\include\g++-3\stl_
algobase.h:188: instantiated from `copy<_Rb_tree_iterator<pair<const basic_str
ing<char,string_char_traits<char>,__default_alloc_template<false,0> >,int>,pair<
const basic_string<char,string_char_traits<char>,__default_alloc_template<false,
0> >,int> &,pair<const basic_string<char,string_char_traits<char>,__default_allo
c_template<false,0> >,int> *>, ostream_iterator<pair<const basic_string<char,str
ing_char_traits<char>,__default_alloc_template<false,0> >,int> > >(_Rb_tree_iter
ator<pair<const basic_string<char,string_char_traits<char>,__default_alloc_templ
ate<false,0> >,int>,pair<const basic_string<char,string_char_traits<char>,__defa
ult_alloc_template<false,0> >,int> &,pair<const basic_string<char,string_char_tr
aits<char>,__default_alloc_template<false,0> >,int> *>, _Rb_tree_iterator<pair<c
onst basic_string<char,string_char_traits<char>,__default_alloc_template<false,0
> >,int>,pair<const basic_string<char,string_char_traits<char>,__default_alloc_t
emplate<false,0> >,int> &,pair<const basic_string<char,string_char_traits<char>,
__default_alloc_template<false,0> >,int> *>, ostream_iterator<pair<const basic_s
tring<char,string_char_traits<char>,__default_alloc_template<false,0> >,int> >)'
t.cpp:21: instantiated from here
c:\gcc\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\..\..\..\..\include\g++-3\stl_
iterator.h:890: no match for `ostream & << const pair<const basic_string<char,st
ring_char_traits<char>,__default_alloc_template<false,0> >,int> &'
c:\gcc\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\..\..\..\..\include\g++-3\iost
ream.h:77: candidates are: class ostream & ostream::operator <<(char)
c:\gcc\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\..\..\..\..\include\g++-3\iost
ream.h:78: class ostream & ostream::operator <<(unsigned char)
c:\gcc\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\..\..\..\..\include\g++-3\iost
ream.h:79: class ostream & ostream::operator <<(signed char)
(Ακολουθούν άλλες 10 γραμμές)
Παράδειγμα λάθους που εμφανίζεται κατά τη μεταγλώττιση προγράμματος
C++ με τη χρήση της βιβλιοθήκης STL κάτω από Microsoft C/C++ compiler:
t.cpp(24) : see reference to function template instantiation 'class std:
:basic_ostream<char,struct std::char_traits<char> > &__cdecl std::operator <<(cl
ass std::basic_ostream<char,struct std::char_traits<char> > &,const char *)' bei
ng compiled
C:\PROGRA~1\MICROS~4\VC98\INCLUDE\iterator(203) : error C2679: binary '<<' : no
operator defined which takes a right-hand operand of type 'const struct std::pai
r<class std::basic_string<char,struct std::char_traits<char>,class std::allocato
r<char> > const ,int>' (or there is no acceptable conversion)
C:\PROGRA~1\MICROS~4\VC98\INCLUDE\iterator(203) : while compiling class-
template member function 'class std::ostream_iterator<struct std::pair<class std
::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > c
onst ,int>,char,struct std::char_traits<char> > &__thiscall std::ostream_iterato
r<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,cl
ass std::allocator<char> > const ,int>,char,struct std::char_traits<char> >::ope
rator =(const struct std::pair<class std::basic_string<char,struct std::char_tra
its<char>,class std::allocator<char> > const ,int> &)'
Πρότυπα σχέδια
Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that
problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.
-- Christopher Alexander et al. A Pattern Language
Τα πρότυπα σχέδια μας επιτρέπουν τη
- σύλληψη,
- τεκμηρίωση,
- οργάνωση και
- διάχυση
υπάρχουσας σχεδιαστικής γνώσης.
Σε αντίθεση με αλγορίθμους και δομές δεδομένων τα στοιχεία που περιγράφουν
δε χρησιμοποιούνται αυτούσια αλλά περιγράφουν πως θα υλοποιηθεί το σχέδιο
του έργου.
Επίσης, τα πρότυπα σχέδια περιγράφονται με τέτοιο τρόπο έτσι ώστε να
μπορούν να συνδυάζονται μεταξύ τους.
Κάθε περιγραφή ενός σχεδίου περιλαμβάνει:
- το όνομά του
- τη δομή του σε UML
- την κατηγοριοποίησή του σε μια από τις κατηγορίες:
- δημιουργίας
- συμπεριφοράς
- δομής
- περιγραφή των περιπτώσεων χρήσης του
- περιγραφή των συμμετεχόντων
- περιγραφή πως το σχέδιο υποστηρίζει τους στόχους του
- παραδείγματα και οδηγίες χρήσης του.
Παράδειγμα προτύπου σχεδίου
Το παρακάτω κείμενο (Σπινέλλης και Ράπτης 2000)
περιγράφει με τη μορφή ενός προτύπου σχεδίου τη σύνδεση εξαρτημάτων:
Component Composition - Structural
Intent
The component composition pattern identifies the primary methods of
encapsulated component composition and integration.
Motivation
Encapsulated components do not operate in a vacuum.
They are composed to create more powerful components and integrated
within an object-based system to provide specialised services.
Moreover, composition of encapsulated components with component glue
can be used to provide
efficient access to off-line data,
graphical user interfaces,
and a multitude of other component-based services.
As an example a spelling checker can be easily constructed by composing
the translate, sort, unique, and common
components, while the gluing of a editbox and listbox components
can be used to provide a GUI front end.
Applicability
Many of the problems solved under the Unix programming environment using shell
programming constructs and pipelines can be transformed to component
composition structures.
Of particular relevance are sequences of filter type components,
where each one receives a data stream, performs some operations on it,
and forwards it to another filter to perform some other operations.
Examples include pipelines of tools that process
text,
images,
sound, and
object code.
Meunier [13] describes a complete pattern language for a
``Pipes and Filters Architecture'' that can be used as a base to
structure applications.
Structure
Figure 4:
A spell checker with a GUI.
Figure 4 depicts the component interaction diagram of
a filter-based spell checker built from Unix-mined and glue components.
The text to be spell-checked is retrieved from the GUI edit box
using a data source glue component.
It is transformed into a list of words using the translate
component which is a direct equivalent of the Unix tr command.
The word list is then transformed into a sorted list of unique words
using the sort and unique components which correspond to the
Unix sort and uniq commands.
At the same time, the system dictionary and a user dictionary are passed
using appropriate file connectors to the merge component
which merges two sorted streams; the merge component is
a specialisation of sort which provides this functionality.
Finally, the two sorted streams of words to be spelled and
acceptable words are checked by common - derived from the
Unix comm command - which outputs a list of words contained
in the first stream and not contained in the second one.
This stream of misspelled words is sent using the ListBoxSink
glue component to a GUI list box.
It is important to note that the integration of GUI elements
using the same component object paradigm and the merging of two
data streams could not be implemented using the standard Unix
linear pipeline system.
Participants
The components composed are object instances of either active process
components that are connected to existing data sources and sinks,
or connector and glue components
(pipes and environment interfacing classes) that provide such sources and sinks.
Consequences
Using the component composition pattern it is possible to implement
sophisticated component interaction topologies.
In addition, it is possible to package together existing components to
provide new standard and reusable components.
Implementations
The implementation of the composition pattern is independent of the
component-framework used.
Most relevant decisions are taken when implementing the
encapsulation and the glue patterns.
Designs based on the composition pattern should be portable across
different component frameworks.
Προγραμματισμός με εξαρτήματα
Ένα εξάρτημα (component)
είναι μια μονάδα σύνθεσης που ορίζεται μόνο από:
- τη διεπαφή του
- το πλαίσιο εφαρμογής του
Μπορούν να χρησιμοποιηθούν:
Όπως και τα αντικείμενα ένα εξάρτημα:
- περιέχει εσωτερική κατάσταση
- επιτρέπει την πρόσβαση μόνο με καθορισμένες προδιαγραφές
- επιτρέπει την υλοποίηση σε τμήματα.
Τα εξαρτήματα επιπλέον:
- μπορούν να υλοποιηθούν σε διαφορετικές γλώσσες
- έρχονται συχνά συσκευασμένα σε εκτελέσιμη μορφή
- μπορούν να περιέχουν πολλαπλά αντικείμενα
- είναι συνήθως πιο στιβαρά από αντικείμενα
- είναι συχνά διαθέσιμα στην αγορά σε μορφή προϊόντων
Παραδείγματα εξαρτημάτων
Κατηγορίες εξαρτημάτων από το δικτυακό τόπο
http://www.componentsource.com (http://www.componentsource.com):
- 3D Modeling Components
- Accounts Interface Components
- Addressing, Postcode and ZipCode Components
- Artificial Intelligence Components
- Audio, MIDI and Sound Components
- Barcode Components
- Biometrics and Authentication Components
- Business Rules Components
- Button and Cursor Design Components
- CAD Components
- Calendar and Scheduling Components
- Charting and Graphing Components
- Code Components
- Component Development and Design
- Configuration and Initialization Components
- Credit Card Authorization Components
- Data Compression Components
- Data Conversion Components
- Data Entry Components
- Data Entry Verification Components
- Data Mining Components
- Data Storage Components
- Database Connectivity Components
- Database Management Components
- Database Reporting
- Debugging and Testing Components
- Deduplication and Data Cleansing Components
- Device Driver Components
- Diagramming Components
- DirectX Components
- Distributed Component Management
- eCommerce Components
- Email Components
- Encryption Components
- Explorer Components
- Facsimile Components
- File Handling Components
- File Upload Components
- Financial Components
- Find and Replace Components
- Function and Source Libraries
- Grid Components
- Imaging Components
- Instrumentation Components
- Internet Communication Components
- Localization Components
- Manufacturing Components
- Mapping and GIS Components
- Math and Stats Components
- Message Queuing Components
- Multimedia Components
- Network Administration Components
- Network Communication Components
- On-Line Analytical Processing Components
- Print and Preview Components
- Product Suites
- Reporting Components
- Resizing Components
- Search Components
- Security and Administration Components
- Serial Communication Components
- Software Licensing Components
- Software Upgrade Components
- Source Code Generators
- Speech Recognition Components
- Spelling Components
- Spreadsheet Components
- SQL Components
- Telephony Components
- Text Components
- Toolbar Components
- Training Courses
- Treeview and List Components
- User Interface Collections
- User Interface Components
- VBA and Scripting Components
- Version Control Components
- Web Site Components
- Windows API Components
- Windows Registry Components
- Wireless, Handheld and Mobile Components
- XML Components
Πλαίσια εφαρμογών
Ένα πλαίσιο εφαρμογής:
- επιτρέπει τη γρήγορη υλοποίηση προκαθορισμένων εφαρμογών
- περιέχει έτοιμη λειτουργικότητα που υπάρχει κοινή ανάμεσα σε εφαρμογές
- μας οδηγεί για να προσθέσουμε την πρόσθετη λειτουργικότητα που απαιτείται
Για παράδειγμα ένα πλαίσιο για εφαρμογές που περιλαμβάνουν γραφική
διεπαφή με το χρήστη ορίζεται ως έτοιμο πλαίσιο με βάση το σχέδιο:
μοντέλο, εικόνα, ελεγκτής (model view controller (MVC)).
Μελέτη περίπτωσης: Java Beans
Η τεχνολογία JavaBeans επιτρέπει την υλοποίηση και χρήση εξαρτημάτων
με οπτική παράσταση στο περιβάλλον της γλώσσας Java.
Οι βασικές αρχές της τεχνολογίας είναι οι παρακάτω:
- Εργαλεία προγραμματισμού μπορούν να δουν τα χαρακτηριστικά ενός
bean με τη διαδικασία ενδοσκόπησης (introspection).
Αυτή η διαδικασία μπορεί να γίνει
- Κάθε bean έχει ένα σύνολο από
ιδιότητες (properties) που καθορίζουν την εμφάνιση
και συμπεριφορά του.
Τα εργαλεία προγραμματισμού ανακαλύπτουν τις ιδιότητες του κάθε
bean και επιτρέπουν την αλλαγή τους.
- Κάθε bean μπορεί να παραμετροποιηθεί (μέσω των ιδιοτήτων του)
κατά τη διάρκεια της υλοποίησης της εφαρμογής που το χρησιμοποιεί
με τη χρήση ενός διορθωτή ιδιοτήτων ή ενός bean customiser.
- Τα bean χρησιμοποιούν
γεγονότα (events) για να επικοινωνήσουν με άλλα
bean.
Κάθε bean που ενδιαφέρεται να λαμβάνει κάποιο γεγονός πρέπει να
καταχωρίσει το ενδιαφέρον του με το αντίστοιχο bean που το στέλνει.
Τα εργαλεία προγραμματισμού μπορούν να βρουν από ένα bean το
σύνολο των γεγονότων που στέλνει και ενδιαφέρεται να λαμβάνει.
- Με τη χρήση τεχνολογίας διατήρησης (persistance)
κάθε bean αποθηκεύει και ανακτά την κατάστασή του όπως αυτή έχει
προγραμματιστεί κατά την υλοποίηση της εφαρμογής.
- Οι μέθοδοι που υποστηρίζει κάθε bean είναι οι δημόσιες
μέθοδοι της αντίστοιχης κλάσης της Java
Εμφάνιση ενός bean στο περιβάλλον εργασίας και αλλαγή των ιδιοτήτων
του (εικόνα από το δικτυακό τόπο της Sun).
Περιέχοντες και επαναλήπτες στην STL
Η πρότυπη βιβλιοθήκη της C++ περιέχει ένα σύνολο από
αλγορίθμους που χρησιμοποιούνται με τη χρήση ενός
επαναλήπτη (iterator)
πάνω σε έναν
περιέχοντα (container).
Οι λειτουργίες αυτές αποτελούν τη βιβλιοθήκη με το όνομα
Standard Template Library (STL).
Η STL ορίζει μια σειρά από περιέχοντες (containers) όπως την ουρά, τη στοίβα,
την απεικόνιση και τον πίνακα.
Πάνω στους περιέχοντες αυτούς επιτρέπει την εκτέλεση αλγορίθμων,
όπως την εύρεση ενός στοιχείου, η ένωση δύο περιεχόντων, η
ταξινόμηση, κ.λπ.
Στην STL
ορίζονται οι παρακάτω πρότυποι (ως προς τα στοιχεία που περιέχουν)
περιέχοντες:
- list
- διπλά συνδεδεμένη λίστα
- queue
- ουρά
- deque
- ουρά με πρόσβαση και στις δύο άκρες
- map
- απεικόνιση (π.χ. από συμβολοσειρές σε ακέραιους)
- set
- απεικόνιση με μοναδικά στοιχεία στο πεδίο τιμών
- stack
- στοίβα
- vector
- πίνακας
Κάθε περιέχων μπορεί να περιλαμβάνει στοιχεία οποιουδήποτε τύπου.
Η πρόσβαση των στοιχείων ενός περιέχοντα από τους αλγορίθμους
γίνεται μέσω επαναληπτών (iterators).
Οι επαναλήπτες - ανάλογα με τη δομή των δεδομένων του περιέχοντα - μπορούν
να επιτρέπουν την παρακάτω ιεραρχία κινήσεων:
- Τυχαία προσπέλαση
- Κίνηση προς τις δύο κατευθύνσεις
- Κίνηση προς τα εμπρός, ή ανάποδη κίνηση
Επίσης, μπορούν να επιτρέπουν την παρακάτω ιεραρχία πρόσβασης στα δεδομένα
που δείχνουν:
- Είσοδο και έξοδο
- Μόνο είσοδο, ή μόνο έξοδο
Η κλάση των επαναληπτών ορίζεται στην επικεφαλίδα iterator.
Μερικές μέθοδοι που ορίζονται σε επαναλήπτες είναι οι παρακάτω:
- advance
- distance
- ==, !=, <, >, >=, <=
- +, -
- ++, --
Για κάθε περιέχοντα ορίζονται μέθοδοι όπως (στην περίπτωση της
διπλής ουράς):
- assign
- ανάθεση τιμής
- at
- αναφορά σε στοιχείο
- back
- το τελευταίο στοιχείο
- begin
- επαναλήπτης που δείχνει στην αρχή της δομής
- clear
- διαγραφή όλων των στοιχείων
- empty
- αληθές αν η δομή είναι άδεια
- end
- επαναλήπτης που δείχνει στο τέλος της δομής
- erase
- διαγραφή σειράς στοιχείων
- front
- το πρώτο στοιχείο
- insert
- προσθήκη στοιχείου
- operator[]
- πρόσβαση σε στοιχείο
- pop_back
- αφαίρεση στοιχείου από το τέλος
- pop_front
- αφαίρεση στοιχείου από την αρχή
- push_back
- προσθήκη στοιχείου στο τέλος
- push_front
- προσθήκη στοιχείου στην αρχή
- rbegin
- ανάστροφος επαναλήπτης που δείχνει στην αρχή της δομής
- rend
- ανάστροφος επαναλήπτης που δείχνει στο τέλος της δομής
- resize
- καθορισμός του αριθμού των στοιχείων
- size
- αριθμός των στοιχείων
- swap
- εναλλαγή δύο στοιχείων μεταξύ τους
Παράδειγμα STL: απεικόνιση
Το παρακάτω παράδειγμα τυπώνει πόσες φορές εμφανίστηκε κάθε λέξη
στην είσοδο του προγράμματος:
#include <map>
#include <iostream>
#include <string>
using namespace std;
typedef map <string, int> smap_t;
int
main()
{
string s;
smap_t m; // Our map
while (!cin.eof()) {
cin >> s;
m[s]++; // Use overloaded [] operator
};
smap_t::iterator i; // Iterator for printing the results
for (i = m.begin(); i != m.end(); i++)
cout << i->first << " " << i->second << endl;
return (0);
}
Πρόσθετες λειτουργίες στην STL
Επικεφαλίδα algorithm
Στην επικεφαλίδα algorithm ορίζονται μέθοδοι που ενεργούν πάνω
σε περιέχοντες:
- adjacent_find
- βρίσκει δύο ίσα στοιχεία σε διπλανές θέσεις
- binary_search
- δυαδική ανίχνευση
- copy
- αντιγραφή περιοχής
- copy_backward
- αντίστροφη αντιγραφή περιοχής
- count
- μέτρημα
- count_if
- μέτρημα υπό συνθήκη
- equal
- σύγκριση περιοχών
- equal_range
- σύγκριση περιοχών με συγκεκριμένη ακρίβεια
- fill
- πλήρωση περιοχής με τιμή
- fill_n
- πλήρωση αριθμού στοιχείων με τιμή
- find
- εύρεση στοιχείου
- find_end
- εύρεση στοιχείου από το τέλος
- find_first_of
- εύρεση στοιχείου ίσου με κάποιο μέλος από σύνολο στοιχείων
- find_if
- εύρεση στοιχείου που να ικανοποιεί συνθήκη
- for_each
- εκτέλεση συνάρτησης για όλα τα στοιχεία σε περιοχή
- generate
- πλήρωση περιοχής με αποτέλεσμα συνάρτησης
- generate_n
- πλήρωση αριθμού στοιχείων με αποτέλεσμα συνάρτησης
- includes
- έλεγχος αν μια περιοχή εμπεριέχει μια άλλη
- inplace_merge
- σύζευξη δεδομένων στον ίδιο περιέχοντα
- iter_swap
- εναλλαγή δύο τιμών
- lexicographical_compare
- σύγκριση δύο περιοχών α, β για α < β
- lower_bound
- εύρεση μιας ελάχιστης τιμής σε περιοχή σε σχέση με μιαν άλλη τιμή
- make_heap
- μετατροπή περιοχής σε
σωρό (heap)
(δυαδικό δένδρο στο οποίο τα παιδιά έχουν
τιμή μικρότερη ή ίση από αυτή των γονέων τους).
- max
- το μέγιστο από δύο στοιχεία
- max_element
- εύρεση του μέγιστου στοιχείου σε περιοχή
- merge
- σύζευξη δύο περιοχών σε τρίτη
- min
- το ελάχιστο από δύο στοιχεία
- min_element
- εύρεση του ελαχίστου στοιχείου σε περιοχή
- mismatch
- εύρεση του πρώτου διαφορετικού στοιχείου ανάμεσα σε δύο περιοχές
- next_permutation
- υπολογισμός της επόμενης μετάθεσης σε μια περιοχή
- nth_element
- θέτει ένα στοιχείο στη θέση που θα έπρεπε να έχει αν η
περιοχή ήταν ταξινομημένη
- partial_sort
- ταξινομεί τα πρώτα στοιχεία μιας περιοχής
- partial_sort_copy
- ταξινομεί τα πρώτα στοιχεία μιας περιοχής σε μιαν άλλη
- partition
-
χωρίζει μια περιοχή στα δύο με βάση μια συνάρτηση και επιστρέφει
το σημείο που είναι ο χωρισμός
- pop_heap
- αφαίρεση στοιχείου από σωρό
- prev_permutation
- υπολογισμός της προηγούμενης μετάθεσης σε μια περιοχή
- push_heap
- προσθήκη στοιχείου από σωρό
- random_shuffle
- ανακατεύει μια περιοχή
- remove
- αφαιρεί στοιχεία ίσα με μια τιμή
- remove_copy
- αφαιρεί στοιχεία ίσα με μια τιμή μεταφέροντας
το αποτέλεσμα σε μιαν άλλη περιοχή
- remove_copy_if
- αφαιρεί στοιχεία για τα οποία μια συνάρτηση είναι
αληθής μεταφέροντας το αποτέλεσμα σε μιαν άλλη περιοχή
- remove_if
- αφαιρεί στοιχεία για τα οποία μια συνάρτηση είναι αληθής
- replace
- αλλάζει τιμή σε στοιχεία ίσα με μια τιμή
- replace_copy
- αλλάζει τιμή σε στοιχεία ίσα με μια τιμή μεταφέροντας
το αποτέλεσμα σε μιαν άλλη περιοχή
- replace_copy_if
- αλλάζει τιμή σε στοιχεία για τα οποία μια συνάρτηση είναι
αληθής μεταφέροντας το αποτέλεσμα σε μιαν άλλη περιοχή
- replace_if
- αλλάζει τιμή σε στοιχεία για τα οποία μια συνάρτηση είναι αληθής
- reverse
- αντιστρέφει τη σειρά σε μια περιοχή
- reverse_copy
- αντιστρέφει τη σειρά σε μια περιοχή
μεταφέροντάς την σε μιαν άλλη περιοχή
- rotate
- περιστρέφει τη σειρά των στοιχείων σε μια περιοχή
- rotate_copy
- περιστρέφει τη σειρά των στοιχείων σε μια περιοχή
μεταφέροντάς την σε μιαν άλλη περιοχή
- search
- εύρεση σειράς στοιχείων σε μια περιοχή ίσης με στοιχεία μιας άλλης
- search_n
- εύρεση σειράς στοιχείων σε μια περιοχή ίσης με αριθμό στοιχείων μιας άλλης
- set_difference
- θέτει μια περιοχή ίση με τη διαφορά των στοιχείων δύο
άλλων περιοχών (διαφορά συνόλων)
- set_intersection
- θέτει μια περιοχή ίση με την τομή των στοιχείων δύο άλλων περιοχών (τομή συνόλων)
- set_symmetric_difference
- θέτει μια περιοχή ίση με τα μη κοινά των στοιχείων δύο άλλων περιοχών
- set_union
- θέτει μια περιοχή ίση με την ένωση των στοιχείων δύο άλλων περιοχών (ένωση συνόλων)
- sort
- ταξινομεί μια περιοχή
- sort_heap
- ταξινομεί έναν σωρό
- stable_partition
-
χωρίζει μια περιοχή στα δύο με βάση μια συνάρτηση και επιστρέφει
το σημείο που είναι ο χωρισμός.
Ο χωρισμός γίνεται χωρίς να αλλάξει η
σχετική σειρά των στοιχείων.
- stable_sort
- ταξινομεί μια περιοχή.
Η ταξινόμηση γίνεται χωρίς να αλλάξει η
σχετική σειρά των στοιχείων που είναι μεταξύ τους ίσα.
- swap
- αντιστρέφει μεταξύ τους δύο στοιχεία
- swap_ranges
- αντιστρέφει μεταξύ τους δύο περιοχές
- transform
- εφαρμόζει έναν τελεστή σε μια περιοχή ή μεταξύ δύο
περιοχών
- unique
- αφαιρεί τα όμοια στοιχεία από μια περιοχή
- unique_copy
- αφαιρεί τα όμοια στοιχεία από μια περιοχή
μεταφέροντάς την σε μιαν άλλη περιοχή
- upper_bound
- εύρεση μιας μέγιστης τιμής σε περιοχή σε σχέση με μια άλλη τιμή
Επικεφαλίδα numeric
Στην επικεφαλίδα algorithm ορίζονται αριθμητικές μέθοδοι που ενεργούν πάνω
σε περιέχοντες:
- accumulate
- υπολογίζει ένα σύνολο πάνω σε μια περιοχή
- adjacent_difference
- υπολογίζει τις διαφορές τιμών μεταξύ στοιχείων
μιας περιοχής
- inner_product
- υπολογίζει ένα εσωτερικό γινόμενο μεταξύ δύο
περιοχών
- partial_sum
- υπολογίζει ένα μερικό άθροισμα τιμών μιας
περιοχής σε μιαν άλλη
Άλλες επικεφαλίδες
Ακόμα στην STL ορίζονται οι παρακάτω επικεφαλίδες:
- utility
- πρότυπη κλάση που ορίζει διάταξη σε ζεύγη τιμών
- functional
- κλάση που επιτρέπει συναρτησιακό προγραμματισμό
- memory
- ορίζει την κλάση allocator η οποία κατανέμει τη μνήμη
σε όλους τους περιέχοντες.
Ο επανακαθορισμός της επιτρέπει την υλοποίηση άλλων στρατηγικών
καταμερισμού και πρόσβασης στη μνήμη.
Κατανεμημένα συστήματα βασισμένα σε εξαρτήματα
Πριν δύο δεκαετίες, η φύση των υπολογιστικών συστημάτων εκφράζονταν με την ύπαρξη ισχυρών κεντρικών υπολογιστικών συστημάτων (mainframes)
στα οποία ήταν εγκατεστημένες εφαρμογές οι οποίες μπορούσαν να προσπελαστούν από τους χρήστες μέσα από τα τερματικά του συστήματος.
Με την εμφάνιση και την ανάπτυξη των προσωπικών υπολογιστών και καθώς οι εφαρμογές άρχισαν να γίνονται ολοένα και πιο μεγάλες και σύνθετες, άρχισαν να μεταμορφώνονται από ενιαία προγράμματα σε κομμάτια ικανά να συνεργάζονται μεταξύ τους.
Στην διάσπαση των εφαρμογών σε περισσότερα από ένα μέρη, συνέβαλλε η ανάπτυξη της αρχιτεκτονικής πελάτη/εξυπηρετητή (client/server)
βάσει της οποίας γινόταν η υλοποίησή τους.
Κατά την αρχιτεκτονική πελάτη/εξυπηρετητή, μία διεργασία καλείται
πελάτης (client process) όταν αιτείται την υλοποίηση κάποιων υπηρεσιών-μεθόδων από μία διεργασία η οποία είναι ικανή να της προσφέρει τις επιθυμητές υπηρεσίες.
Η τελευταία αυτή διεργασία καλείται
διεργασία του εξυπηρετητή (server process).
Αργότερα με την ανάπτυξη των υπολογιστικών δικτύων τα συνθετικά μέρη των εφαρμογών, προκειμένου να υπάρξει καλύτερη και αποτελεσματικότερη εκμετάλλευση των νέων δυνατοτήτων, άρχισαν να διαμοιράζονται στους υπολογιστές του δικτύου.
Με τον τρόπο αυτό αυξανόταν η απόδοση και εκμετάλλευση των πόρων του δικτύου.
Αυτού του είδους οι εφαρμογές ονομάζονται
κατανεμημένες εφαρμογές (distributed applications).
Η δυνατότητα διασύνδεσης, σε δίκτυα, υπολογιστικών συστημάτων διαφορετικής αρχιτεκτονικής είχε σαν αποτέλεσμα την δημιουργία ενός ανομοιογενούς υπολογιστικού περιβάλλοντος.
Θα έπρεπε, λοιπόν, και οι εφαρμογές να μπορέσουν να εξελιχθούν έτσι ώστε να είναι δυνατή η λειτουργία τους σε τέτοια ετερογενή συστήματα υπολογιστών.
Αυτή η εξέλιξη οδήγησε στην εμφάνιση των
ετερογενών κατανεμημένων εφαρμογών (heterogeneous distributed applications).
Τεχνολογίες διαλειτουργικότητας κατανεμημένων εφαρμογών
Τα βασικά στοιχεία που χαρακτηρίζουν ένα σύγχρονο υπολογιστικό περιβάλλον
είναι τα εξής:
- Η χρησιμοποίηση κατανεμημένων εφαρμογών οι οποίες βασίζονται στην τεχνολογία πελάτη/εξυπηρετητή,
- Η λειτουργία των εφαρμογών σε περιβάλλον το οποίο πιθανόν να αποτελείται από υπολογιστικά συστήματα τα οποία να βασίζονται σε διαφορετική τεχνολογία και να λειτουργούν "πάνω" σε διαφορετικά λειτουργικά συστήματα και
- Η χρησιμοποίηση εργαλείων προγραμματισμού (γλώσσες προγραμματισμού) τα οποία βασίζονται στην τεχνολογία του αντικειμένου.
Με βάση τα παραπάνω στοιχεία η χρησιμοποίηση μοντέλων-μεθοδολογιών τα οποία θα διευκολύνουν την λειτουργία των εφαρμογών κάτω από τις συνθήκες ενός ετερογενούς περιβάλλοντος και θα επιτελούν τις λειτουργίες επικοινωνίας με τρόπο τέτοιο έτσι ώστε να είναι διαφανής προς τους τελικούς χρήστες, είναι επιβεβλημένη και η υιοθέτησή τους αποτελεί πλέον ζήτημα για τους οργανισμούς και τις επιχειρήσεις οι οποίες συντηρούν τέτοιου είδους υπολογιστικά συστήματα και δίκτυα.
Τρία είναι τα βασικά μοντέλα των οποίων σκοπός είναι η υλοποίηση των παραπάνω και αυτά είναι:
- Η "CORBA" (Common Object Request Broker Architecture) της Object Management Group (OMG).
- H "COM/DCOM" (Component Object Model / Distributed Component Object Model) της Microsoft.
- Η "Java RMI" (Remote Method Invocation) της Sun.
Και τα τρία αυτά μοντέλα βασίζονται πάνω στις ίδιες αρχές (και οι τρεις τεχνολογίες λειτουργούν βασιζόμενες στην έννοια του αντικειμένου) και εξυπηρετούν τον ίδιο σκοπό. Κάθε ένα από αυτά έχει όμως τις δικές του ιδιαιτερότητες από τις οποίες κρίνονται και επιλέγονται.
OMG CORBA
Η OMG (Object Management Group) αναπτύσσει πρότυπα βασιζόμενη στην τεχνολογία του αντικειμένου.
Σύμφωνα με την αρχιτεκτονική που προτείνεται από την OMG, την OMA (Object Management Architecture), το κάθε κομμάτι λογισμικού παρουσιάζεται σαν αντικείμενο (Object).
Τα διάφορα αντικείμενα επικοινωνούν μεταξύ τους μέσω του ORB (Object Request Broker), ο οποίος αποτελεί το στοιχείο-κλειδί γι' αυτήν την επικοινωνία.
Ο ORB παρέχει τους μηχανισμούς εκείνους μέσω των οποίων τα αντικείμενα κάνουν τις αιτήσεις και συλλέγουν τις αποκρίσεις.
Η CORBA (Common Object Request Broker Architecture) αποτελεί το πρότυπο της OMG για τον ORB.
Κατά την CORBA, ένας πελάτης ο οποίος ζητάει κάποιες υπηρεσίες από κάποιο αντικείμενο, κάνει μία αίτηση (request)
η οποία μεταβιβάζεται στον ORB και ο οποίος είναι στη συνέχεια υπεύθυνος για την προώθηση της αίτησης προς τον κατάλληλο εξυπηρετητή.
Η αίτηση αυτή περιέχει όλες τις απαραίτητες πληροφορίες που απαιτούνται προκειμένου να υλοποιηθεί και αυτές είναι:
- το επιθυμητό αντικείμενο,
- επιθυμητές υπηρεσίες,
- τυχόν παραμέτρους.
Για να είναι κατανοητή όμως η αίτηση θα πρέπει να έχει μία κατάλληλη μορφή και γι'
αυτό το λόγο γίνεται προς τον ORB μέσω διασυνδετών (interfaces: "Dynamic Invocation" και "IDL Stubs").
Για τον ίδιο λόγο η προώθηση της αίτησης προς τον εξυπηρετητή γίνεται μέσω διασυνδετών ("Static IDL Skeleton" και "IDL Skeleton").
Ένας διασυνδέτης αποτελεί μία περιγραφή ενός συνόλου από πιθανές λειτουργίες τις οποίες ένας πελάτης μπορεί να αιτηθεί ενός αντικειμένου.
Ένα αντικείμενο ικανοποιεί έναν διασυνδέτη εάν μπορεί να προσδιοριστεί σαν το αντικείμενο-στόχος (target object) για κάθε δυνατή αίτηση η οποία περιγράφεται από τον διασυνδέτη.
Στο σημείο αυτό δεν θα πρέπει να αγνοήσουμε την ιδιότητα της κληρονομικότητας που χαρακτηρίζει τους διασυνδέτες και η οποία παρέχει τον συνθετικό εκείνο μηχανισμό που επιτρέπει σ' ένα αντικείμενο να υποστηρίζει πολλαπλούς διασυνδέτες.
Οι διασυνδέτες καθορίζονται πλήρως μέσω της OMG IDL (Interface Definition Language).
Η IDL δεν αποτελεί γλώσσα προγραμματισμού, όπως οι γνωστές γλώσσες προγραμματισμού, αλλά μία καθαρά περιγραφική γλώσσα η οποία δεν περιλαμβάνει δομές αλγορίθμων ή μεταβλητές.
Η γραμματική της αποτελεί υποσύνολο της ANSI C++ με πρόσθετες κατασκευές για την υποστήριξη μηχανισμών για την επίκληση απομακρυσμένων λειτουργιών.
Οι πελάτες δεν είναι "γραμμένοι" σε OMG IDL αλλά σε γλώσσα για την οποία έχει προσδιοριστεί η αντιστοιχία της με την OMG IDL.
Microsoft COM/DCOM/COM+
Το δεύτερο μοντέλο βασίζεται και αυτό στην τεχνολογία του αντικειμένου με την έννοια όμως εδώ των αυτόνομων συνθετικών εξαρτημάτων μίας εφαρμογής.
Και εδώ, ο βασικός σκοπός του μοντέλου είναι να καταστήσει δυνατή την επικοινωνία δύο ή περισσοτέρων εφαρμογών ή συνθετικών, ακόμα και στην περίπτωση που αυτά διαφέρουν ως προς την προέλευση, τη γλώσσα προγραμματισμού, τα μηχανήματα στα οποία βρίσκονται και τα λειτουργικά συστήματα κάτω από τα οποία τρέχουν.
Ο "μηχανισμός λειτουργίας του μοντέλου είναι παρόμοιος με αυτόν της CORBA. Βασικό ρόλο παίζουν οι διασυνδέτες τα οποία δεν είναι τίποτα άλλο από ένα σαφές διατυπωμένο "συμβόλαιο" μεταξύ των "κομματιών" λογισμικού, το οποίο περιέχει ένα σύνολο από σχετικές λειτουργίες.
Όταν λέμε ότι ένα αντικείμενο υλοποιεί έναν διασυνδέτη αυτό σημαίνει ότι το αντικείμενο αυτό υλοποιεί κάθε λειτουργία του.
Πως γίνεται, όμως, η διαδικασία της αιτήσεως κάποιων λειτουργιών από έναν πελάτη;
Για να μπορέσει ένας πελάτης να εξυπηρετηθεί από κάποιο αντικείμενο, θα πρέπει η γλώσσα προγραμματισμού, στην οποία είναι υλοποιημένος, να έχει τη δυνατότητα δημιουργίας δεικτών και να καλεί συναρτήσεις μέσω των δεικτών. Θα πρέπει λοιπόν ο πελάτης να έχει τον κατάλληλο δείκτη προς τον επιθυμητό διασυνδέτη τον οποίο περιέχει τις επιθυμητές από τον πελάτη λειτουργίες.
Στην περίπτωση όμως που ο πελάτης δεν έχει τον κατάλληλο δείκτη προς το επιθυμητό διασυνδέτη, τότε απευθύνεται προς την COM δίνοντας σαν στοιχεία την
ταυτότητα της κλάσης του εξυπηρετητή που επιθυμεί ο πελάτης και τον τύπο του,
δηλαδή εάν είναι:
Η COM τότε αναλαμβάνει να βρει τον επιθυμητό εξυπηρετητή και να επιστρέψει στον πελάτη τον επιθυμητό δείκτη.
Όπως έγινε σαφές, ο κάθε πελάτης μπορεί να είναι υλοποιημένος σε οποιαδήποτε γλώσσα προγραμματισμού, αρκεί αυτή να υποστηρίζει την κατασκευή και την χρήση δεικτών. Για τα "interfaces", όμως, υπάρχει και εδώ μία "IDL" (interface Definition Language) η οποία επιτρέπει και βοηθάει τους σχεδιαστές να κατασκευάζουν διασυνδέτες.
Sun Java RMI
Το μοντέλο RMI της Sun, βασίζεται και αυτό στην τεχνολογία του αντικειμένου και είναι σχεδιασμένο για να προάγει την διαλειτουργικότητα μεταξύ αντικειμένων, κατασκευασμένων σε Java, μέσα σε ένα κατανεμημένο και ετερογενές περιβάλλον.
Η τεχνολογία RMI αφορά αποκλειστικά αντικείμενα τα οποία είναι κατασκευασμένα με τη γλώσσα προγραμματισμού Java. Αυτό έχει ως αποτέλεσμα να δίνει την δυνατότητα της πλήρους εκμετάλλευσης των δυνατοτήτων της Java αλλά και το πλεονέκτημα του ομοιογενούς, ως προς τη γλώσσα προγραμματισμού, περιβάλλοντος.
Η αρχιτεκτονική ενός RMI συστήματος ακολουθεί την δομή των στρωμάτων-επιπέδων (layers). Υπάρχουν τρία (συν ένα) επίπεδα:
- Το επίπεδο "Stub/Skeleton".
- Το επίπεδο απομακρυσμένης αναφοράς (Remote Reference).
- Το επίπεδο μεταφοράς (Transport)
Υπάρχει, επίσης, το επίπεδο της Εφαρμογής (Application) το οποίο όμως δεν αποτελεί καθαρό κομμάτι της τεχνολογίας και το οποίο βρίσκεται πάνω απΤ τα υπόλοιπα.
Η διαδικασία επίκλησης κάποιων υπηρεσιών από έναν πελάτη, δεν διαφέρει, ιδιαίτερα, σε σχέση με τις προαναφερθείσες τεχνολογίες. Ένας πελάτης, ο οποίος επιθυμεί την υλοποίηση κάποιων υπηρεσιών, υποβάλλει μία αίτηση προς το RMI-σύστημα. Στην αίτηση αυτή θα πρέπει να αναφέρονται οι κατάλληλες εκείνες πληροφορίες οι οποίες απαιτούνται για την αποστολή της αίτησης προς τον κατάλληλο εξυπηρετητή. Αυτές οι πληροφορίες-παράμετροι είναι: μία αναφορά του επιθυμητού αντικειμένου (object reference), οι επιθυμητές μέθοδοι και οι κατάλληλες παράμετροι για την υλοποίηση των μεθόδων.
Από τη στιγμή που ο πελάτης καταθέσει την αίτησή του, το RMI-σύστημα είναι υπεύθυνο για την ανεύρεση του κατάλληλου εξυπηρετητή, την μεταβίβαση της αιτήσεων και την επιστροφή των αποτελεσμάτων στον πελάτη.
Όμοια με την CORBA και την COM/DCOM, σε ένα RMI-σύστημα, οι πελάτες δεν έρχονται ποτέ σε απευθείας επικοινωνία με τα επιθυμητά αντικείμενα παρά μόνο μέσω των διασυνδετών αυτών των αντικειμένων. Και εδώ ο διασυνδέτης είναι αυτός που περιέχει τις μεθόδους-υπηρεσίες τις οποίες μπορεί να υλοποιήσει το αντικείμενο.
Η επικοινωνία πελάτη-αντικειμένου, σΤ ένα σύστημα RMI, είναι η ίδια ανεξάρτητα με το που βρίσκεται το επιθυμητό αντικείμενο (αν δηλαδή βρίσκεται στην ίδια διεργασία με τον πελάτη, αν βρίσκεται τοπικά ή απομακρυσμένα).
Βιβλιογραφία
- Christopher Alexander,
Sara Ishikawa, Murray Silverstein, Max Jacobson, Ingrid Fiksdahl-King, and
Shlomo Angel.
A Pattern Language.
Oxford University Press, 1977.
- Matthew H. Austern.
Generic Programming and the STL: Using and Extending the C++ Standard
Template Library.
Addison-Wesley, 1998.
- James O. Coplien and
Douglas C. Schmidt.
Pattern Languages of Program Design.
Addison-Wesley, 1995.
- Erich Gamma, Richard
Helm, Ralph Johnson, and John Vlissides.
Design
Patterns: Elements of Reusable Object-Oriented Software.
Addison-Wesley, 1995.
- Institute of Electrical and
Electronics Engineers, Inc., New York, NY, USA.
Information Technology - Software Packages - Quality Requirements and
Testing, 1998.
IEEE Standard 1465-1998 (ISO/IEC 12119:1998).
- Institute of Electrical and
Electronics Engineers, Inc., New York, NY, USA.
Information Technology - Software Life Cycle Processes - Reuse
Processes, 1999.
IEEE Standard 1517-1999.
- Roger S. Pressman.
Software Engineering: A Practitioner's Approach, pages 738–763.
McGraw-Hill, fifth edition, 2000.
European Adaptation. Adapted by Darrel Ince.
- Ian Sommerville.
Software Engineering, pages 306–326.
Addison-Wesley, sixth edition, 2001.
- Diomidis Spinellis
and Konstantinos Raptis.
Component mining: A process and its pattern language ( http://www.spinellis.gr/pubs/jrnl/2000-IST-Components/html/comp.html).
Information and Software Technology, 42(9):609–617, June 2000.
- Diomidis Spinellis.
Explore, excogitate, exploit: Component mining ( http://www.spinellis.gr/pubs/jrnl/1999-Computer-Components/html/comp.html).
IEEE Computer, 32(9):114–116, September 1999.
- Clemens Szyperski.
Component Software: Behind Object-Oriented Programming.
Addison-Wesley, 1998.
Ασκήσεις
- Ερευνήστε το περιβάλλον Windows και τις εφαρμογές που τρέχουν σε αυτό
για παραδείγματα επαναχρησιμοποίησης.
- Εξετάστε τα εξαρτήματα με τις μεγαλύτερες πωλήσεις που
εμφανίζει η εταιρία
Componentsource (http://www.componentsource.com).
Τι συμπεράσματα βγάζετε για το είδος των εφαρμογών που υλοποιούνται,
τα εργαλεία που χρησιμοποιούνται, και τις αντίστοιχες αδυναμίες τους;